Add default TTL test for udp and tcp endpoints

Simplify the retrieval of the default TTL and include multicast flow in
the UDP SetTTL tests.

Add IPv6 protocol coverage for the TCP TTL tests

PiperOrigin-RevId: 417429943
This commit is contained in:
Arthur Sfez
2021-12-20 10:11:07 -08:00
committed by gVisor bot
parent 5baf7212b7
commit ec18c6bcf9
2 changed files with 106 additions and 40 deletions
+81 -10
View File
@@ -3403,33 +3403,104 @@ func TestSendGreaterThanMTU(t *testing.T) {
testBrokenUpWrite(t, c, maxPayload)
}
func TestSetTTL(t *testing.T) {
for _, wantTTL := range []uint8{1, 2, 50, 64, 128, 254, 255} {
t.Run(fmt.Sprintf("TTL:%d", wantTTL), func(t *testing.T) {
func TestDefaultTTL(t *testing.T) {
for _, test := range []struct {
name string
protoNum tcpip.NetworkProtocolNumber
addr tcpip.Address
}{
{"ipv4", ipv4.ProtocolNumber, context.TestAddr},
{"ipv6", ipv6.ProtocolNumber, context.TestV6Addr},
} {
t.Run(fmt.Sprint(test.name), func(t *testing.T) {
c := context.New(t, 65535)
defer c.Cleanup()
var err tcpip.Error
c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &waiter.Queue{})
c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, test.protoNum, &waiter.Queue{})
if err != nil {
t.Fatalf("NewEndpoint failed: %s", err)
}
if err := c.EP.SetSockOptInt(tcpip.TTLOption, int(wantTTL)); err != nil {
t.Fatalf("SetSockOptInt(TTLOption, %d) failed: %s", wantTTL, err)
proto := c.Stack().NetworkProtocolInstance(test.protoNum)
if proto == nil {
t.Fatalf("c.s.NetworkProtocolInstance(flow.netProto()) did not return a protocol")
}
var initialDefaultTTL tcpip.DefaultTTLOption
if err := proto.Option(&initialDefaultTTL); err != nil {
t.Fatalf("proto.Option(&initialDefaultTTL) (%T) failed: %s", initialDefaultTTL, err)
}
{
err := c.EP.Connect(tcpip.FullAddress{Addr: context.TestAddr, Port: context.TestPort})
err := c.EP.Connect(tcpip.FullAddress{Addr: test.addr, Port: context.TestPort})
if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" {
t.Fatalf("c.EP.Connect(...) mismatch (-want +got):\n%s", d)
}
}
// Receive SYN packet.
b := c.GetPacket()
checkTTL := func(ttl uint8) {
if test.protoNum == ipv4.ProtocolNumber {
checker.IPv4(t, c.GetPacket(), checker.TTL(ttl))
} else {
checker.IPv6(t, c.GetV6Packet(), checker.TTL(ttl))
}
}
checker.IPv4(t, b, checker.TTL(wantTTL))
// Receive SYN packet.
checkTTL(uint8(initialDefaultTTL))
newDefaultTTL := tcpip.DefaultTTLOption(initialDefaultTTL + 1)
if err := proto.SetOption(&newDefaultTTL); err != nil {
t.Fatalf("proto.SetOption(&%T(%d))) failed: %s", newDefaultTTL, newDefaultTTL, err)
}
// Receive retransmitted SYN packet.
checkTTL(uint8(newDefaultTTL))
})
}
}
func TestSetTTL(t *testing.T) {
for _, test := range []struct {
name string
protoNum tcpip.NetworkProtocolNumber
addr tcpip.Address
}{
{"ipv4", ipv4.ProtocolNumber, context.TestAddr},
{"ipv6", ipv6.ProtocolNumber, context.TestV6Addr},
} {
t.Run(fmt.Sprint(test.name), func(t *testing.T) {
for _, wantTTL := range []uint8{1, 2, 50, 64, 128, 254, 255} {
t.Run(fmt.Sprintf("TTL:%d", wantTTL), func(t *testing.T) {
c := context.New(t, 65535)
defer c.Cleanup()
var err tcpip.Error
c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, test.protoNum, &waiter.Queue{})
if err != nil {
t.Fatalf("NewEndpoint failed: %s", err)
}
if err := c.EP.SetSockOptInt(tcpip.TTLOption, int(wantTTL)); err != nil {
t.Fatalf("SetSockOptInt(TTLOption, %d) failed: %s", wantTTL, err)
}
{
err := c.EP.Connect(tcpip.FullAddress{Addr: test.addr, Port: context.TestPort})
if d := cmp.Diff(&tcpip.ErrConnectStarted{}, err); d != "" {
t.Fatalf("c.EP.Connect(...) mismatch (-want +got):\n%s", d)
}
}
// Receive SYN packet.
if test.protoNum == ipv4.ProtocolNumber {
checker.IPv4(t, c.GetPacket(), checker.TTL(wantTTL))
} else {
checker.IPv6(t, c.GetV6Packet(), checker.TTL(wantTTL))
}
})
}
})
}
}
+25 -30
View File
@@ -287,6 +287,13 @@ func (flow testFlow) isReverseMulticast() bool {
}
}
func (flow testFlow) ttlOption() tcpip.SockOptInt {
if flow.isMulticast() {
return tcpip.MulticastTTLOption
}
return tcpip.TTLOption
}
type testContext struct {
t *testing.T
linkEP *channel.Endpoint
@@ -1608,48 +1615,35 @@ func (*testInterface) Enabled() bool {
return true
}
func TestTTL(t *testing.T) {
for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6} {
func TestNonMulticastDefaultTTL(t *testing.T) {
for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6} {
t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) {
c := newDualTestContext(t, defaultMTU)
defer c.cleanup()
c.createEndpointForFlow(flow)
const multicastTTL = 42
if err := c.ep.SetSockOptInt(tcpip.MulticastTTLOption, multicastTTL); err != nil {
c.t.Fatalf("SetSockOptInt failed: %s", err)
proto := c.s.NetworkProtocolInstance(flow.netProto())
if proto == nil {
t.Fatalf("c.s.NetworkProtocolInstance(flow.netProto()) did not return a protocol")
}
var wantTTL uint8
if flow.isMulticast() {
wantTTL = multicastTTL
} else {
var p stack.NetworkProtocolFactory
var n tcpip.NetworkProtocolNumber
if flow.isV4() {
p = ipv4.NewProtocol
n = ipv4.ProtocolNumber
} else {
p = ipv6.NewProtocol
n = ipv6.ProtocolNumber
}
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{p},
Clock: &faketime.NullClock{},
})
ep := s.NetworkProtocolInstance(n).NewEndpoint(&testInterface{}, nil)
wantTTL = ep.DefaultTTL()
ep.Close()
var initialDefaultTTL tcpip.DefaultTTLOption
if err := proto.Option(&initialDefaultTTL); err != nil {
t.Fatalf("proto.Option(&initialDefaultTTL) (%T) failed: %s", initialDefaultTTL, err)
}
testWrite(c, flow, checker.TTL(uint8(initialDefaultTTL)))
testWrite(c, flow, checker.TTL(wantTTL))
newDefaultTTL := tcpip.DefaultTTLOption(initialDefaultTTL + 1)
if err := proto.SetOption(&newDefaultTTL); err != nil {
c.t.Fatalf("proto.SetOption(&%T(%d))) failed: %s", newDefaultTTL, newDefaultTTL, err)
}
testWrite(c, flow, checker.TTL(uint8(newDefaultTTL)))
})
}
}
func TestSetTTL(t *testing.T) {
for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6} {
for _, flow := range []testFlow{unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6} {
t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) {
for _, wantTTL := range []uint8{1, 2, 50, 64, 128, 254, 255} {
t.Run(fmt.Sprintf("TTL:%d", wantTTL), func(t *testing.T) {
@@ -1658,8 +1652,9 @@ func TestSetTTL(t *testing.T) {
c.createEndpointForFlow(flow)
if err := c.ep.SetSockOptInt(tcpip.TTLOption, int(wantTTL)); err != nil {
c.t.Fatalf("SetSockOptInt(TTLOption, %d) failed: %s", wantTTL, err)
opt := flow.ttlOption()
if err := c.ep.SetSockOptInt(opt, int(wantTTL)); err != nil {
c.t.Fatalf("SetSockOptInt(%d, %d) failed: %s", opt, wantTTL, err)
}
testWrite(c, flow, checker.TTL(wantTTL))