diff --git a/hack/buildenv.sh b/hack/buildenv.sh index 5b33045..e394ccc 100755 --- a/hack/buildenv.sh +++ b/hack/buildenv.sh @@ -41,6 +41,7 @@ else -e E2E_TRACE="${E2E_TRACE:-}" \ -e E2E_DISPATCH_TRACE="${E2E_DISPATCH_TRACE:-}" \ -e E2E_PAUSE_ON_ERROR="${E2E_PAUSE_ON_ERROR:-}" \ + -e E2E_MULTICORE="${E2E_MULTICORE:-}" \ -w /src/vpp \ "${build_image}" \ "$@" diff --git a/hack/e2e.sh b/hack/e2e.sh index 7afe79c..d7de3f8 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -20,6 +20,7 @@ cd "$(dirname "${BASH_SOURCE}")/.." : "${E2E_TRACE:=}" : "${E2E_DISPATCH_TRACE:=}" : "${E2E_PAUSE_ON_ERROR:=}" +: "${E2E_MULTICORE:=}" if grep -q '^gtp ' /proc/modules; then echo >&2 "* Using kernel GTP-U support for IPv4 PGW tests" @@ -31,6 +32,7 @@ fi export UPG_TEST_QUICK="${E2E_QUICK}" export VPP_TRACE="${E2E_TRACE}" export VPP_DISPATCH_TRACE="${E2E_DISPATCH_TRACE}" +export VPP_MULTICORE="${E2E_MULTICORE}" case ${E2E_TARGET} in debug) diff --git a/test/e2e/README.md b/test/e2e/README.md index e7f123b..81e2e7f 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -35,6 +35,7 @@ The make commands accept following variables: * `E2E_TRACE`: enable VPP trace * `E2E_DISPATCH_TRACE`: store the VPP dispatch trace as `dispatch-trace.pcap` in the test dir * `E2E_PAUSE_ON_ERROR`: pause on error for interactive debugging +* `E2E_MULTICORE`: run tests with a single worker core enabled An example with multiple flags: diff --git a/test/e2e/upg_test.go b/test/e2e/upg_test.go index 25d1393..432c59c 100644 --- a/test/e2e/upg_test.go +++ b/test/e2e/upg_test.go @@ -35,6 +35,8 @@ func FailPause(message string, callerSkip ...int) { } } +// Here we select logical CPU cores for parallel Ginkgo nodes starting +// from the least loaded ones. var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { percents, err := cpu.Percent(5*time.Second, true) if err != nil { @@ -57,12 +59,24 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { } return r }, func(data []byte) { - // select 2 cores for the current parallel node numCores := len(data) / 2 - n := (config.GinkgoConfig.ParallelNode - 1) % (numCores / 2) - vpp.Cores = []int{ - int(binary.LittleEndian.Uint16(data[n*4:])), - int(binary.LittleEndian.Uint16(data[n*4+2:])), + var startupCfg vpp.VPPStartupConfig + startupCfg.SetFromEnv() + if startupCfg.Multicore { + // select 2 cores for the current parallel node + // in the multicore mode + n := (config.GinkgoConfig.ParallelNode - 1) % (numCores / 2) + vpp.Cores = []int{ + int(binary.LittleEndian.Uint16(data[n*4:])), + int(binary.LittleEndian.Uint16(data[n*4+2:])), + } + } else { + // select a single core for the current parallel node + // in the single core mode + n := (config.GinkgoConfig.ParallelNode - 1) % numCores + vpp.Cores = []int{ + int(binary.LittleEndian.Uint16(data[n*2:])), + } } fmt.Println("Cores:", vpp.Cores) }) diff --git a/test/e2e/vpp/vpp.go b/test/e2e/vpp/vpp.go index 1d13629..550bf5f 100644 --- a/test/e2e/vpp/vpp.go +++ b/test/e2e/vpp/vpp.go @@ -168,7 +168,9 @@ func (vi *VPPInstance) prepareCommand() (*exec.Cmd, error) { vi.startupCfg.VPPLog = vi.vppFilePath("vpp.log") vi.startupCfg.MainCore = Cores[0] - vi.startupCfg.WorkerCore = Cores[1] + if vi.startupCfg.Multicore { + vi.startupCfg.WorkerCore = Cores[1] + } startupFile, err := vi.writeVPPFile("startup.conf", vi.startupCfg.Get()) if err != nil { @@ -507,15 +509,21 @@ func (vi *VPPInstance) interfaceCmds(nsCfg VPPNetworkNamespace) []string { if mtu == 0 { mtu = DEFAULT_MTU } - placement := "main" - if nsCfg.Placement >= 0 { - placement = fmt.Sprintf("worker %d", nsCfg.Placement) + cmds = append(cmds, + fmt.Sprintf("create host-interface name %s", nsCfg.VPPLinkName)) + + if vi.startupCfg.Multicore { + placement := "main" + if nsCfg.Placement >= 0 { + placement = fmt.Sprintf("worker %d", nsCfg.Placement) + } + cmds = append(cmds, + fmt.Sprintf("set interface rx-placement host-%s %s", nsCfg.VPPLinkName, placement)) } + return append(cmds, - fmt.Sprintf("create host-interface name %s", nsCfg.VPPLinkName), // TODO: add an option for interrupt mode // fmt.Sprintf("set interface rx-mode host-%s interrupt", nsCfg.VPPLinkName), - fmt.Sprintf("set interface rx-placement host-%s %s", nsCfg.VPPLinkName, placement), fmt.Sprintf("set interface mac address host-%s %s", nsCfg.VPPLinkName, nsCfg.VPPMac), fmt.Sprintf("set interface %s table host-%s %d", ipCmd, nsCfg.VPPLinkName, nsCfg.Table), fmt.Sprintf("set interface ip address host-%s %s", nsCfg.VPPLinkName, nsCfg.VPPIP), diff --git a/test/e2e/vpp/vppstartup.go b/test/e2e/vpp/vppstartup.go index df0dfa0..d3036db 100644 --- a/test/e2e/vpp/vppstartup.go +++ b/test/e2e/vpp/vppstartup.go @@ -31,7 +31,11 @@ api-trace { cpu { main-core {{.MainCore}} +{{ if .Multicore }} corelist-workers {{.WorkerCore}} +{{ else }} + workers 0 +{{ end }} } statseg { @@ -80,6 +84,7 @@ type VPPStartupConfig struct { UseGDB bool Trace bool DispatchTrace bool + Multicore bool } func (cfg *VPPStartupConfig) SetFromEnv() { @@ -94,6 +99,7 @@ func (cfg *VPPStartupConfig) SetFromEnv() { cfg.UseGDB = os.Getenv("VPP_NO_GDB") == "" cfg.Trace = os.Getenv("VPP_TRACE") != "" cfg.DispatchTrace = os.Getenv("VPP_DISPATCH_TRACE") != "" + cfg.Multicore = os.Getenv("VPP_MULTICORE") != "" cfg.SetDefaults() }