hs-test: support for multiple workers
Type: test Signed-off-by: Filip Tehlar <ftehlar@cisco.com> Change-Id: Ie90e4b02c268bc3ca40171b03829f5686fb83162
This commit is contained in:

committed by
Florin Coras

parent
47f3527108
commit
608d0069d9
@ -19,6 +19,10 @@ ifeq ($(DEBUG),)
|
||||
DEBUG=false
|
||||
endif
|
||||
|
||||
ifeq ($(CPUS),)
|
||||
CPUS=1
|
||||
endif
|
||||
|
||||
ifeq ($(UBUNTU_CODENAME),)
|
||||
UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=)
|
||||
endif
|
||||
@ -47,6 +51,7 @@ help:
|
||||
@echo " UNCONFIGURE=[true|false] - unconfigure selected test"
|
||||
@echo " DEBUG=[true|false] - attach VPP to GDB"
|
||||
@echo " TEST=[test-name] - specific test to run"
|
||||
@echo " CPUS=[n-cpus] - number of cpus to run with vpp"
|
||||
@echo
|
||||
@echo "List of all tests:"
|
||||
$(call list_tests)
|
||||
@ -64,7 +69,7 @@ build-vpp-debug:
|
||||
.PHONY: test
|
||||
test: .deps.ok .build.vpp
|
||||
@bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
|
||||
--unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST)
|
||||
--unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS)
|
||||
|
||||
build-go:
|
||||
go build ./tools/http_server
|
||||
|
@ -216,16 +216,12 @@ func (c *Container) getEnvVarsAsCliOption() string {
|
||||
return cliOption
|
||||
}
|
||||
|
||||
func (c *Container) newVppInstance(additionalConfig ...Stanza) (*VppInstance, error) {
|
||||
func (c *Container) newVppInstance(cpus []int, additionalConfigs ...Stanza) (*VppInstance, error) {
|
||||
vpp := new(VppInstance)
|
||||
vpp.container = c
|
||||
|
||||
if len(additionalConfig) > 0 {
|
||||
vpp.additionalConfig = additionalConfig[0]
|
||||
}
|
||||
|
||||
vpp.cpus = cpus
|
||||
vpp.additionalConfig = append(vpp.additionalConfig, additionalConfigs...)
|
||||
c.vppInstance = vpp
|
||||
|
||||
return vpp, nil
|
||||
}
|
||||
|
||||
|
69
extras/hs-test/cpu.go
Normal file
69
extras/hs-test/cpu.go
Normal file
@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var CPU_PATH = "/sys/fs/cgroup/cpuset.cpus.effective"
|
||||
|
||||
type CpuContext struct {
|
||||
cpuAllocator *CpuAllocatorT
|
||||
cpus []int
|
||||
}
|
||||
|
||||
func (c *CpuContext) Release() {
|
||||
c.cpuAllocator.cpus = append(c.cpuAllocator.cpus, c.cpus...)
|
||||
c.cpus = c.cpus[:0] // empty the list
|
||||
}
|
||||
|
||||
type CpuAllocatorT struct {
|
||||
cpus []int
|
||||
}
|
||||
|
||||
var cpuAllocator *CpuAllocatorT = nil
|
||||
|
||||
func (c *CpuAllocatorT) Allocate(nCpus int) (*CpuContext, error) {
|
||||
var cpuCtx CpuContext
|
||||
|
||||
if len(c.cpus) < nCpus {
|
||||
return nil, fmt.Errorf("could not allocate %d CPUs; available: %d", nCpus, len(c.cpus))
|
||||
}
|
||||
cpuCtx.cpus = c.cpus[0:nCpus]
|
||||
cpuCtx.cpuAllocator = c
|
||||
c.cpus = c.cpus[nCpus:]
|
||||
return &cpuCtx, nil
|
||||
}
|
||||
|
||||
func (c *CpuAllocatorT) readCpus(fname string) error {
|
||||
var first, last int
|
||||
file, err := os.Open(CPU_PATH)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
sc := bufio.NewScanner(file)
|
||||
sc.Scan()
|
||||
line := sc.Text()
|
||||
_, err = fmt.Sscanf(line, "%d-%d", &first, &last)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := first; i <= last; i++ {
|
||||
c.cpus = append(c.cpus, i)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CpuAllocator() (*CpuAllocatorT, error) {
|
||||
if cpuAllocator == nil {
|
||||
cpuAllocator = new(CpuAllocatorT)
|
||||
err := cpuAllocator.readCpus(CPU_PATH)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cpuAllocator, nil
|
||||
}
|
@ -14,13 +14,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultNetworkNumber int = 1
|
||||
DEFAULT_NETWORK_NUM int = 1
|
||||
)
|
||||
|
||||
var isPersistent = flag.Bool("persist", false, "persists topology config")
|
||||
var isVerbose = flag.Bool("verbose", false, "verbose test output")
|
||||
var isUnconfiguring = flag.Bool("unconfigure", false, "remove topology")
|
||||
var isVppDebug = flag.Bool("debug", false, "attach gdb to vpp")
|
||||
var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
|
||||
|
||||
type HstSuite struct {
|
||||
suite.Suite
|
||||
@ -30,6 +31,29 @@ type HstSuite struct {
|
||||
netInterfaces map[string]*NetInterface
|
||||
addresser *Addresser
|
||||
testIds map[string]string
|
||||
cpuAllocator *CpuAllocatorT
|
||||
cpuContexts []*CpuContext
|
||||
cpuPerVpp int
|
||||
}
|
||||
|
||||
func (s *HstSuite) SetupSuite() {
|
||||
var err error
|
||||
s.cpuAllocator, err = CpuAllocator()
|
||||
if err != nil {
|
||||
s.FailNow("failed to init cpu allocator: %v", err)
|
||||
}
|
||||
s.cpuPerVpp = *nConfiguredCpus
|
||||
}
|
||||
|
||||
func (s *HstSuite) AllocateCpus() []int {
|
||||
cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
|
||||
s.assertNil(err)
|
||||
s.AddCpuContext(cpuCtx)
|
||||
return cpuCtx.cpus
|
||||
}
|
||||
|
||||
func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
|
||||
s.cpuContexts = append(s.cpuContexts, cpuCtx)
|
||||
}
|
||||
|
||||
func (s *HstSuite) TearDownSuite() {
|
||||
@ -40,6 +64,9 @@ func (s *HstSuite) TearDownTest() {
|
||||
if *isPersistent {
|
||||
return
|
||||
}
|
||||
for _, c := range s.cpuContexts {
|
||||
c.Release()
|
||||
}
|
||||
s.resetContainers()
|
||||
s.removeVolumes()
|
||||
}
|
||||
@ -66,7 +93,7 @@ func (s *HstSuite) setupVolumes() {
|
||||
|
||||
func (s *HstSuite) setupContainers() {
|
||||
for _, container := range s.containers {
|
||||
if container.isOptional == false {
|
||||
if !container.isOptional {
|
||||
container.run()
|
||||
}
|
||||
}
|
||||
@ -130,6 +157,12 @@ func (s *HstSuite) skip(args ...any) {
|
||||
s.T().SkipNow()
|
||||
}
|
||||
|
||||
func (s *HstSuite) SkipIfMultiWorker(args ...any) {
|
||||
if *nConfiguredCpus > 1 {
|
||||
s.skip("test case not supported with multiple vpp workers")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HstSuite) resetContainers() {
|
||||
for _, container := range s.containers {
|
||||
container.stop()
|
||||
|
@ -77,7 +77,7 @@ func newNetworkInterface(cfg NetDevConfig, a *Addresser) (*NetInterface, error)
|
||||
var err error
|
||||
newInterface.addresser = a
|
||||
newInterface.name = cfg["name"].(string)
|
||||
newInterface.networkNumber = defaultNetworkNumber
|
||||
newInterface.networkNumber = DEFAULT_NETWORK_NUM
|
||||
|
||||
if interfaceType, ok := cfg["type"]; ok {
|
||||
newInterface.category = interfaceType.(string)
|
||||
|
@ -14,27 +14,25 @@ type NginxSuite struct {
|
||||
}
|
||||
|
||||
func (s *NginxSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.loadNetworkTopology("2taps")
|
||||
|
||||
s.loadContainerTopology("nginxProxyAndServer")
|
||||
}
|
||||
|
||||
func (s *NginxSuite) SetupTest() {
|
||||
s.skipIfUnconfiguring()
|
||||
|
||||
s.setupVolumes()
|
||||
s.setupContainers()
|
||||
s.HstSuite.SetupTest()
|
||||
|
||||
// Setup test conditions
|
||||
var startupConfig Stanza
|
||||
startupConfig.
|
||||
var sessionConfig Stanza
|
||||
sessionConfig.
|
||||
newStanza("session").
|
||||
append("enable").
|
||||
append("use-app-socket-api").close()
|
||||
|
||||
cpus := s.AllocateCpus()
|
||||
// ... for proxy
|
||||
vppProxyContainer := s.getContainerByName(vppProxyContainerName)
|
||||
proxyVpp, _ := vppProxyContainer.newVppInstance(startupConfig)
|
||||
proxyVpp, _ := vppProxyContainer.newVppInstance(cpus, sessionConfig)
|
||||
proxyVpp.start()
|
||||
|
||||
clientInterface := s.netInterfaces[mirroringClientInterfaceName]
|
||||
|
@ -12,25 +12,24 @@ type NoTopoSuite struct {
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.loadNetworkTopology("tap")
|
||||
|
||||
s.loadContainerTopology("single")
|
||||
}
|
||||
|
||||
func (s *NoTopoSuite) SetupTest() {
|
||||
s.skipIfUnconfiguring()
|
||||
s.setupVolumes()
|
||||
s.setupContainers()
|
||||
s.HstSuite.SetupTest()
|
||||
|
||||
// Setup test conditions
|
||||
var startupConfig Stanza
|
||||
startupConfig.
|
||||
var sessionConfig Stanza
|
||||
sessionConfig.
|
||||
newStanza("session").
|
||||
append("enable").
|
||||
append("use-app-socket-api").close()
|
||||
|
||||
cpus := s.AllocateCpus()
|
||||
container := s.getContainerByName(singleTopoContainerVpp)
|
||||
vpp, _ := container.newVppInstance(startupConfig)
|
||||
vpp, _ := container.newVppInstance(cpus, sessionConfig)
|
||||
vpp.start()
|
||||
|
||||
tapInterface := s.netInterfaces[tapInterfaceName]
|
||||
|
@ -11,27 +11,26 @@ type NsSuite struct {
|
||||
}
|
||||
|
||||
func (s *NsSuite) SetupSuite() {
|
||||
s.HstSuite.SetupSuite()
|
||||
s.configureNetworkTopology("ns")
|
||||
|
||||
s.loadContainerTopology("ns")
|
||||
}
|
||||
|
||||
func (s *NsSuite) SetupTest() {
|
||||
s.skipIfUnconfiguring()
|
||||
s.setupVolumes()
|
||||
s.setupContainers()
|
||||
s.HstSuite.SetupTest()
|
||||
|
||||
// Setup test conditions
|
||||
var startupConfig Stanza
|
||||
startupConfig.
|
||||
var sessionConfig Stanza
|
||||
sessionConfig.
|
||||
newStanza("session").
|
||||
append("enable").
|
||||
append("use-app-socket-api").
|
||||
append("evt_qs_memfd_seg").
|
||||
append("event-queue-length 100000").close()
|
||||
|
||||
cpus := s.AllocateCpus()
|
||||
container := s.getContainerByName("vpp")
|
||||
vpp, _ := container.newVppInstance(startupConfig)
|
||||
vpp, _ := container.newVppInstance(cpus, sessionConfig)
|
||||
vpp.start()
|
||||
|
||||
idx, err := vpp.createAfPacket(s.netInterfaces[serverInterface])
|
||||
|
@ -10,6 +10,6 @@ type TapSuite struct {
|
||||
|
||||
func (s *TapSuite) SetupSuite() {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.HstSuite.SetupSuite()
|
||||
s.configureNetworkTopology("tap")
|
||||
}
|
||||
|
@ -16,22 +16,18 @@ type VethsSuite struct {
|
||||
|
||||
func (s *VethsSuite) SetupSuite() {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
s.HstSuite.SetupSuite()
|
||||
s.configureNetworkTopology("2peerVeth")
|
||||
|
||||
s.loadContainerTopology("2peerVeth")
|
||||
}
|
||||
|
||||
func (s *VethsSuite) SetupTest() {
|
||||
s.skipIfUnconfiguring()
|
||||
|
||||
s.setupVolumes()
|
||||
s.setupContainers()
|
||||
s.HstSuite.SetupTest()
|
||||
|
||||
// Setup test conditions
|
||||
|
||||
var startupConfig Stanza
|
||||
startupConfig.
|
||||
var sessionConfig Stanza
|
||||
sessionConfig.
|
||||
newStanza("session").
|
||||
append("enable").
|
||||
append("use-app-socket-api").close()
|
||||
@ -39,7 +35,8 @@ func (s *VethsSuite) SetupTest() {
|
||||
// ... For server
|
||||
serverContainer := s.getContainerByName("server-vpp")
|
||||
|
||||
serverVpp, _ := serverContainer.newVppInstance(startupConfig)
|
||||
cpus := s.AllocateCpus()
|
||||
serverVpp, _ := serverContainer.newVppInstance(cpus, sessionConfig)
|
||||
s.assertNotNil(serverVpp)
|
||||
|
||||
s.setupServerVpp()
|
||||
@ -47,7 +44,8 @@ func (s *VethsSuite) SetupTest() {
|
||||
// ... For client
|
||||
clientContainer := s.getContainerByName("client-vpp")
|
||||
|
||||
clientVpp, _ := clientContainer.newVppInstance(startupConfig)
|
||||
cpus = s.AllocateCpus()
|
||||
clientVpp, _ := clientContainer.newVppInstance(cpus, sessionConfig)
|
||||
s.assertNotNil(clientVpp)
|
||||
|
||||
s.setupClientVpp()
|
||||
@ -67,7 +65,6 @@ func (s *VethsSuite) setupServerVpp() {
|
||||
namespaceSecret := "1"
|
||||
err = serverVpp.addAppNamespace(1, idx, namespaceSecret)
|
||||
s.assertNil(err)
|
||||
|
||||
}
|
||||
|
||||
func (s *VethsSuite) setupClientVpp() {
|
||||
|
@ -38,6 +38,9 @@ case "${i}" in
|
||||
unconfigure_set=1
|
||||
fi
|
||||
;;
|
||||
--cpus=*)
|
||||
args="$args -cpus ${i#*=}"
|
||||
;;
|
||||
--test=*)
|
||||
tc_name="${i#*=}"
|
||||
if [ $tc_name != "all" ]; then
|
||||
|
@ -126,7 +126,7 @@ func startWget(finished chan error, server_ip, port, query, netNs string) {
|
||||
if err != nil {
|
||||
finished <- fmt.Errorf("wget error: '%v\n\n%s'", err, o)
|
||||
return
|
||||
} else if strings.Contains(string(o), "200 OK") == false {
|
||||
} else if !strings.Contains(string(o), "200 OK") {
|
||||
finished <- fmt.Errorf("wget error: response not 200 OK")
|
||||
return
|
||||
}
|
||||
|
@ -72,9 +72,10 @@ const (
|
||||
|
||||
type VppInstance struct {
|
||||
container *Container
|
||||
additionalConfig Stanza
|
||||
additionalConfig []Stanza
|
||||
connection *core.Connection
|
||||
apiChannel api.Channel
|
||||
cpus []int
|
||||
}
|
||||
|
||||
func (vpp *VppInstance) getSuite() *HstSuite {
|
||||
@ -113,7 +114,10 @@ func (vpp *VppInstance) start() error {
|
||||
defaultApiSocketFilePath,
|
||||
defaultLogFilePath,
|
||||
)
|
||||
configContent += vpp.additionalConfig.toString()
|
||||
configContent += vpp.generateCpuConfig()
|
||||
for _, c := range vpp.additionalConfig {
|
||||
configContent += c.toString()
|
||||
}
|
||||
startupFileName := vpp.getEtcDir() + "/startup.conf"
|
||||
vpp.container.createFile(startupFileName, configContent)
|
||||
|
||||
@ -341,3 +345,25 @@ func (vpp *VppInstance) disconnect() {
|
||||
vpp.connection.Disconnect()
|
||||
vpp.apiChannel.Close()
|
||||
}
|
||||
|
||||
func (vpp *VppInstance) generateCpuConfig() string {
|
||||
var c Stanza
|
||||
var s string
|
||||
if len(vpp.cpus) < 1 {
|
||||
return ""
|
||||
}
|
||||
c.newStanza("cpu").
|
||||
append(fmt.Sprintf("main-core %d", vpp.cpus[0]))
|
||||
workers := vpp.cpus[1:]
|
||||
|
||||
if len(workers) > 0 {
|
||||
for i := 0; i < len(workers); i++ {
|
||||
if i != 0 {
|
||||
s = s + ", "
|
||||
}
|
||||
s = s + fmt.Sprintf("%d", workers[i])
|
||||
}
|
||||
c.append(fmt.Sprintf("corelist-workers %s", s))
|
||||
}
|
||||
return c.close().toString()
|
||||
}
|
||||
|
Reference in New Issue
Block a user