mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[1/3] Support isolated containers for parallel packetimpact tests
Summary of the approach: the test runner will set up a few DUTs according to a flag and pass all the test networks to the testbench. The testbench will only reside in a single container. The testbench will put all the test networks into a buffered channel which served as a semaphore and now the user can freely use t.Parallel() in (sub)tests and the true parallelism will be determined by how many DUTs are configured. Creating DUTs on demand is not supported yet, the test author should determine the number of DUTs to be used statically. Specifically in this change: - Don't export any global variables about the test network in testbench. - Sniffer only binds on the local interface because it will be possible to have multiple interfaces to multiple DUTs in a single testbench container. - Migrate existing tests to stop using global variables. PiperOrigin-RevId: 343965962
This commit is contained in:
@@ -17,7 +17,6 @@ package testbench
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -42,7 +41,7 @@ func portFromSockaddr(sa unix.Sockaddr) (uint16, error) {
|
||||
// pickPort makes a new socket and returns the socket FD and port. The domain
|
||||
// should be AF_INET or AF_INET6. The caller must close the FD when done with
|
||||
// the port if there is no error.
|
||||
func pickPort(domain, typ int) (fd int, port uint16, err error) {
|
||||
func (n *DUTTestNet) pickPort(domain, typ int) (fd int, port uint16, err error) {
|
||||
fd, err = unix.Socket(domain, typ, 0)
|
||||
if err != nil {
|
||||
return -1, 0, fmt.Errorf("creating socket: %w", err)
|
||||
@@ -58,11 +57,11 @@ func pickPort(domain, typ int) (fd int, port uint16, err error) {
|
||||
switch domain {
|
||||
case unix.AF_INET:
|
||||
var sa4 unix.SockaddrInet4
|
||||
copy(sa4.Addr[:], net.ParseIP(LocalIPv4).To4())
|
||||
copy(sa4.Addr[:], n.LocalIPv4)
|
||||
sa = &sa4
|
||||
case unix.AF_INET6:
|
||||
sa6 := unix.SockaddrInet6{ZoneId: uint32(LocalInterfaceID)}
|
||||
copy(sa6.Addr[:], net.ParseIP(LocalIPv6).To16())
|
||||
sa6 := unix.SockaddrInet6{ZoneId: n.LocalDevID}
|
||||
copy(sa6.Addr[:], n.LocalIPv6)
|
||||
sa = &sa6
|
||||
default:
|
||||
return -1, 0, fmt.Errorf("invalid domain %d, it should be one of unix.AF_INET or unix.AF_INET6", domain)
|
||||
@@ -117,19 +116,12 @@ type etherState struct {
|
||||
var _ layerState = (*etherState)(nil)
|
||||
|
||||
// newEtherState creates a new etherState.
|
||||
func newEtherState(out, in Ether) (*etherState, error) {
|
||||
lMAC, err := tcpip.ParseMACAddress(LocalMAC)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing local MAC: %q: %w", LocalMAC, err)
|
||||
}
|
||||
|
||||
rMAC, err := tcpip.ParseMACAddress(RemoteMAC)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing remote MAC: %q: %w", RemoteMAC, err)
|
||||
}
|
||||
func (n *DUTTestNet) newEtherState(out, in Ether) (*etherState, error) {
|
||||
lmac := tcpip.LinkAddress(n.LocalMAC)
|
||||
rmac := tcpip.LinkAddress(n.RemoteMAC)
|
||||
s := etherState{
|
||||
out: Ether{SrcAddr: &lMAC, DstAddr: &rMAC},
|
||||
in: Ether{SrcAddr: &rMAC, DstAddr: &lMAC},
|
||||
out: Ether{SrcAddr: &lmac, DstAddr: &rmac},
|
||||
in: Ether{SrcAddr: &rmac, DstAddr: &lmac},
|
||||
}
|
||||
if err := s.out.merge(&out); err != nil {
|
||||
return nil, err
|
||||
@@ -169,9 +161,9 @@ type ipv4State struct {
|
||||
var _ layerState = (*ipv4State)(nil)
|
||||
|
||||
// newIPv4State creates a new ipv4State.
|
||||
func newIPv4State(out, in IPv4) (*ipv4State, error) {
|
||||
lIP := tcpip.Address(net.ParseIP(LocalIPv4).To4())
|
||||
rIP := tcpip.Address(net.ParseIP(RemoteIPv4).To4())
|
||||
func (n *DUTTestNet) newIPv4State(out, in IPv4) (*ipv4State, error) {
|
||||
lIP := tcpip.Address(n.LocalIPv4)
|
||||
rIP := tcpip.Address(n.RemoteIPv4)
|
||||
s := ipv4State{
|
||||
out: IPv4{SrcAddr: &lIP, DstAddr: &rIP},
|
||||
in: IPv4{SrcAddr: &rIP, DstAddr: &lIP},
|
||||
@@ -214,9 +206,9 @@ type ipv6State struct {
|
||||
var _ layerState = (*ipv6State)(nil)
|
||||
|
||||
// newIPv6State creates a new ipv6State.
|
||||
func newIPv6State(out, in IPv6) (*ipv6State, error) {
|
||||
lIP := tcpip.Address(net.ParseIP(LocalIPv6).To16())
|
||||
rIP := tcpip.Address(net.ParseIP(RemoteIPv6).To16())
|
||||
func (n *DUTTestNet) newIPv6State(out, in IPv6) (*ipv6State, error) {
|
||||
lIP := tcpip.Address(n.LocalIPv6)
|
||||
rIP := tcpip.Address(n.RemoteIPv6)
|
||||
s := ipv6State{
|
||||
out: IPv6{SrcAddr: &lIP, DstAddr: &rIP},
|
||||
in: IPv6{SrcAddr: &rIP, DstAddr: &lIP},
|
||||
@@ -272,8 +264,8 @@ func SeqNumValue(v seqnum.Value) *seqnum.Value {
|
||||
}
|
||||
|
||||
// newTCPState creates a new TCPState.
|
||||
func newTCPState(domain int, out, in TCP) (*tcpState, error) {
|
||||
portPickerFD, localPort, err := pickPort(domain, unix.SOCK_STREAM)
|
||||
func (n *DUTTestNet) newTCPState(domain int, out, in TCP) (*tcpState, error) {
|
||||
portPickerFD, localPort, err := n.pickPort(domain, unix.SOCK_STREAM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,8 +368,8 @@ type udpState struct {
|
||||
var _ layerState = (*udpState)(nil)
|
||||
|
||||
// newUDPState creates a new udpState.
|
||||
func newUDPState(domain int, out, in UDP) (*udpState, error) {
|
||||
portPickerFD, localPort, err := pickPort(domain, unix.SOCK_DGRAM)
|
||||
func (n *DUTTestNet) newUDPState(domain int, out, in UDP) (*udpState, error) {
|
||||
portPickerFD, localPort, err := n.pickPort(domain, unix.SOCK_DGRAM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("picking port: %w", err)
|
||||
}
|
||||
@@ -639,26 +631,26 @@ func (conn *Connection) Drain(t *testing.T) {
|
||||
type TCPIPv4 Connection
|
||||
|
||||
// NewTCPIPv4 creates a new TCPIPv4 connection with reasonable defaults.
|
||||
func NewTCPIPv4(t *testing.T, outgoingTCP, incomingTCP TCP) TCPIPv4 {
|
||||
func (n *DUTTestNet) NewTCPIPv4(t *testing.T, outgoingTCP, incomingTCP TCP) TCPIPv4 {
|
||||
t.Helper()
|
||||
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make etherState: %s", err)
|
||||
}
|
||||
ipv4State, err := newIPv4State(IPv4{}, IPv4{})
|
||||
ipv4State, err := n.newIPv4State(IPv4{}, IPv4{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make ipv4State: %s", err)
|
||||
}
|
||||
tcpState, err := newTCPState(unix.AF_INET, outgoingTCP, incomingTCP)
|
||||
tcpState, err := n.newTCPState(unix.AF_INET, outgoingTCP, incomingTCP)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make tcpState: %s", err)
|
||||
}
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
@@ -841,23 +833,23 @@ func (conn *TCPIPv4) Drain(t *testing.T) {
|
||||
type IPv4Conn Connection
|
||||
|
||||
// NewIPv4Conn creates a new IPv4Conn connection with reasonable defaults.
|
||||
func NewIPv4Conn(t *testing.T, outgoingIPv4, incomingIPv4 IPv4) IPv4Conn {
|
||||
func (n *DUTTestNet) NewIPv4Conn(t *testing.T, outgoingIPv4, incomingIPv4 IPv4) IPv4Conn {
|
||||
t.Helper()
|
||||
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make EtherState: %s", err)
|
||||
}
|
||||
ipv4State, err := newIPv4State(outgoingIPv4, incomingIPv4)
|
||||
ipv4State, err := n.newIPv4State(outgoingIPv4, incomingIPv4)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make IPv4State: %s", err)
|
||||
}
|
||||
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
@@ -896,23 +888,23 @@ func (c *IPv4Conn) ExpectFrame(t *testing.T, frame Layers, timeout time.Duration
|
||||
type IPv6Conn Connection
|
||||
|
||||
// NewIPv6Conn creates a new IPv6Conn connection with reasonable defaults.
|
||||
func NewIPv6Conn(t *testing.T, outgoingIPv6, incomingIPv6 IPv6) IPv6Conn {
|
||||
func (n *DUTTestNet) NewIPv6Conn(t *testing.T, outgoingIPv6, incomingIPv6 IPv6) IPv6Conn {
|
||||
t.Helper()
|
||||
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make EtherState: %s", err)
|
||||
}
|
||||
ipv6State, err := newIPv6State(outgoingIPv6, incomingIPv6)
|
||||
ipv6State, err := n.newIPv6State(outgoingIPv6, incomingIPv6)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make IPv6State: %s", err)
|
||||
}
|
||||
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
@@ -951,26 +943,26 @@ func (conn *IPv6Conn) ExpectFrame(t *testing.T, frame Layers, timeout time.Durat
|
||||
type UDPIPv4 Connection
|
||||
|
||||
// NewUDPIPv4 creates a new UDPIPv4 connection with reasonable defaults.
|
||||
func NewUDPIPv4(t *testing.T, outgoingUDP, incomingUDP UDP) UDPIPv4 {
|
||||
func (n *DUTTestNet) NewUDPIPv4(t *testing.T, outgoingUDP, incomingUDP UDP) UDPIPv4 {
|
||||
t.Helper()
|
||||
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make etherState: %s", err)
|
||||
}
|
||||
ipv4State, err := newIPv4State(IPv4{}, IPv4{})
|
||||
ipv4State, err := n.newIPv4State(IPv4{}, IPv4{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make ipv4State: %s", err)
|
||||
}
|
||||
udpState, err := newUDPState(unix.AF_INET, outgoingUDP, incomingUDP)
|
||||
udpState, err := n.newUDPState(unix.AF_INET, outgoingUDP, incomingUDP)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make udpState: %s", err)
|
||||
}
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
@@ -1075,26 +1067,26 @@ func (conn *UDPIPv4) Drain(t *testing.T) {
|
||||
type UDPIPv6 Connection
|
||||
|
||||
// NewUDPIPv6 creates a new UDPIPv6 connection with reasonable defaults.
|
||||
func NewUDPIPv6(t *testing.T, outgoingUDP, incomingUDP UDP) UDPIPv6 {
|
||||
func (n *DUTTestNet) NewUDPIPv6(t *testing.T, outgoingUDP, incomingUDP UDP) UDPIPv6 {
|
||||
t.Helper()
|
||||
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make etherState: %s", err)
|
||||
}
|
||||
ipv6State, err := newIPv6State(IPv6{}, IPv6{})
|
||||
ipv6State, err := n.newIPv6State(IPv6{}, IPv6{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make IPv6State: %s", err)
|
||||
}
|
||||
udpState, err := newUDPState(unix.AF_INET6, outgoingUDP, incomingUDP)
|
||||
udpState, err := n.newUDPState(unix.AF_INET6, outgoingUDP, incomingUDP)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make udpState: %s", err)
|
||||
}
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
@@ -1126,14 +1118,14 @@ func (conn *UDPIPv6) ipv6State(t *testing.T) *ipv6State {
|
||||
}
|
||||
|
||||
// LocalAddr gets the local socket address of this connection.
|
||||
func (conn *UDPIPv6) LocalAddr(t *testing.T) *unix.SockaddrInet6 {
|
||||
func (conn *UDPIPv6) LocalAddr(t *testing.T, zoneID uint32) *unix.SockaddrInet6 {
|
||||
t.Helper()
|
||||
|
||||
sa := &unix.SockaddrInet6{
|
||||
Port: int(*conn.udpState(t).out.SrcPort),
|
||||
// Local address is in perspective to the remote host, so it's scoped to the
|
||||
// ID of the remote interface.
|
||||
ZoneId: uint32(RemoteInterfaceID),
|
||||
ZoneId: zoneID,
|
||||
}
|
||||
copy(sa.Addr[:], *conn.ipv6State(t).out.SrcAddr)
|
||||
return sa
|
||||
@@ -1203,24 +1195,24 @@ func (conn *UDPIPv6) Drain(t *testing.T) {
|
||||
type TCPIPv6 Connection
|
||||
|
||||
// NewTCPIPv6 creates a new TCPIPv6 connection with reasonable defaults.
|
||||
func NewTCPIPv6(t *testing.T, outgoingTCP, incomingTCP TCP) TCPIPv6 {
|
||||
etherState, err := newEtherState(Ether{}, Ether{})
|
||||
func (n *DUTTestNet) NewTCPIPv6(t *testing.T, outgoingTCP, incomingTCP TCP) TCPIPv6 {
|
||||
etherState, err := n.newEtherState(Ether{}, Ether{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make etherState: %s", err)
|
||||
}
|
||||
ipv6State, err := newIPv6State(IPv6{}, IPv6{})
|
||||
ipv6State, err := n.newIPv6State(IPv6{}, IPv6{})
|
||||
if err != nil {
|
||||
t.Fatalf("can't make ipv6State: %s", err)
|
||||
}
|
||||
tcpState, err := newTCPState(unix.AF_INET6, outgoingTCP, incomingTCP)
|
||||
tcpState, err := n.newTCPState(unix.AF_INET6, outgoingTCP, incomingTCP)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make tcpState: %s", err)
|
||||
}
|
||||
injector, err := NewInjector(t)
|
||||
injector, err := n.NewInjector(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make injector: %s", err)
|
||||
}
|
||||
sniffer, err := NewSniffer(t)
|
||||
sniffer, err := n.NewSniffer(t)
|
||||
if err != nil {
|
||||
t.Fatalf("can't make sniffer: %s", err)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,8 @@ package testbench
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -35,18 +34,26 @@ import (
|
||||
type DUT struct {
|
||||
conn *grpc.ClientConn
|
||||
posixServer POSIXClient
|
||||
Net *DUTTestNet
|
||||
}
|
||||
|
||||
// NewDUT creates a new connection with the DUT over gRPC.
|
||||
func NewDUT(t *testing.T) DUT {
|
||||
t.Helper()
|
||||
n := GetDUTTestNet()
|
||||
dut := n.ConnectToDUT(t)
|
||||
t.Cleanup(func() {
|
||||
dut.TearDownConnection()
|
||||
dut.Net.Release()
|
||||
})
|
||||
return dut
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
if err := genPseudoFlags(); err != nil {
|
||||
t.Fatal("generating psuedo flags:", err)
|
||||
}
|
||||
// ConnectToDUT connects to DUT through gRPC.
|
||||
func (n *DUTTestNet) ConnectToDUT(t *testing.T) DUT {
|
||||
t.Helper()
|
||||
|
||||
posixServerAddress := POSIXServerIP + ":" + strconv.Itoa(POSIXServerPort)
|
||||
posixServerAddress := net.JoinHostPort(n.POSIXServerIP.String(), fmt.Sprintf("%d", n.POSIXServerPort))
|
||||
conn, err := grpc.Dial(posixServerAddress, grpc.WithInsecure(), grpc.WithKeepaliveParams(keepalive.ClientParameters{Timeout: RPCKeepalive}))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to grpc.Dial(%s): %s", posixServerAddress, err)
|
||||
@@ -55,11 +62,12 @@ func NewDUT(t *testing.T) DUT {
|
||||
return DUT{
|
||||
conn: conn,
|
||||
posixServer: posixServer,
|
||||
Net: n,
|
||||
}
|
||||
}
|
||||
|
||||
// TearDown closes the underlying connection.
|
||||
func (dut *DUT) TearDown() {
|
||||
// TearDownConnection closes the underlying connection.
|
||||
func (dut *DUT) TearDownConnection() {
|
||||
dut.conn.Close()
|
||||
}
|
||||
|
||||
@@ -132,7 +140,7 @@ func (dut *DUT) CreateBoundSocket(t *testing.T, typ, proto int32, addr net.IP) (
|
||||
fd = dut.Socket(t, unix.AF_INET6, typ, proto)
|
||||
sa := unix.SockaddrInet6{}
|
||||
copy(sa.Addr[:], addr.To16())
|
||||
sa.ZoneId = uint32(RemoteInterfaceID)
|
||||
sa.ZoneId = dut.Net.RemoteDevID
|
||||
dut.Bind(t, fd, &sa)
|
||||
} else {
|
||||
t.Fatalf("invalid IP address: %s", addr)
|
||||
@@ -154,7 +162,7 @@ func (dut *DUT) CreateBoundSocket(t *testing.T, typ, proto int32, addr net.IP) (
|
||||
func (dut *DUT) CreateListener(t *testing.T, typ, proto, backlog int32) (int32, uint16) {
|
||||
t.Helper()
|
||||
|
||||
fd, remotePort := dut.CreateBoundSocket(t, typ, proto, net.ParseIP(RemoteIPv4))
|
||||
fd, remotePort := dut.CreateBoundSocket(t, typ, proto, dut.Net.RemoteIPv4)
|
||||
dut.Listen(t, fd, backlog)
|
||||
return fd, remotePort
|
||||
}
|
||||
@@ -717,9 +725,9 @@ func (dut *DUT) SetSockLingerOption(t *testing.T, sockfd int32, timeout time.Dur
|
||||
dut.SetSockOpt(t, sockfd, unix.SOL_SOCKET, unix.SO_LINGER, buf)
|
||||
}
|
||||
|
||||
// Shutdown calls shutdown on the DUT and causes a fatal test failure if it doesn't
|
||||
// succeed. If more control over the timeout or error handling is needed, use
|
||||
// ShutdownWithErrno.
|
||||
// Shutdown calls shutdown on the DUT and causes a fatal test failure if it
|
||||
// doesn't succeed. If more control over the timeout or error handling is
|
||||
// needed, use ShutdownWithErrno.
|
||||
func (dut *DUT) Shutdown(t *testing.T, fd, how int32) error {
|
||||
t.Helper()
|
||||
|
||||
|
||||
@@ -38,13 +38,27 @@ func htons(x uint16) uint16 {
|
||||
}
|
||||
|
||||
// NewSniffer creates a Sniffer connected to *device.
|
||||
func NewSniffer(t *testing.T) (Sniffer, error) {
|
||||
func (n *DUTTestNet) NewSniffer(t *testing.T) (Sniffer, error) {
|
||||
t.Helper()
|
||||
|
||||
ifInfo, err := net.InterfaceByName(n.LocalDevName)
|
||||
if err != nil {
|
||||
return Sniffer{}, err
|
||||
}
|
||||
|
||||
var haddr [8]byte
|
||||
copy(haddr[:], ifInfo.HardwareAddr)
|
||||
sa := unix.SockaddrLinklayer{
|
||||
Protocol: htons(unix.ETH_P_ALL),
|
||||
Ifindex: ifInfo.Index,
|
||||
}
|
||||
snifferFd, err := unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, int(htons(unix.ETH_P_ALL)))
|
||||
if err != nil {
|
||||
return Sniffer{}, err
|
||||
}
|
||||
if err := unix.Bind(snifferFd, &sa); err != nil {
|
||||
return Sniffer{}, err
|
||||
}
|
||||
if err := unix.SetsockoptInt(snifferFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, 1); err != nil {
|
||||
t.Fatalf("can't set sockopt SO_RCVBUFFORCE to 1: %s", err)
|
||||
}
|
||||
@@ -136,10 +150,10 @@ type Injector struct {
|
||||
}
|
||||
|
||||
// NewInjector creates a new injector on *device.
|
||||
func NewInjector(t *testing.T) (Injector, error) {
|
||||
func (n *DUTTestNet) NewInjector(t *testing.T) (Injector, error) {
|
||||
t.Helper()
|
||||
|
||||
ifInfo, err := net.InterfaceByName(LocalDevice)
|
||||
ifInfo, err := net.InterfaceByName(n.LocalDevName)
|
||||
if err != nil {
|
||||
return Injector{}, err
|
||||
}
|
||||
@@ -147,7 +161,7 @@ func NewInjector(t *testing.T) (Injector, error) {
|
||||
var haddr [8]byte
|
||||
copy(haddr[:], ifInfo.HardwareAddr)
|
||||
sa := unix.SockaddrLinklayer{
|
||||
Protocol: unix.ETH_P_IP,
|
||||
Protocol: htons(unix.ETH_P_IP),
|
||||
Ifindex: ifInfo.Index,
|
||||
Halen: uint8(len(ifInfo.HardwareAddr)),
|
||||
Addr: haddr,
|
||||
|
||||
@@ -31,64 +31,120 @@ import (
|
||||
var (
|
||||
// Native indicates that the test is being run natively.
|
||||
Native = false
|
||||
// LocalDevice is the device that testbench uses to inject traffic.
|
||||
LocalDevice = ""
|
||||
// RemoteDevice is the device name on the DUT, individual tests can
|
||||
// use the name to construct tests.
|
||||
RemoteDevice = ""
|
||||
|
||||
// LocalIPv4 is the local IPv4 address on the test network.
|
||||
LocalIPv4 = ""
|
||||
// RemoteIPv4 is the DUT's IPv4 address on the test network.
|
||||
RemoteIPv4 = ""
|
||||
// IPv4PrefixLength is the network prefix length of the IPv4 test network.
|
||||
IPv4PrefixLength = 0
|
||||
|
||||
// LocalIPv6 is the local IPv6 address on the test network.
|
||||
LocalIPv6 = ""
|
||||
// RemoteIPv6 is the DUT's IPv6 address on the test network.
|
||||
RemoteIPv6 = ""
|
||||
|
||||
// LocalInterfaceID is the ID of the local interface on the test network.
|
||||
LocalInterfaceID uint32
|
||||
// RemoteInterfaceID is the ID of the remote interface on the test network.
|
||||
//
|
||||
// Not using uint32 because package flag does not support uint32.
|
||||
RemoteInterfaceID uint64
|
||||
|
||||
// LocalMAC is the local MAC address on the test network.
|
||||
LocalMAC = ""
|
||||
// RemoteMAC is the DUT's MAC address on the test network.
|
||||
RemoteMAC = ""
|
||||
|
||||
// POSIXServerIP is the POSIX server's IP address on the control network.
|
||||
POSIXServerIP = ""
|
||||
// POSIXServerPort is the UDP port the POSIX server is bound to on the
|
||||
// control network.
|
||||
POSIXServerPort = 40000
|
||||
|
||||
// RPCKeepalive is the gRPC keepalive.
|
||||
RPCKeepalive = 10 * time.Second
|
||||
// RPCTimeout is the gRPC timeout.
|
||||
RPCTimeout = 100 * time.Millisecond
|
||||
|
||||
// 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
|
||||
)
|
||||
|
||||
// RegisterFlags defines flags and associates them with the package-level
|
||||
// DUTTestNet describes the test network setup on dut and how the testbench
|
||||
// should connect with an existing DUT.
|
||||
type DUTTestNet struct {
|
||||
// LocalMAC is the local MAC address on the test network.
|
||||
LocalMAC net.HardwareAddr
|
||||
// RemoteMAC is the DUT's MAC address on the test network.
|
||||
RemoteMAC net.HardwareAddr
|
||||
// LocalIPv4 is the local IPv4 address on the test network.
|
||||
LocalIPv4 net.IP
|
||||
// RemoteIPv4 is the DUT's IPv4 address on the test network.
|
||||
RemoteIPv4 net.IP
|
||||
// IPv4PrefixLength is the network prefix length of the IPv4 test network.
|
||||
IPv4PrefixLength int
|
||||
// LocalIPv6 is the local IPv6 address on the test network.
|
||||
LocalIPv6 net.IP
|
||||
// RemoteIPv6 is the DUT's IPv6 address on the test network.
|
||||
RemoteIPv6 net.IP
|
||||
// LocalDevID is the ID of the local interface on the test network.
|
||||
LocalDevID uint32
|
||||
// RemoteDevID is the ID of the remote interface on the test network.
|
||||
RemoteDevID uint32
|
||||
// LocalDevName is the device that testbench uses to inject traffic.
|
||||
LocalDevName string
|
||||
// RemoteDevName is the device name on the DUT, individual tests can
|
||||
// use the name to construct tests.
|
||||
RemoteDevName string
|
||||
|
||||
// The following two fields on actually on the control network instead
|
||||
// of the test network, including them for convenience.
|
||||
|
||||
// POSIXServerIP is the POSIX server's IP address on the control network.
|
||||
POSIXServerIP net.IP
|
||||
// POSIXServerPort is the UDP port the POSIX server is bound to on the
|
||||
// control network.
|
||||
POSIXServerPort uint16
|
||||
}
|
||||
|
||||
// registerFlags defines flags and associates them with the package-level
|
||||
// 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")
|
||||
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(&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.BoolVar(&Native, "native", Native, "whether the test is running natively")
|
||||
fs.Uint64Var(&RemoteInterfaceID, "remote_interface_id", RemoteInterfaceID, "remote interface ID for test packets")
|
||||
}
|
||||
|
||||
// Initialize initializes the testbench, it parse the flags and sets up the
|
||||
// pool of test networks for testbench's later use.
|
||||
func Initialize(fs *flag.FlagSet) {
|
||||
registerFlags(fs)
|
||||
flag.Parse()
|
||||
if err := genPseudoFlags(); 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.
|
||||
@@ -104,21 +160,20 @@ func genPseudoFlags() error {
|
||||
return fmt.Errorf("parsing devices: %w", err)
|
||||
}
|
||||
|
||||
_, deviceInfo, err := netdevs.FindDeviceByIP(net.ParseIP(LocalIPv4), devs)
|
||||
_, 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
|
||||
localMAC = deviceInfo.MAC.String()
|
||||
localIPv6 = deviceInfo.IPv6Addr.String()
|
||||
localInterfaceID = deviceInfo.ID
|
||||
|
||||
if deviceInfo.IPv4Net != nil {
|
||||
IPv4PrefixLength, _ = deviceInfo.IPv4Net.Mask.Size()
|
||||
ipv4PrefixLength, _ = deviceInfo.IPv4Net.Mask.Size()
|
||||
} else {
|
||||
IPv4PrefixLength, _ = net.ParseIP(LocalIPv4).DefaultMask().Size()
|
||||
ipv4PrefixLength, _ = net.ParseIP(localIPv4).DefaultMask().Size()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -132,3 +187,15 @@ func GenerateRandomPayload(t *testing.T, n int) []byte {
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
// GetDUTTestNet gets a usable DUTTestNet, the function will block until any
|
||||
// becomes available.
|
||||
func GetDUTTestNet() *DUTTestNet {
|
||||
return <-dutTestNets
|
||||
}
|
||||
|
||||
// Release releases the DUTTestNet back to the pool so that some other test
|
||||
// can use.
|
||||
func (n *DUTTestNet) Release() {
|
||||
dutTestNets <- n
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func TestFinWait2Timeout(t *testing.T) {
|
||||
@@ -38,10 +38,9 @@ func TestFinWait2Timeout(t *testing.T) {
|
||||
} {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFd, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFd)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
conn.Connect(t)
|
||||
|
||||
|
||||
@@ -25,15 +25,14 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestICMPv6ParamProblemTest sends a packet with a bad next header. The DUT
|
||||
// should respond with an ICMPv6 Parameter Problem message.
|
||||
func TestICMPv6ParamProblemTest(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
defer conn.Close(t)
|
||||
ipv6 := testbench.IPv6{
|
||||
// 254 is reserved and used for experimentation and testing. This should
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
type fragmentInfo struct {
|
||||
@@ -69,8 +69,7 @@ func TestIPv4FragmentReassembly(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
conn := testbench.NewIPv4Conn(t, testbench.IPv4{}, testbench.IPv4{})
|
||||
conn := dut.Net.NewIPv4Conn(t, testbench.IPv4{}, testbench.IPv4{})
|
||||
defer conn.Close(t)
|
||||
|
||||
data := make([]byte, test.ipPayloadLen)
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func recvTCPSegment(t *testing.T, conn *testbench.TCPIPv4, expect *testbench.TCP, expectPayload *testbench.Payload) (uint16, error) {
|
||||
@@ -67,12 +67,10 @@ func TestIPv4RetransmitIdentificationUniqueness(t *testing.T) {
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFD)
|
||||
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
conn.Connect(t)
|
||||
|
||||
@@ -16,7 +16,6 @@ package ipv6_fragment_icmp_error_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -35,10 +34,10 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func fragmentedICMPEchoRequest(t *testing.T, conn *testbench.Connection, firstPayloadLength uint16, payload []byte, secondFragmentOffset uint16) ([]testbench.Layers, [][]byte) {
|
||||
func fragmentedICMPEchoRequest(t *testing.T, n *testbench.DUTTestNet, conn *testbench.Connection, firstPayloadLength uint16, payload []byte, secondFragmentOffset uint16) ([]testbench.Layers, [][]byte) {
|
||||
t.Helper()
|
||||
|
||||
icmpv6Header := header.ICMPv6(make([]byte, header.ICMPv6EchoMinimumSize))
|
||||
@@ -48,8 +47,8 @@ func fragmentedICMPEchoRequest(t *testing.T, conn *testbench.Connection, firstPa
|
||||
icmpv6Header.SetSequence(0)
|
||||
cksum := header.ICMPv6Checksum(
|
||||
icmpv6Header,
|
||||
tcpip.Address(net.ParseIP(testbench.LocalIPv6).To16()),
|
||||
tcpip.Address(net.ParseIP(testbench.RemoteIPv6).To16()),
|
||||
tcpip.Address(n.LocalIPv6),
|
||||
tcpip.Address(n.RemoteIPv6),
|
||||
buffer.NewVectorisedView(len(payload), []buffer.View{payload}),
|
||||
)
|
||||
icmpv6Header.SetChecksum(cksum)
|
||||
@@ -121,12 +120,11 @@ func TestIPv6ICMPEchoRequestFragmentReassembly(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
ipv6Conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
ipv6Conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := (*testbench.Connection)(&ipv6Conn)
|
||||
defer ipv6Conn.Close(t)
|
||||
|
||||
fragments, _ := fragmentedICMPEchoRequest(t, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
fragments, _ := fragmentedICMPEchoRequest(t, dut.Net, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
|
||||
for _, i := range test.sendFrameOrder {
|
||||
conn.SendFrame(t, fragments[i-1])
|
||||
@@ -223,12 +221,11 @@ func TestIPv6FragmentReassemblyTimeout(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
ipv6Conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
ipv6Conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := (*testbench.Connection)(&ipv6Conn)
|
||||
defer ipv6Conn.Close(t)
|
||||
|
||||
fragments, ipv6Bytes := fragmentedICMPEchoRequest(t, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
fragments, ipv6Bytes := fragmentedICMPEchoRequest(t, dut.Net, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
|
||||
for _, i := range test.sendFrameOrder {
|
||||
conn.SendFrame(t, fragments[i-1])
|
||||
@@ -319,12 +316,11 @@ func TestIPv6FragmentParamProblem(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
ipv6Conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
ipv6Conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := (*testbench.Connection)(&ipv6Conn)
|
||||
defer ipv6Conn.Close(t)
|
||||
|
||||
fragments, ipv6Bytes := fragmentedICMPEchoRequest(t, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
fragments, ipv6Bytes := fragmentedICMPEchoRequest(t, dut.Net, conn, test.firstPayloadLength, test.payload, test.secondFragmentOffset)
|
||||
|
||||
for _, i := range test.sendFrameOrder {
|
||||
conn.SendFrame(t, fragments[i-1])
|
||||
|
||||
@@ -17,7 +17,6 @@ package ipv6_fragment_reassembly_test
|
||||
import (
|
||||
"flag"
|
||||
"math/rand"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
type fragmentInfo struct {
|
||||
@@ -72,12 +71,11 @@ func TestIPv6FragmentReassembly(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
defer conn.Close(t)
|
||||
|
||||
lIP := tcpip.Address(net.ParseIP(testbench.LocalIPv6).To16())
|
||||
rIP := tcpip.Address(net.ParseIP(testbench.RemoteIPv6).To16())
|
||||
lIP := tcpip.Address(dut.Net.LocalIPv6)
|
||||
rIP := tcpip.Address(dut.Net.RemoteIPv6)
|
||||
|
||||
data := make([]byte, test.ipPayloadLen)
|
||||
icmp := header.ICMPv6(data[:header.ICMPv6HeaderSize])
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func mkHopByHopOptionsExtHdr(optType byte) testbench.Layer {
|
||||
@@ -141,8 +141,7 @@ func TestIPv6UnknownOptionAction(t *testing.T) {
|
||||
} {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
ipv6Conn := testbench.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
ipv6Conn := dut.Net.NewIPv6Conn(t, testbench.IPv6{}, testbench.IPv6{})
|
||||
conn := (*testbench.Connection)(&ipv6Conn)
|
||||
defer ipv6Conn.Close(t)
|
||||
|
||||
|
||||
@@ -25,16 +25,15 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestTCPCorkMSS tests for segment coalesce and split as per MSS.
|
||||
func TestTCPCorkMSS(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFD)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
const mss = uint32(header.TCPDefaultMSS)
|
||||
|
||||
@@ -25,17 +25,16 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestTCPHandshakeWindowSize tests if the stack is honoring the window size
|
||||
// communicated during handshake.
|
||||
func TestTCPHandshakeWindowSize(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFD)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
// Start handshake with zero window size.
|
||||
|
||||
@@ -27,12 +27,12 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func createSocket(t *testing.T, dut testbench.DUT) (int32, int32, testbench.TCPIPv4) {
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn.Connect(t)
|
||||
acceptFD, _ := dut.Accept(t, listenFD)
|
||||
return acceptFD, listenFD, conn
|
||||
@@ -41,7 +41,6 @@ func createSocket(t *testing.T, dut testbench.DUT) (int32, int32, testbench.TCPI
|
||||
func closeAll(t *testing.T, dut testbench.DUT, listenFD int32, conn testbench.TCPIPv4) {
|
||||
conn.Close(t)
|
||||
dut.Close(t, listenFD)
|
||||
dut.TearDown()
|
||||
}
|
||||
|
||||
// lingerDuration is the timeout value used with SO_LINGER socket option.
|
||||
@@ -266,5 +265,4 @@ func TestTCPLingerNonEstablished(t *testing.T) {
|
||||
if diff > lingerDuration {
|
||||
t.Errorf("expected close to return within %s, but returned after %s", lingerDuration, diff)
|
||||
}
|
||||
dut.TearDown()
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package tcp_synsent_reset_test
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -28,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestTCPSynSentUnreachable verifies that TCP connections fail immediately when
|
||||
@@ -37,17 +36,16 @@ func init() {
|
||||
func TestTCPSynSentUnreachable(t *testing.T) {
|
||||
// Create the DUT and connection.
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
clientFD, clientPort := dut.CreateBoundSocket(t, unix.SOCK_STREAM|unix.SOCK_NONBLOCK, unix.IPPROTO_TCP, net.ParseIP(testbench.RemoteIPv4))
|
||||
clientFD, clientPort := dut.CreateBoundSocket(t, unix.SOCK_STREAM|unix.SOCK_NONBLOCK, unix.IPPROTO_TCP, dut.Net.RemoteIPv4)
|
||||
port := uint16(9001)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{SrcPort: &port, DstPort: &clientPort}, testbench.TCP{SrcPort: &clientPort, DstPort: &port})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{SrcPort: &port, DstPort: &clientPort}, testbench.TCP{SrcPort: &clientPort, DstPort: &port})
|
||||
defer conn.Close(t)
|
||||
|
||||
// Bring the DUT to SYN-SENT state with a non-blocking connect.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testbench.RPCTimeout)
|
||||
defer cancel()
|
||||
sa := unix.SockaddrInet4{Port: int(port)}
|
||||
copy(sa.Addr[:], net.IP(net.ParseIP(testbench.LocalIPv4)).To4())
|
||||
copy(sa.Addr[:], dut.Net.LocalIPv4)
|
||||
if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != syscall.Errno(unix.EINPROGRESS) {
|
||||
t.Errorf("expected connect to fail with EINPROGRESS, but got %v", err)
|
||||
}
|
||||
@@ -91,9 +89,8 @@ func TestTCPSynSentUnreachable(t *testing.T) {
|
||||
func TestTCPSynSentUnreachable6(t *testing.T) {
|
||||
// Create the DUT and connection.
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
clientFD, clientPort := dut.CreateBoundSocket(t, unix.SOCK_STREAM|unix.SOCK_NONBLOCK, unix.IPPROTO_TCP, net.ParseIP(testbench.RemoteIPv6))
|
||||
conn := testbench.NewTCPIPv6(t, testbench.TCP{DstPort: &clientPort}, testbench.TCP{SrcPort: &clientPort})
|
||||
clientFD, clientPort := dut.CreateBoundSocket(t, unix.SOCK_STREAM|unix.SOCK_NONBLOCK, unix.IPPROTO_TCP, dut.Net.RemoteIPv6)
|
||||
conn := dut.Net.NewTCPIPv6(t, testbench.TCP{DstPort: &clientPort}, testbench.TCP{SrcPort: &clientPort})
|
||||
defer conn.Close(t)
|
||||
|
||||
// Bring the DUT to SYN-SENT state with a non-blocking connect.
|
||||
@@ -101,9 +98,9 @@ func TestTCPSynSentUnreachable6(t *testing.T) {
|
||||
defer cancel()
|
||||
sa := unix.SockaddrInet6{
|
||||
Port: int(conn.SrcPort()),
|
||||
ZoneId: uint32(testbench.RemoteInterfaceID),
|
||||
ZoneId: dut.Net.RemoteDevID,
|
||||
}
|
||||
copy(sa.Addr[:], net.IP(net.ParseIP(testbench.LocalIPv6)).To16())
|
||||
copy(sa.Addr[:], dut.Net.LocalIPv6)
|
||||
if _, err := dut.ConnectWithErrno(ctx, t, clientFD, &sa); err != syscall.Errno(unix.EINPROGRESS) {
|
||||
t.Errorf("expected connect to fail with EINPROGRESS, but got %v", err)
|
||||
}
|
||||
|
||||
@@ -25,14 +25,13 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func TestTcpNoAcceptCloseReset(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFd, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn.Connect(t)
|
||||
defer conn.Close(t)
|
||||
dut.Close(t, listenFd)
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestTCPOutsideTheWindows tests the behavior of the DUT when packets arrive
|
||||
@@ -62,10 +62,9 @@ func TestTCPOutsideTheWindow(t *testing.T) {
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%s%d", tt.description, tt.seqNumOffset), func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFD)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
conn.Connect(t)
|
||||
acceptFD, _ := dut.Accept(t, listenFD)
|
||||
|
||||
@@ -26,15 +26,14 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
func TestPAWSMechanism(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
listenFD, remotePort := dut.CreateListener(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, 1)
|
||||
defer dut.Close(t, listenFD)
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
options := make([]byte, header.TCPOptionTSLength)
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"flag"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
@@ -32,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestQueueReceiveInSynSent tests receive behavior when the TCP state
|
||||
@@ -50,10 +49,9 @@ func TestQueueReceiveInSynSent(t *testing.T) {
|
||||
} {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
|
||||
socket, remotePort := dut.CreateBoundSocket(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, net.ParseIP(testbench.RemoteIPv4))
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
socket, remotePort := dut.CreateBoundSocket(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, dut.Net.RemoteIPv4)
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
sampleData := []byte("Sample Data")
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
@@ -30,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
testbench.RegisterFlags(flag.CommandLine)
|
||||
testbench.Initialize(flag.CommandLine)
|
||||
}
|
||||
|
||||
// TestQueueSendInSynSent tests send behavior when the TCP state
|
||||
@@ -48,10 +47,9 @@ func TestQueueSendInSynSent(t *testing.T) {
|
||||
} {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
dut := testbench.NewDUT(t)
|
||||
defer dut.TearDown()
|
||||
|
||||
socket, remotePort := dut.CreateBoundSocket(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, net.ParseIP(testbench.RemoteIPv4))
|
||||
conn := testbench.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
socket, remotePort := dut.CreateBoundSocket(t, unix.SOCK_STREAM, unix.IPPROTO_TCP, dut.Net.RemoteIPv4)
|
||||
conn := dut.Net.NewTCPIPv4(t, testbench.TCP{DstPort: &remotePort}, testbench.TCP{SrcPort: &remotePort})
|
||||
defer conn.Close(t)
|
||||
|
||||
sampleData := []byte("Sample Data")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user