mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[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:
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
+245
-164
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user