wgengine/netstack: add tests

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
chaosinthecrd
2026-03-16 17:03:48 +01:00
parent 0a46d61008
commit a529739a29

View File

@@ -453,6 +453,194 @@ func TestShouldProcessInbound(t *testing.T) {
},
want: false,
},
{
name: "udp-on-service-vip-with-listener-ipv4",
pkt: &packet.Parsed{
IPVersion: 4,
IPProto: ipproto.UDP,
Src: netip.MustParseAddrPort("100.101.102.103:1234"),
Dst: netip.MustParseAddrPort("100.100.100.100:8080"),
},
beforeStart: func(i *Impl) {
i.ProcessLocalIPs = false
i.ProcessSubnets = false
},
afterStart: func(i *Impl) {
IPServiceMap := netmap.IPServiceMappings{
serviceIP: "svc:test-service",
}
i.lb.SetIPServiceMappingsForTest(IPServiceMap)
i.atomicIsVIPServiceIPFunc.Store(func(addr netip.Addr) bool {
return addr == serviceIP
})
// Register the service VIP address on the NIC so gVisor can route to it
protocolAddr := tcpip.ProtocolAddress{
Protocol: header.IPv4ProtocolNumber,
AddressWithPrefix: tcpip.AddrFrom4(serviceIP.As4()).WithPrefix(),
}
if err := i.ipstack.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
t.Fatalf("AddProtocolAddress: %v", err)
}
// Create a UDP listener on the service VIP
pc, err := gonet.DialUDP(i.ipstack, &tcpip.FullAddress{
NIC: nicID,
Addr: tcpip.AddrFrom4(serviceIP.As4()),
Port: 8080,
}, nil, header.IPv4ProtocolNumber)
if err != nil {
t.Fatalf("DialUDP: %v", err)
}
t.Cleanup(func() { pc.Close() })
i.atomicIsLocalIPFunc.Store(looksLikeATailscaleSelfAddress)
},
want: true,
},
{
name: "udp-on-service-vip-no-listener-ipv4",
pkt: &packet.Parsed{
IPVersion: 4,
IPProto: ipproto.UDP,
Src: netip.MustParseAddrPort("100.101.102.103:1234"),
Dst: netip.MustParseAddrPort("100.100.100.100:9999"),
},
beforeStart: func(i *Impl) {
i.ProcessLocalIPs = false
i.ProcessSubnets = false
},
afterStart: func(i *Impl) {
IPServiceMap := netmap.IPServiceMappings{
serviceIP: "svc:test-service",
}
i.lb.SetIPServiceMappingsForTest(IPServiceMap)
i.atomicIsVIPServiceIPFunc.Store(func(addr netip.Addr) bool {
return addr == serviceIP
})
i.atomicIsLocalIPFunc.Store(looksLikeATailscaleSelfAddress)
},
want: false,
},
{
name: "udp-on-service-vip-with-listener-ipv6",
pkt: &packet.Parsed{
IPVersion: 6,
IPProto: ipproto.UDP,
Src: netip.MustParseAddrPort("[fd7a:115c:a1e0::1]:1234"),
Dst: netip.MustParseAddrPort("[fd7a:115c:a1e0::53]:8080"),
},
beforeStart: func(i *Impl) {
i.ProcessLocalIPs = false
i.ProcessSubnets = false
},
afterStart: func(i *Impl) {
IPServiceMap := netmap.IPServiceMappings{
serviceIPv6: "svc:test-service",
}
i.lb.SetIPServiceMappingsForTest(IPServiceMap)
i.atomicIsVIPServiceIPFunc.Store(func(addr netip.Addr) bool {
return addr == serviceIPv6
})
protocolAddr := tcpip.ProtocolAddress{
Protocol: header.IPv6ProtocolNumber,
AddressWithPrefix: tcpip.AddrFrom16(serviceIPv6.As16()).WithPrefix(),
}
if err := i.ipstack.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
t.Fatalf("AddProtocolAddress: %v", err)
}
pc, err := gonet.DialUDP(i.ipstack, &tcpip.FullAddress{
NIC: nicID,
Addr: tcpip.AddrFrom16(serviceIPv6.As16()),
Port: 8080,
}, nil, header.IPv6ProtocolNumber)
if err != nil {
t.Fatalf("DialUDP: %v", err)
}
t.Cleanup(func() { pc.Close() })
i.atomicIsLocalIPFunc.Store(looksLikeATailscaleSelfAddress)
},
want: true,
},
{
name: "udp-on-service-vip-no-listener-ipv6",
pkt: &packet.Parsed{
IPVersion: 6,
IPProto: ipproto.UDP,
Src: netip.MustParseAddrPort("[fd7a:115c:a1e0::1]:1234"),
Dst: netip.MustParseAddrPort("[fd7a:115c:a1e0:ffff:ffff:ffff:ffff:fffe]:9999"), // serviceIPv6
},
beforeStart: func(i *Impl) {
i.ProcessLocalIPs = false
i.ProcessSubnets = false
},
afterStart: func(i *Impl) {
IPServiceMap := netmap.IPServiceMappings{
serviceIPv6: "svc:test-service",
}
i.lb.SetIPServiceMappingsForTest(IPServiceMap)
i.atomicIsVIPServiceIPFunc.Store(func(addr netip.Addr) bool {
return addr == serviceIPv6
})
i.atomicIsLocalIPFunc.Store(looksLikeATailscaleSelfAddress)
},
want: false,
},
{
name: "tcp-on-service-vip-with-udp-listener",
pkt: &packet.Parsed{
IPVersion: 4,
IPProto: ipproto.TCP,
Src: netip.MustParseAddrPort("100.101.102.103:1234"),
Dst: netip.MustParseAddrPort("100.100.100.100:8080"), // serviceIP
TCPFlags: packet.TCPSyn,
},
beforeStart: func(i *Impl) {
i.ProcessLocalIPs = false
i.ProcessSubnets = false
},
afterStart: func(i *Impl) {
IPServiceMap := netmap.IPServiceMappings{
serviceIP: "svc:test-service",
}
i.lb.SetIPServiceMappingsForTest(IPServiceMap)
i.atomicIsVIPServiceIPFunc.Store(func(addr netip.Addr) bool {
return addr == serviceIP
})
protocolAddr := tcpip.ProtocolAddress{
Protocol: header.IPv4ProtocolNumber,
AddressWithPrefix: tcpip.AddrFrom4(serviceIP.As4()).WithPrefix(),
}
if err := i.ipstack.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
t.Fatalf("AddProtocolAddress: %v", err)
}
pc, err := gonet.DialUDP(i.ipstack, &tcpip.FullAddress{
NIC: nicID,
Addr: tcpip.AddrFrom4(serviceIP.As4()),
Port: 8080,
}, nil, header.IPv4ProtocolNumber)
if err != nil {
t.Fatalf("DialUDP: %v", err)
}
t.Cleanup(func() { pc.Close() })
i.atomicIsLocalIPFunc.Store(looksLikeATailscaleSelfAddress)
},
want: false,
},
// TODO(andrew): test PeerAPI
// TODO(andrew): test TCP packets without the SYN flag set