diff --git a/pkg/tcpip/stack/route.go b/pkg/tcpip/stack/route.go index 9b921eaf4..9755362af 100644 --- a/pkg/tcpip/stack/route.go +++ b/pkg/tcpip/stack/route.go @@ -101,11 +101,6 @@ func (r *Route) Loop() PacketLooping { return r.routeInfo.Loop } -// OutgoingNIC returns the route's outgoing NIC. -func (r *Route) OutgoingNIC() tcpip.NICID { - return r.outgoingNIC.id -} - // RouteInfo contains all of Route's exported fields. // // +stateify savable diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go index 16bb05119..0ed358e51 100644 --- a/pkg/tcpip/stack/stack_test.go +++ b/pkg/tcpip/stack/stack_test.go @@ -841,11 +841,11 @@ func testRoute(t *testing.T, s *stack.Stack, nic tcpip.NICID, srcAddr, dstAddr, defer r.Release() if r.LocalAddress() != expectedSrcAddr { - t.Fatalf("got Route.LocalAddress() = %s, want = %s", r.LocalAddress(), expectedSrcAddr) + t.Fatalf("got Route.LocalAddress() = %s, want = %s", expectedSrcAddr, r.LocalAddress()) } if r.RemoteAddress() != dstAddr { - t.Fatalf("got Route.RemoteAddress() = %s, want = %s", r.RemoteAddress(), dstAddr) + t.Fatalf("got Route.RemoteAddress() = %s, want = %s", dstAddr, r.RemoteAddress()) } } @@ -5461,207 +5461,3 @@ func TestStaticGetLinkAddress(t *testing.T) { }) } } - -// TODO(b/221146133): Test with: -// - Multiple NICs -// - Gateway first route tables -// - IPv6 -// - Set local address -// - Set NIC -func TestFindRoute(t *testing.T) { - // Just use a consistent prefix length throughout tests for simplicity. - const prefixLen = 24 - - type nic struct { - id tcpip.NICID - addresses []string - } - type route struct { - gateway string - subnet string - nic tcpip.NICID - } - type query struct { - name string - remote string - wantID tcpip.NICID - wantLocal string - wantNextHop string - wantErr bool - } - stacks := []struct { - name string - nics []nic - routes []route - queries []query - }{ - { - name: "one NIC, multiple addresses, partially overlapping addresses", - nics: []nic{{id: 1, addresses: []string{"169.254.9.1", "169.254.169.1"}}}, - routes: []route{ - {gateway: "1.1.1.1", subnet: "0.0.0.0/0", nic: 1}, - {gateway: "1.1.1.1", subnet: "169.254.169.0/25", nic: 1}, - }, - queries: []query{ - { - name: "match default only", - remote: "2.2.2.2", - wantID: 1, - wantLocal: "169.254.9.1", - wantNextHop: "1.1.1.1", - }, - { - name: "match both, but prefer non-default", - remote: "169.254.169.2", - wantID: 1, - wantLocal: "169.254.169.1", - wantNextHop: "1.1.1.1", - }, - }, - }, - { - name: "one NIC, multiple addresses, addresses swapped", - nics: []nic{{id: 1, addresses: []string{"192.168.2.1", "192.168.1.1"}}}, - routes: []route{ - {gateway: "192.168.2.22", subnet: "192.168.2.0/24", nic: 1}, - {gateway: "192.168.1.11", subnet: "0.0.0.0/0", nic: 1}, - }, - queries: []query{ - { - name: "match default only", - remote: "1.1.1.1", - wantID: 1, - wantLocal: "192.168.2.1", - wantNextHop: "192.168.1.11", - }, - { - name: "match both, but prefer non-default", - remote: "192.168.2.2", - wantID: 1, - wantLocal: "192.168.2.1", - wantNextHop: "192.168.2.22", - }, - }, - }, - { - name: "one NIC, multiple addresses, gateway last", - nics: []nic{{id: 1, addresses: []string{"192.168.1.1", "192.168.2.1"}}}, - routes: []route{ - {gateway: "192.168.2.22", subnet: "192.168.2.0/24", nic: 1}, - {gateway: "192.168.1.11", subnet: "0.0.0.0/0", nic: 1}, - }, - queries: []query{ - { - name: "match default only", - remote: "1.1.1.1", - wantID: 1, - wantLocal: "192.168.1.1", - wantNextHop: "192.168.1.11", - }, - { - name: "match both, but prefer non-default", - remote: "192.168.2.2", - wantID: 1, - wantLocal: "192.168.2.1", - wantNextHop: "192.168.2.22", - }, - }, - }, - { - name: "one NIC, multiple addresses, no default gateway", - nics: []nic{{id: 1, addresses: []string{"192.168.1.1", "192.168.2.1"}}}, - routes: []route{ - {gateway: "192.168.2.22", subnet: "192.168.2.0/24", nic: 1}, - {gateway: "192.168.1.11", subnet: "192.168.1.0/24", nic: 1}, - }, - queries: []query{ - { - name: "match single A", - remote: "192.168.1.2", - wantID: 1, - wantLocal: "192.168.1.1", - wantNextHop: "192.168.1.11", - }, - { - name: "match single B", - remote: "192.168.2.2", - wantID: 1, - wantLocal: "192.168.2.1", - wantNextHop: "192.168.2.22", - }, - { - name: "match none", - remote: "3.3.3.3", - wantErr: true, - }, - }, - }, - } - - for _, stackConfig := range stacks { - t.Run(stackConfig.name, func(t *testing.T) { - // Create the stack. The channel endpoint is unused, but necessary for creation. - ep := channel.New(1, defaultMTU, "") - stk := stack.New(stack.Options{ - NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol /*, arp.NewProtocol*/}, - }) - - // Create NICs and assign addresses to them. - for _, nic := range stackConfig.nics { - if err := stk.CreateNIC(nic.id, ep); err != nil { - t.Fatal("NewNIC failed:", err) - } - for _, addr := range nic.addresses { - protocolAddr := tcpip.ProtocolAddress{ - Protocol: header.IPv4ProtocolNumber, - AddressWithPrefix: tcpip.AddressWithPrefix{ - Address: testutil.MustParse4(addr), - PrefixLen: prefixLen, - }, - } - if err := stk.AddProtocolAddress(nic.id, protocolAddr, stack.AddressProperties{}); err != nil { - t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", 1, protocolAddr, err) - } - } - } - - // Setup the route table. - var routeTable []tcpip.Route - for _, route := range stackConfig.routes { - routeTable = append(routeTable, tcpip.Route{ - Destination: testutil.MustParseSubnet4(route.subnet), - Gateway: testutil.MustParse4(route.gateway), - NIC: route.nic, - }) - } - stk.SetRouteTable(routeTable) - - for _, query := range stackConfig.queries { - t.Run(query.name, func(t *testing.T) { - route, err := stk.FindRoute( - 0, - tcpip.Address{}, - testutil.MustParse4(query.remote), - header.IPv4ProtocolNumber, - false, /* multicastLoop */ - ) - if err != nil { - if _, ok := err.(*tcpip.ErrHostUnreachable); query.wantErr && ok { - return - } - t.Fatalf("FoundRoute failed: %v", err) - } - if got, want := route.OutgoingNIC(), query.wantID; got != want { - t.Errorf("got outgoing NIC %d, but wanted %d", got, want) - } - if got, want := route.LocalAddress(), testutil.MustParse4(query.wantLocal); got != want { - t.Errorf("got local address %s, but wanted %s", got, want) - } - if got, want := route.NextHop(), testutil.MustParse4(query.wantNextHop); got != want { - t.Errorf("got next hop %s, but wanted %s", got, want) - } - }) - } - }) - } -} diff --git a/pkg/tcpip/testutil/testutil.go b/pkg/tcpip/testutil/testutil.go index 53ce839bb..6455d1f82 100644 --- a/pkg/tcpip/testutil/testutil.go +++ b/pkg/tcpip/testutil/testutil.go @@ -19,7 +19,6 @@ import ( "fmt" "net" "reflect" - "strconv" "strings" "gvisor.dev/gvisor/pkg/tcpip" @@ -45,25 +44,6 @@ func MustParse6(addr string) tcpip.Address { return tcpip.AddrFrom16Slice(ip) } -// MustParseSubnet4 parses an IPv4 subnet string (e.g. "192.168.1.0/24") into a -// tcpip.Subnet. -func MustParseSubnet4(subnet string) tcpip.Subnet { - parts := strings.Split(subnet, "/") - if len(parts) != 2 { - panic(fmt.Sprintf("MustParseSubnet4 expected CIDR notation (/), but got %q", subnet)) - } - addr := MustParse4(parts[0]) - prefixLen, err := strconv.Atoi(parts[1]) - if err != nil { - panic(fmt.Sprintf("Failed to parse prefix length %q: %v", parts[1], err)) - } - if prefixLen < 0 || prefixLen > 32 { - panic(fmt.Sprintf("Prefix length %d is invalid. It must be between 0 and 32", prefixLen)) - } - prefixed := tcpip.AddressWithPrefix{Address: addr, PrefixLen: prefixLen} - return prefixed.Subnet() -} - func checkFieldCounts(ref, multi reflect.Value) error { refTypeName := ref.Type().Name() multiTypeName := multi.Type().Name()