[2/3] Support isolated containers for parallel packetimpact tests

Added a new flag num_duts to the test runner to create multiple DUTs for the
testbench can connect to.

PiperOrigin-RevId: 344195435
This commit is contained in:
Zeling Feng
2020-11-24 23:22:05 -08:00
committed by gVisor bot
parent 99f2d0ea2f
commit d04144fbb7
7 changed files with 279 additions and 247 deletions
+1
View File
@@ -32,6 +32,7 @@ go_library(
deps = [
"//pkg/test/dockerutil",
"//test/packetimpact/netdevs",
"//test/packetimpact/testbench",
"@com_github_docker_docker//api/types/mount:go_default_library",
],
)
+11 -3
View File
@@ -12,10 +12,11 @@ def _packetimpact_test_impl(ctx):
# current user, and no other users will be mapped in that namespace.
# Make sure that everything is readable here.
"find . -type f -or -type d -exec chmod a+rx {} \\;",
"%s %s --testbench_binary %s $@\n" % (
"%s %s --testbench_binary %s --num_duts %d $@\n" % (
test_runner.short_path,
" ".join(ctx.attr.flags),
ctx.files.testbench_binary[0].short_path,
ctx.attr.num_duts,
),
])
ctx.actions.write(bench, bench_content, is_executable = True)
@@ -51,6 +52,10 @@ _packetimpact_test = rule(
mandatory = False,
default = [],
),
"num_duts": attr.int(
mandatory = False,
default = 1,
),
},
test = True,
implementation = _packetimpact_test_impl,
@@ -110,24 +115,27 @@ def packetimpact_netstack_test(
**kwargs
)
def packetimpact_go_test(name, expect_native_failure = False, expect_netstack_failure = False):
def packetimpact_go_test(name, expect_native_failure = False, expect_netstack_failure = False, num_duts = 1):
"""Add packetimpact tests written in go.
Args:
name: name of the test
expect_native_failure: the test must fail natively
expect_netstack_failure: the test must fail for Netstack
num_duts: how many DUTs are needed for the test
"""
testbench_binary = name + "_test"
packetimpact_native_test(
name = name,
expect_failure = expect_native_failure,
testbench_binary = testbench_binary,
num_duts = num_duts,
)
packetimpact_netstack_test(
name = name,
expect_failure = expect_netstack_failure,
testbench_binary = testbench_binary,
num_duts = num_duts,
)
def packetimpact_testbench(name, size = "small", pure = True, **kwargs):
@@ -153,7 +161,7 @@ def packetimpact_testbench(name, size = "small", pure = True, **kwargs):
PacketimpactTestInfo = provider(
doc = "Provide information for packetimpact tests",
fields = ["name", "expect_netstack_failure"],
fields = ["name", "expect_netstack_failure", "num_duts"],
)
ALL_TESTS = [
File diff suppressed because it is too large Load Diff
-1
View File
@@ -21,7 +21,6 @@ go_library(
"//pkg/tcpip/header",
"//pkg/tcpip/seqnum",
"//pkg/usermem",
"//test/packetimpact/netdevs",
"//test/packetimpact/proto:posix_server_go_proto",
"@com_github_google_go_cmp//cmp:go_default_library",
"@com_github_google_go_cmp//cmp/cmpopts:go_default_library",
+20 -78
View File
@@ -17,15 +17,13 @@
package testbench
import (
"encoding/json"
"flag"
"fmt"
"math/rand"
"net"
"os/exec"
"testing"
"time"
"gvisor.dev/gvisor/test/packetimpact/netdevs"
)
var (
@@ -36,25 +34,12 @@ var (
// RPCTimeout is the gRPC timeout.
RPCTimeout = 100 * time.Millisecond
// dutTestNetsJSON is the json string that describes all the test networks to
// duts available to use.
dutTestNetsJSON string
// dutTestNets is the pool among which the testbench can choose a DUT to work
// with.
dutTestNets chan *DUTTestNet
// TODO(zeling): Remove the following variables once the test runner side is
// ready.
localDevice = ""
remoteDevice = ""
localIPv4 = ""
remoteIPv4 = ""
ipv4PrefixLength = 0
localIPv6 = ""
remoteIPv6 = ""
localInterfaceID uint32
remoteInterfaceID uint64
localMAC = ""
remoteMAC = ""
posixServerIP = ""
posixServerPort = 40000
)
// DUTTestNet describes the test network setup on dut and how the testbench
@@ -98,19 +83,10 @@ type DUTTestNet struct {
// exported variables above. It should be called by tests in their init
// functions.
func registerFlags(fs *flag.FlagSet) {
fs.StringVar(&posixServerIP, "posix_server_ip", posixServerIP, "ip address to listen to for UDP commands")
fs.IntVar(&posixServerPort, "posix_server_port", posixServerPort, "port to listen to for UDP commands")
fs.StringVar(&localIPv4, "local_ipv4", localIPv4, "local IPv4 address for test packets")
fs.StringVar(&remoteIPv4, "remote_ipv4", remoteIPv4, "remote IPv4 address for test packets")
fs.StringVar(&remoteIPv6, "remote_ipv6", remoteIPv6, "remote IPv6 address for test packets")
fs.StringVar(&remoteMAC, "remote_mac", remoteMAC, "remote mac address for test packets")
fs.StringVar(&localDevice, "local_device", localDevice, "local device to inject traffic")
fs.StringVar(&remoteDevice, "remote_device", remoteDevice, "remote device on the DUT")
fs.Uint64Var(&remoteInterfaceID, "remote_interface_id", remoteInterfaceID, "remote interface ID for test packets")
fs.BoolVar(&Native, "native", Native, "whether the test is running natively")
fs.DurationVar(&RPCTimeout, "rpc_timeout", RPCTimeout, "gRPC timeout")
fs.DurationVar(&RPCKeepalive, "rpc_keepalive", RPCKeepalive, "gRPC keepalive")
fs.StringVar(&dutTestNetsJSON, "dut_test_nets_json", dutTestNetsJSON, "path to the dut test nets json file")
}
// Initialize initializes the testbench, it parse the flags and sets up the
@@ -118,61 +94,27 @@ func registerFlags(fs *flag.FlagSet) {
func Initialize(fs *flag.FlagSet) {
registerFlags(fs)
flag.Parse()
if err := genPseudoFlags(); err != nil {
if err := loadDUTTestNets(); err != nil {
panic(err)
}
var dut DUTTestNet
var err error
dut.LocalMAC, err = net.ParseMAC(localMAC)
if err != nil {
panic(err)
}
dut.RemoteMAC, err = net.ParseMAC(remoteMAC)
if err != nil {
panic(err)
}
dut.LocalIPv4 = net.ParseIP(localIPv4).To4()
dut.LocalIPv6 = net.ParseIP(localIPv6).To16()
dut.RemoteIPv4 = net.ParseIP(remoteIPv4).To4()
dut.RemoteIPv6 = net.ParseIP(remoteIPv6).To16()
dut.LocalDevID = uint32(localInterfaceID)
dut.RemoteDevID = uint32(remoteInterfaceID)
dut.LocalDevName = localDevice
dut.RemoteDevName = remoteDevice
dut.POSIXServerIP = net.ParseIP(posixServerIP)
dut.POSIXServerPort = uint16(posixServerPort)
dut.IPv4PrefixLength = ipv4PrefixLength
dutTestNets = make(chan *DUTTestNet, 1)
dutTestNets <- &dut
}
// genPseudoFlags populates flag-like global config based on real flags.
//
// genPseudoFlags must only be called after flag.Parse.
func genPseudoFlags() error {
out, err := exec.Command("ip", "addr", "show").CombinedOutput()
if err != nil {
return fmt.Errorf("listing devices: %q: %w", string(out), err)
// loadDUTTestNets loads available DUT test networks from the json file, it
// must be called after flag.Parse().
func loadDUTTestNets() error {
var parsedTestNets []DUTTestNet
if err := json.Unmarshal([]byte(dutTestNetsJSON), &parsedTestNets); err != nil {
return fmt.Errorf("failed to unmarshal JSON: %w", err)
}
devs, err := netdevs.ParseDevices(string(out))
if err != nil {
return fmt.Errorf("parsing devices: %w", err)
if got, want := len(parsedTestNets), 1; got < want {
return fmt.Errorf("got %d DUTs, the test requires at least %d DUTs", got, want)
}
_, deviceInfo, err := netdevs.FindDeviceByIP(net.ParseIP(localIPv4), devs)
if err != nil {
return fmt.Errorf("can't find deviceInfo: %w", err)
}
localMAC = deviceInfo.MAC.String()
localIPv6 = deviceInfo.IPv6Addr.String()
localInterfaceID = deviceInfo.ID
if deviceInfo.IPv4Net != nil {
ipv4PrefixLength, _ = deviceInfo.IPv4Net.Mask.Size()
} else {
ipv4PrefixLength, _ = net.ParseIP(localIPv4).DefaultMask().Size()
// Using a buffered channel as semaphore
dutTestNets = make(chan *DUTTestNet, len(parsedTestNets))
for i := range parsedTestNets {
parsedTestNets[i].LocalIPv4 = parsedTestNets[i].LocalIPv4.To4()
parsedTestNets[i].RemoteIPv4 = parsedTestNets[i].RemoteIPv4.To4()
dutTestNets <- &parsedTestNets[i]
}
return nil
}
+1
View File
@@ -371,4 +371,5 @@ validate_all_tests()
[packetimpact_go_test(
name = t.name,
expect_netstack_failure = hasattr(t, "expect_netstack_failure"),
num_duts = t.num_duts if hasattr(t, "num_duts") else 1,
) for t in ALL_TESTS]
@@ -44,7 +44,7 @@ func TestUDPRecvMcastBcast(t *testing.T) {
{bound: subnetBcastAddr, to: subnetBcastAddr},
// FIXME(gvisor.dev/issues/4896): Previously by the time subnetBcastAddr is
// FIXME(gvisor.dev/issue/4896): Previously by the time subnetBcastAddr is
// created, IPv4PrefixLength is still 0 because genPseudoFlags is not called
// yet, it was only called in NewDUT, so the test didn't do what the author
// original intended to and becomes failing because we process all flags at