Add a flag to tcp_benchmarks that runs the workload over ipv6.

PiperOrigin-RevId: 465404721
This commit is contained in:
Lucas Manning
2022-08-04 14:28:11 -07:00
committed by gVisor bot
parent 23c6100e92
commit 2f34113ec1
3 changed files with 79 additions and 19 deletions
+2
View File
@@ -13,7 +13,9 @@ go_binary(
"//pkg/tcpip/link/qdisc/fifo",
"//pkg/tcpip/network/arp",
"//pkg/tcpip/network/ipv4",
"//pkg/tcpip/network/ipv6",
"//pkg/tcpip/stack",
"//pkg/tcpip/transport/icmp",
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/udp",
"@org_golang_x_sys//unix:go_default_library",
+28 -9
View File
@@ -19,11 +19,15 @@
# Fixed parameters.
iperf_port=45201 # Not likely to be privileged.
proxy_port=44000 # Ditto.
mask=8
client_addr=10.0.0.1
client_proxy_addr=10.0.0.2
server_proxy_addr=10.0.0.3
server_addr=10.0.0.4
mask=8
full_server_addr=${server_addr}:${iperf_port}
full_server_proxy_addr=${server_proxy_addr}:${proxy_port}
iperf_version_arg=
# Defaults; this provides a reasonable approximation of a decent internet link.
# Parameters can be varied independently from this set to see response to
@@ -140,6 +144,16 @@ while [ $# -gt 0 ]; do
--disable-linux-gro)
disable_linux_gro=1
;;
--ipv6)
client_addr=fd::1
client_proxy_addr=fd::2
server_proxy_addr=fd::3
server_addr=fd::4
full_server_addr=[${server_addr}]:${iperf_port}
full_server_proxy_addr=[${server_proxy_addr}]:${proxy_port}
iperf_version_arg=-V
netstack_opts="${netstack_opts} -ipv6"
;;
--num-client-threads)
shift
num_client_threads=$1
@@ -171,6 +185,7 @@ while [ $# -gt 0 ]; do
echo " --num-client-threads number of parallel client threads to run"
echo " --disable-linux-gso disable segmentation offload (TSO, GSO, GRO) in the Linux network stack"
echo " --disable-linux-gro disable GRO in the Linux network stack"
echo " --ipv6 use ipv6 for benchmarks"
echo ""
echo "The output will of the script will be:"
echo " <throughput> <client-cpu-usage> <server-cpu-usage>"
@@ -213,24 +228,24 @@ fi
# Client proxy that will listen on the client's iperf target forward traffic
# using the host networking stack.
client_args="${proxy_binary} -port ${proxy_port} -forward ${server_proxy_addr}:${proxy_port}"
client_args="${proxy_binary} -port ${proxy_port} -forward ${full_server_proxy_addr}"
if ${client}; then
# Client proxy that will listen on the client's iperf target
# and forward traffic using netstack.
client_args="${proxy_binary} ${netstack_opts} -port ${proxy_port} -client \\
-mtu ${mtu} -iface client.0 -addr ${client_proxy_addr} -mask ${mask} \\
-forward ${server_proxy_addr}:${proxy_port} -gso=${gso} -swgso=${swgso}"
-forward ${full_server_proxy_addr} -gso=${gso} -swgso=${swgso}"
fi
# Server proxy that will listen on the proxy port and forward to the server's
# iperf server using the host networking stack.
server_args="${proxy_binary} -port ${proxy_port} -forward ${server_addr}:${iperf_port}"
server_args="${proxy_binary} -port ${proxy_port} -forward ${full_server_addr}"
if ${server}; then
# Server proxy that will listen on the proxy port and forward to the servers'
# iperf server using netstack.
server_args="${proxy_binary} ${netstack_opts} -port ${proxy_port} -server \\
-mtu ${mtu} -iface server.0 -addr ${server_proxy_addr} -mask ${mask} \\
-forward ${server_addr}:${iperf_port} -gso=${gso} -swgso=${swgso}"
-forward ${full_server_addr} -gso=${gso} -swgso=${swgso}"
fi
# Specify loss and duplicate parameters only if they are non-zero
@@ -344,15 +359,19 @@ ${nsjoin_binary} /tmp/server.netns ip link set lo up
ip link set dev client.1 up
ip link set dev server.1 up
${nsjoin_binary} /tmp/client.netns ${client_args} &
client_pid=\$!
${nsjoin_binary} /tmp/server.netns ${server_args} &
server_pid=\$!
# Start the iperf server.
${nsjoin_binary} /tmp/server.netns iperf -p ${iperf_port} -s >&2 &
${nsjoin_binary} /tmp/server.netns iperf ${iperf_version_arg} -p ${iperf_port} -s >&2 &
iperf_pid=\$!
# Give services time to start.
sleep 5
${nsjoin_binary} /tmp/client.netns ${client_args} &
client_pid=\$!
# Show traffic information.
if ! ${client} && ! ${server}; then
${nsjoin_binary} /tmp/client.netns ping -c 100 -i 0.001 -W 1 ${server_addr} >&2 || true
@@ -374,7 +393,7 @@ trap cleanup EXIT
# Run the benchmark, recording the results file.
while ${nsjoin_binary} /tmp/client.netns iperf \\
-p ${proxy_port} -c ${client_addr} -t ${duration} -f m -P ${num_client_threads} 2>&1 \\
${iperf_version_arg} -p ${proxy_port} -c ${client_addr} -t ${duration} -f m -P ${num_client_threads} 2>&1 \\
| tee \$results_file \\
| grep "connect failed" >/dev/null; do
sleep 0.1 # Wait for all services.
+49 -10
View File
@@ -38,7 +38,9 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/link/qdisc/fifo"
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
)
@@ -64,6 +66,7 @@ var (
serverTCPProbeFile = flag.String("server_tcp_probe_file", "", "if specified, installs a tcp probe to dump endpoint state to the specified file.")
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to the specified file.")
memprofile = flag.String("memprofile", "", "write memory profile to the specified file.")
useIpv6 = flag.Bool("ipv6", false, "use ipv6 instead of ipv4.")
)
type impl interface {
@@ -156,26 +159,37 @@ func newNetstackImpl(mode string) (impl, error) {
// Parse details.
parsedAddr := tcpip.Address(net.ParseIP(*addr).To4())
parsedDest := tcpip.Address("") // Filled in below.
parsedMask := tcpip.AddressMask("") // Filled in below.
if *useIpv6 {
parsedAddr = tcpip.Address(net.ParseIP(*addr).To16())
}
parsedDest := tcpip.Address("") // Filled in below.
parsedMask := tcpip.AddressMask("") // Filled in below.
parsedDest6 := tcpip.Address("") // Filled in below.
parsedMask6 := tcpip.AddressMask("") // Filled in below.
switch *mask {
case 8:
parsedDest = tcpip.Address([]byte{parsedAddr[0], 0, 0, 0})
parsedMask = tcpip.AddressMask([]byte{0xff, 0, 0, 0})
parsedDest6 = tcpip.Address(append([]byte{parsedAddr[0]}, make([]byte, 15)...))
parsedMask6 = tcpip.AddressMask(append([]byte{0xff}, make([]byte, 15)...))
case 16:
parsedDest = tcpip.Address([]byte{parsedAddr[0], parsedAddr[1], 0, 0})
parsedMask = tcpip.AddressMask([]byte{0xff, 0xff, 0, 0})
parsedDest6 = tcpip.Address(append([]byte{parsedAddr[0], parsedAddr[1]}, make([]byte, 14)...))
parsedMask6 = tcpip.AddressMask(append([]byte{0xff, 0xff}, make([]byte, 14)...))
case 24:
parsedDest = tcpip.Address([]byte{parsedAddr[0], parsedAddr[1], parsedAddr[2], 0})
parsedMask = tcpip.AddressMask([]byte{0xff, 0xff, 0xff, 0})
parsedDest6 = tcpip.Address(append([]byte{parsedAddr[0], parsedAddr[1], parsedAddr[2]}, make([]byte, 13)...))
parsedMask6 = tcpip.AddressMask(append([]byte{0xff, 0xff, 0xff}, make([]byte, 13)...))
default:
// This is just laziness; we don't expect a different mask.
return nil, fmt.Errorf("mask %d not supported", mask)
}
// Create a new network stack.
netProtos := []stack.NetworkProtocolFactory{ipv4.NewProtocol, arp.NewProtocol}
transProtos := []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol}
netProtos := []stack.NetworkProtocolFactory{ipv6.NewProtocol, ipv4.NewProtocol, arp.NewProtocol}
transProtos := []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol4, icmp.NewProtocol6}
s := stack.New(stack.Options{
NetworkProtocols: netProtos,
TransportProtocols: transProtos,
@@ -210,22 +224,35 @@ func newNetstackImpl(mode string) (impl, error) {
if err := s.CreateNICWithOptions(nicID, ep, opts); err != nil {
return nil, fmt.Errorf("error creating NIC %q: %v", *iface, err)
}
proto := ipv4.ProtocolNumber
if *useIpv6 {
proto = ipv6.ProtocolNumber
}
protocolAddr := tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
Protocol: proto,
AddressWithPrefix: parsedAddr.WithPrefix(),
}
if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
return nil, fmt.Errorf("error adding IP address %+v to %q: %s", protocolAddr, *iface, err)
}
subnet, err := tcpip.NewSubnet(parsedDest, parsedMask)
subnet4, err := tcpip.NewSubnet(parsedDest, parsedMask)
if err != nil {
return nil, fmt.Errorf("tcpip.Subnet(%s, %s): %s", parsedDest, parsedMask, err)
}
subnet6, err := tcpip.NewSubnet(parsedDest6, parsedMask6)
if err != nil {
return nil, fmt.Errorf("tcpip.Subnet(%s, %s): %s", parsedDest, parsedMask, err)
}
// Add default route; we only support
s.SetRouteTable([]tcpip.Route{
{
Destination: subnet,
Destination: subnet4,
NIC: nicID,
},
{
Destination: subnet6,
NIC: nicID,
},
})
@@ -281,12 +308,20 @@ func (n netstackImpl) dial(address string) (net.Conn, error) {
if err != nil {
return nil, err
}
hostAddr := net.ParseIP(host).To4()
if *useIpv6 {
hostAddr = net.ParseIP(host).To16()
}
addr := tcpip.FullAddress{
NIC: nicID,
Addr: tcpip.Address(net.ParseIP(host).To4()),
Addr: tcpip.Address(hostAddr),
Port: uint16(portNumber),
}
conn, err := gonet.DialTCP(n.s, addr, ipv4.ProtocolNumber)
proto := ipv4.ProtocolNumber
if *useIpv6 {
proto = ipv6.ProtocolNumber
}
conn, err := gonet.DialTCP(n.s, addr, proto)
if err != nil {
return nil, err
}
@@ -298,7 +333,11 @@ func (n netstackImpl) listen(port int) (net.Listener, error) {
NIC: nicID,
Port: uint16(port),
}
listener, err := gonet.ListenTCP(n.s, addr, ipv4.ProtocolNumber)
proto := ipv4.ProtocolNumber
if *useIpv6 {
proto = ipv6.ProtocolNumber
}
listener, err := gonet.ListenTCP(n.s, addr, proto)
if err != nil {
return nil, err
}