From 6bc27946a6cb159ecbe049acff888d0041d4a432 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 2 Mar 2021 11:55:45 -0800 Subject: Plumb link address request errors up to requester Prevent the situation where callers to (*stack).GetLinkAddress provide incorrect arguments and are unable to observe this condition. Updates #5583. PiperOrigin-RevId: 360481557 --- pkg/tcpip/stack/neighbor_cache.go | 2 +- pkg/tcpip/stack/neighbor_cache_test.go | 18 ++--- pkg/tcpip/stack/neighbor_entry.go | 37 ++++++---- pkg/tcpip/stack/nic.go | 2 +- pkg/tcpip/stack/pending_packets.go | 12 +-- pkg/tcpip/stack/route.go | 8 +- pkg/tcpip/stack/stack.go | 2 +- pkg/tcpip/stack/stack_test.go | 2 +- .../tests/integration/link_resolution_test.go | 86 +++++++++++++--------- 9 files changed, 94 insertions(+), 75 deletions(-) diff --git a/pkg/tcpip/stack/neighbor_cache.go b/pkg/tcpip/stack/neighbor_cache.go index 6b1f8da86..509f5ce5c 100644 --- a/pkg/tcpip/stack/neighbor_cache.go +++ b/pkg/tcpip/stack/neighbor_cache.go @@ -140,7 +140,7 @@ func (n *neighborCache) entry(remoteAddr, localAddr tcpip.Address, onResolve fun // a node continues sending packets to that neighbor using the cached // link-layer address." if onResolve != nil { - onResolve(LinkResolutionResult{LinkAddress: entry.mu.neigh.LinkAddr, Success: true}) + onResolve(LinkResolutionResult{LinkAddress: entry.mu.neigh.LinkAddr, Err: nil}) } return entry.mu.neigh, nil, nil case Unknown, Incomplete, Unreachable: diff --git a/pkg/tcpip/stack/neighbor_cache_test.go b/pkg/tcpip/stack/neighbor_cache_test.go index 38fe82fc1..afff1b434 100644 --- a/pkg/tcpip/stack/neighbor_cache_test.go +++ b/pkg/tcpip/stack/neighbor_cache_test.go @@ -1162,7 +1162,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { t.Fatalf("linkRes.entries.entry(%d) not found", i) } _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1218,7 +1218,7 @@ func TestNeighborCacheKeepFrequentlyUsed(t *testing.T) { } _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1379,7 +1379,7 @@ func TestNeighborCacheReplace(t *testing.T) { } _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1485,7 +1485,7 @@ func TestNeighborCacheResolutionFailed(t *testing.T) { // First, sanity check that resolution is working { _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1519,7 +1519,7 @@ func TestNeighborCacheResolutionFailed(t *testing.T) { entry.Addr += "2" { _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{Success: false}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{Err: &tcpip.ErrTimeout{}}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1559,7 +1559,7 @@ func TestNeighborCacheResolutionTimeout(t *testing.T) { } _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{Success: false}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{Err: &tcpip.ErrTimeout{}}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1593,7 +1593,7 @@ func TestNeighborCacheRetryResolution(t *testing.T) { // Perform address resolution with a faulty link, which will fail. { _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{Success: false}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{Err: &tcpip.ErrTimeout{}}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1625,7 +1625,7 @@ func TestNeighborCacheRetryResolution(t *testing.T) { linkRes.dropReplies = false { incompleteEntry, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { t.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) @@ -1678,7 +1678,7 @@ func BenchmarkCacheClear(b *testing.B) { } _, ch, err := linkRes.neigh.entry(entry.Addr, "", func(r LinkResolutionResult) { - if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Success: true}, r); diff != "" { + if diff := cmp.Diff(LinkResolutionResult{LinkAddress: entry.LinkAddr, Err: nil}, r); diff != "" { b.Fatalf("got link resolution result mismatch (-want +got):\n%s", diff) } }) diff --git a/pkg/tcpip/stack/neighbor_entry.go b/pkg/tcpip/stack/neighbor_entry.go index 36d3cad62..6d95e1664 100644 --- a/pkg/tcpip/stack/neighbor_entry.go +++ b/pkg/tcpip/stack/neighbor_entry.go @@ -157,8 +157,8 @@ func newStaticNeighborEntry(cache *neighborCache, addr tcpip.Address, linkAddr t // the link address if resolution completed successfully. // // Precondition: e.mu MUST be locked. -func (e *neighborEntry) notifyCompletionLocked(succeeded bool) { - res := LinkResolutionResult{LinkAddress: e.mu.neigh.LinkAddr, Success: succeeded} +func (e *neighborEntry) notifyCompletionLocked(err tcpip.Error) { + res := LinkResolutionResult{LinkAddress: e.mu.neigh.LinkAddr, Err: err} for _, callback := range e.mu.onResolve { callback(res) } @@ -173,7 +173,7 @@ func (e *neighborEntry) notifyCompletionLocked(succeeded bool) { // is resolved (which ends up obtaining the entry's lock) while holding the // link resolution queue's lock. Dequeuing packets in a new goroutine avoids // a lock ordering violation. - go e.cache.nic.linkResQueue.dequeue(ch, e.mu.neigh.LinkAddr, succeeded) + go e.cache.nic.linkResQueue.dequeue(ch, e.mu.neigh.LinkAddr, err) } } @@ -227,7 +227,13 @@ func (e *neighborEntry) removeLocked() { e.mu.neigh.UpdatedAtNanos = e.cache.nic.stack.clock.NowNanoseconds() e.dispatchRemoveEventLocked() e.cancelTimerLocked() - e.notifyCompletionLocked(false /* succeeded */) + // TODO(https://gvisor.dev/issues/5583): test the case where this function is + // called during resolution; that can happen in at least these scenarios: + // + // - manual address removal during resolution + // + // - neighbor cache eviction during resolution + e.notifyCompletionLocked(&tcpip.ErrAborted{}) } // setStateLocked transitions the entry to the specified state immediately. @@ -302,9 +308,8 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { e.mu.timer = timer{ done: &done, timer: e.cache.nic.stack.Clock().AfterFunc(0, func() { - var err tcpip.Error - timedoutResolution := remaining == 0 - if !timedoutResolution { + var err tcpip.Error = &tcpip.ErrTimeout{} + if remaining != 0 { err = e.cache.linkRes.LinkAddressRequest(addr, "" /* localAddr */, linkAddr) } @@ -316,8 +321,9 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { return } - if timedoutResolution || err != nil { + if err != nil { e.setStateLocked(Unreachable) + e.notifyCompletionLocked(err) e.dispatchChangeEventLocked() return } @@ -328,7 +334,6 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { } case Unreachable: - e.notifyCompletionLocked(false /* succeeded */) case Unknown, Stale, Static: // Do nothing @@ -374,9 +379,8 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) { e.mu.timer = timer{ done: &done, timer: e.cache.nic.stack.Clock().AfterFunc(0, func() { - var err tcpip.Error - timedoutResolution := remaining == 0 - if !timedoutResolution { + var err tcpip.Error = &tcpip.ErrTimeout{} + if remaining != 0 { // As per RFC 4861 section 7.2.2: // // If the source address of the packet prompting the solicitation is @@ -395,8 +399,9 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) { return } - if timedoutResolution || err != nil { + if err != nil { e.setStateLocked(Unreachable) + e.notifyCompletionLocked(err) e.dispatchChangeEventLocked() return } @@ -442,7 +447,7 @@ func (e *neighborEntry) handleProbeLocked(remoteLinkAddr tcpip.LinkAddress) { // - RFC 4861 section 7.2.3 e.mu.neigh.LinkAddr = remoteLinkAddr e.setStateLocked(Stale) - e.notifyCompletionLocked(true /* succeeded */) + e.notifyCompletionLocked(nil) e.dispatchChangeEventLocked() case Reachable, Delay, Probe: @@ -504,7 +509,7 @@ func (e *neighborEntry) handleConfirmationLocked(linkAddr tcpip.LinkAddress, fla } e.dispatchChangeEventLocked() e.mu.isRouter = flags.IsRouter - e.notifyCompletionLocked(true /* succeeded */) + e.notifyCompletionLocked(nil) // "Note that the Override flag is ignored if the entry is in the // INCOMPLETE state." - RFC 4861 section 7.2.5 @@ -539,7 +544,7 @@ func (e *neighborEntry) handleConfirmationLocked(linkAddr tcpip.LinkAddress, fla wasReachable := e.mu.neigh.State == Reachable // Set state to Reachable again to refresh timers. e.setStateLocked(Reachable) - e.notifyCompletionLocked(true /* succeeded */) + e.notifyCompletionLocked(nil) if !wasReachable { e.dispatchChangeEventLocked() } diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index f66db16a7..f9323d545 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -613,7 +613,7 @@ func (n *nic) getLinkAddress(addr, localAddr tcpip.Address, protocol tcpip.Netwo } if linkAddr, ok := linkRes.resolver.ResolveStaticAddress(addr); ok { - onResolve(LinkResolutionResult{LinkAddress: linkAddr, Success: true}) + onResolve(LinkResolutionResult{LinkAddress: linkAddr, Err: nil}) return nil } diff --git a/pkg/tcpip/stack/pending_packets.go b/pkg/tcpip/stack/pending_packets.go index dc139ebb2..e936aa728 100644 --- a/pkg/tcpip/stack/pending_packets.go +++ b/pkg/tcpip/stack/pending_packets.go @@ -91,9 +91,9 @@ func (f *packetsPendingLinkResolution) init(nic *nic) { // dequeue any pending packets associated with ch. // -// If success is true, packets will be written and sent to the given remote link +// If err is nil, packets will be written and sent to the given remote link // address. -func (f *packetsPendingLinkResolution) dequeue(ch <-chan struct{}, linkAddr tcpip.LinkAddress, success bool) { +func (f *packetsPendingLinkResolution) dequeue(ch <-chan struct{}, linkAddr tcpip.LinkAddress, err tcpip.Error) { f.mu.Lock() packets, ok := f.mu.packets[ch] delete(f.mu.packets, ch) @@ -110,7 +110,7 @@ func (f *packetsPendingLinkResolution) dequeue(ch <-chan struct{}, linkAddr tcpi f.mu.Unlock() if ok { - f.dequeuePackets(packets, linkAddr, success) + f.dequeuePackets(packets, linkAddr, err) } } @@ -176,7 +176,7 @@ func (f *packetsPendingLinkResolution) enqueue(r *Route, gso *GSO, proto tcpip.N if len(cancelledPackets) != 0 { // Dequeue the pending packets in a new goroutine to not hold up the current // goroutine as handing link resolution failures may be a costly operation. - go f.dequeuePackets(cancelledPackets, "" /* linkAddr */, false /* success */) + go f.dequeuePackets(cancelledPackets, "" /* linkAddr */, &tcpip.ErrAborted{}) } return pkt.len(), nil @@ -207,9 +207,9 @@ func (f *packetsPendingLinkResolution) newCancelChannelLocked(newCH <-chan struc return packets } -func (f *packetsPendingLinkResolution) dequeuePackets(packets []pendingPacket, linkAddr tcpip.LinkAddress, success bool) { +func (f *packetsPendingLinkResolution) dequeuePackets(packets []pendingPacket, linkAddr tcpip.LinkAddress, err tcpip.Error) { for _, p := range packets { - if success { + if err == nil { p.routeInfo.RemoteLinkAddress = linkAddr _, _ = f.nic.writePacketBuffer(p.routeInfo, p.gso, p.proto, p.pkt) } else { diff --git a/pkg/tcpip/stack/route.go b/pkg/tcpip/stack/route.go index e946f9fe3..4ba6794a0 100644 --- a/pkg/tcpip/stack/route.go +++ b/pkg/tcpip/stack/route.go @@ -318,7 +318,7 @@ func (r *Route) ResolveWith(addr tcpip.LinkAddress) { // ResolvedFieldsResult is the result of a route resolution attempt. type ResolvedFieldsResult struct { RouteInfo RouteInfo - Success bool + Err tcpip.Error } // ResolvedFields attempts to resolve the remote link address if it is not @@ -349,7 +349,7 @@ func (r *Route) resolvedFields(afterResolve func(ResolvedFieldsResult)) (RouteIn r.mu.RUnlock() if !resolutionRequired { if afterResolve != nil { - afterResolve(ResolvedFieldsResult{RouteInfo: fields, Success: true}) + afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil}) } return fields, nil, nil } @@ -364,11 +364,11 @@ func (r *Route) resolvedFields(afterResolve func(ResolvedFieldsResult)) (RouteIn afterResolveFields := fields linkAddr, ch, err := r.linkRes.getNeighborLinkAddress(r.nextHop(), linkAddressResolutionRequestLocalAddr, func(r LinkResolutionResult) { if afterResolve != nil { - if r.Success { + if r.Err == nil { afterResolveFields.RemoteLinkAddress = r.LinkAddress } - afterResolve(ResolvedFieldsResult{RouteInfo: afterResolveFields, Success: r.Success}) + afterResolve(ResolvedFieldsResult{RouteInfo: afterResolveFields, Err: r.Err}) } }) if err == nil { diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go index 674c9a1ff..de94ddfda 100644 --- a/pkg/tcpip/stack/stack.go +++ b/pkg/tcpip/stack/stack.go @@ -1542,7 +1542,7 @@ func (s *Stack) SetSpoofing(nicID tcpip.NICID, enable bool) tcpip.Error { // LinkResolutionResult is the result of a link address resolution attempt. type LinkResolutionResult struct { LinkAddress tcpip.LinkAddress - Success bool + Err tcpip.Error } // GetLinkAddress finds the link address corresponding to a network address. diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go index 92a0cb401..8e39e828c 100644 --- a/pkg/tcpip/stack/stack_test.go +++ b/pkg/tcpip/stack/stack_test.go @@ -4455,7 +4455,7 @@ func TestStaticGetLinkAddress(t *testing.T) { t.Fatalf("s.GetLinkAddress(%d, %s, '', %d, _): %s", nicID, test.addr, test.proto, err) } - if diff := cmp.Diff(stack.LinkResolutionResult{LinkAddress: test.expectedLinkAddr, Success: true}, <-ch); diff != "" { + if diff := cmp.Diff(stack.LinkResolutionResult{LinkAddress: test.expectedLinkAddr, Err: nil}, <-ch); diff != "" { t.Fatalf("link resolution result mismatch (-want +got):\n%s", diff) } }) diff --git a/pkg/tcpip/tests/integration/link_resolution_test.go b/pkg/tcpip/tests/integration/link_resolution_test.go index 18da67fb1..165f73f21 100644 --- a/pkg/tcpip/tests/integration/link_resolution_test.go +++ b/pkg/tcpip/tests/integration/link_resolution_test.go @@ -402,34 +402,48 @@ func TestGetLinkAddress(t *testing.T) { ) tests := []struct { - name string - netProto tcpip.NetworkProtocolNumber - remoteAddr tcpip.Address - expectedOk bool + name string + netProto tcpip.NetworkProtocolNumber + remoteAddr, localAddr tcpip.Address + expectedErr tcpip.Error }{ { - name: "IPv4 resolvable", - netProto: ipv4.ProtocolNumber, - remoteAddr: utils.Ipv4Addr2.AddressWithPrefix.Address, - expectedOk: true, + name: "IPv4 resolvable", + netProto: ipv4.ProtocolNumber, + remoteAddr: utils.Ipv4Addr2.AddressWithPrefix.Address, + expectedErr: nil, }, { - name: "IPv6 resolvable", - netProto: ipv6.ProtocolNumber, - remoteAddr: utils.Ipv6Addr2.AddressWithPrefix.Address, - expectedOk: true, + name: "IPv6 resolvable", + netProto: ipv6.ProtocolNumber, + remoteAddr: utils.Ipv6Addr2.AddressWithPrefix.Address, + expectedErr: nil, }, { - name: "IPv4 not resolvable", - netProto: ipv4.ProtocolNumber, - remoteAddr: utils.Ipv4Addr3.AddressWithPrefix.Address, - expectedOk: false, + name: "IPv4 not resolvable", + netProto: ipv4.ProtocolNumber, + remoteAddr: utils.Ipv4Addr3.AddressWithPrefix.Address, + expectedErr: &tcpip.ErrTimeout{}, }, { - name: "IPv6 not resolvable", - netProto: ipv6.ProtocolNumber, - remoteAddr: utils.Ipv6Addr3.AddressWithPrefix.Address, - expectedOk: false, + name: "IPv6 not resolvable", + netProto: ipv6.ProtocolNumber, + remoteAddr: utils.Ipv6Addr3.AddressWithPrefix.Address, + expectedErr: &tcpip.ErrTimeout{}, + }, + { + name: "IPv4 bad local address", + netProto: ipv4.ProtocolNumber, + remoteAddr: utils.Ipv4Addr2.AddressWithPrefix.Address, + localAddr: utils.Ipv4Addr2.AddressWithPrefix.Address, + expectedErr: &tcpip.ErrBadLocalAddress{}, + }, + { + name: "IPv6 bad local address", + netProto: ipv6.ProtocolNumber, + remoteAddr: utils.Ipv6Addr2.AddressWithPrefix.Address, + localAddr: utils.Ipv6Addr2.AddressWithPrefix.Address, + expectedErr: &tcpip.ErrBadLocalAddress{}, }, } @@ -442,14 +456,14 @@ func TestGetLinkAddress(t *testing.T) { host1Stack, _ := setupStack(t, stackOpts, host1NICID, host2NICID) ch := make(chan stack.LinkResolutionResult, 1) - err := host1Stack.GetLinkAddress(host1NICID, test.remoteAddr, "", test.netProto, func(r stack.LinkResolutionResult) { + err := host1Stack.GetLinkAddress(host1NICID, test.remoteAddr, test.localAddr, test.netProto, func(r stack.LinkResolutionResult) { ch <- r }) if _, ok := err.(*tcpip.ErrWouldBlock); !ok { t.Fatalf("got host1Stack.GetLinkAddress(%d, %s, '', %d, _) = %s, want = %s", host1NICID, test.remoteAddr, test.netProto, err, &tcpip.ErrWouldBlock{}) } - wantRes := stack.LinkResolutionResult{Success: test.expectedOk} - if test.expectedOk { + wantRes := stack.LinkResolutionResult{Err: test.expectedErr} + if test.expectedErr == nil { wantRes.LinkAddress = utils.LinkAddr2 } if diff := cmp.Diff(wantRes, <-ch); diff != "" { @@ -471,7 +485,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr tcpip.Address remoteAddr tcpip.Address immediatelyResolvable bool - expectedSuccess bool + expectedErr tcpip.Error expectedLinkAddr tcpip.LinkAddress }{ { @@ -480,7 +494,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv4Addr1.AddressWithPrefix.Address, remoteAddr: header.IPv4AllSystems, immediatelyResolvable: true, - expectedSuccess: true, + expectedErr: nil, expectedLinkAddr: header.EthernetAddressFromMulticastIPv4Address(header.IPv4AllSystems), }, { @@ -489,7 +503,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv6Addr1.AddressWithPrefix.Address, remoteAddr: header.IPv6AllNodesMulticastAddress, immediatelyResolvable: true, - expectedSuccess: true, + expectedErr: nil, expectedLinkAddr: header.EthernetAddressFromMulticastIPv6Address(header.IPv6AllNodesMulticastAddress), }, { @@ -498,7 +512,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv4Addr1.AddressWithPrefix.Address, remoteAddr: utils.Ipv4Addr2.AddressWithPrefix.Address, immediatelyResolvable: false, - expectedSuccess: true, + expectedErr: nil, expectedLinkAddr: utils.LinkAddr2, }, { @@ -507,7 +521,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv6Addr1.AddressWithPrefix.Address, remoteAddr: utils.Ipv6Addr2.AddressWithPrefix.Address, immediatelyResolvable: false, - expectedSuccess: true, + expectedErr: nil, expectedLinkAddr: utils.LinkAddr2, }, { @@ -516,7 +530,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv4Addr1.AddressWithPrefix.Address, remoteAddr: utils.Ipv4Addr3.AddressWithPrefix.Address, immediatelyResolvable: false, - expectedSuccess: false, + expectedErr: &tcpip.ErrTimeout{}, }, { name: "IPv6 not resolvable", @@ -524,7 +538,7 @@ func TestRouteResolvedFields(t *testing.T) { localAddr: utils.Ipv6Addr1.AddressWithPrefix.Address, remoteAddr: utils.Ipv6Addr3.AddressWithPrefix.Address, immediatelyResolvable: false, - expectedSuccess: false, + expectedErr: &tcpip.ErrTimeout{}, }, } @@ -535,9 +549,9 @@ func TestRouteResolvedFields(t *testing.T) { } host1Stack, _ := setupStack(t, stackOpts, host1NICID, host2NICID) - r, err := host1Stack.FindRoute(host1NICID, "", test.remoteAddr, test.netProto, false /* multicastLoop */) + r, err := host1Stack.FindRoute(host1NICID, test.localAddr, test.remoteAddr, test.netProto, false /* multicastLoop */) if err != nil { - t.Fatalf("host1Stack.FindRoute(%d, '', %s, %d, false): %s", host1NICID, test.remoteAddr, test.netProto, err) + t.Fatalf("host1Stack.FindRoute(%d, %s, %s, %d, false): %s", host1NICID, test.localAddr, test.remoteAddr, test.netProto, err) } defer r.Release() @@ -561,11 +575,11 @@ func TestRouteResolvedFields(t *testing.T) { if _, ok := err.(*tcpip.ErrWouldBlock); !ok { t.Errorf("got r.ResolvedFields(_) = %s, want = %s", err, &tcpip.ErrWouldBlock{}) } - if diff := cmp.Diff(stack.ResolvedFieldsResult{RouteInfo: wantRouteInfo, Success: test.expectedSuccess}, <-ch, cmp.AllowUnexported(stack.RouteInfo{})); diff != "" { + if diff := cmp.Diff(stack.ResolvedFieldsResult{RouteInfo: wantRouteInfo, Err: test.expectedErr}, <-ch, cmp.AllowUnexported(stack.RouteInfo{})); diff != "" { t.Errorf("route resolve result mismatch (-want +got):\n%s", diff) } - if !test.expectedSuccess { + if test.expectedErr != nil { return } @@ -580,7 +594,7 @@ func TestRouteResolvedFields(t *testing.T) { } select { case routeResolveRes := <-ch: - if diff := cmp.Diff(stack.ResolvedFieldsResult{RouteInfo: wantRouteInfo, Success: true}, routeResolveRes, cmp.AllowUnexported(stack.RouteInfo{})); diff != "" { + if diff := cmp.Diff(stack.ResolvedFieldsResult{RouteInfo: wantRouteInfo, Err: nil}, routeResolveRes, cmp.AllowUnexported(stack.RouteInfo{})); diff != "" { t.Errorf("route resolve result from resolved route mismatch (-want +got):\n%s", diff) } default: @@ -1021,7 +1035,7 @@ func TestTCPConfirmNeighborReachability(t *testing.T) { if _, ok := err.(*tcpip.ErrWouldBlock); !ok { t.Fatalf("got host1Stack.GetLinkAddress(%d, %s, '', %d, _) = %s, want = %s", utils.Host1NICID, test.neighborAddr, test.netProto, err, &tcpip.ErrWouldBlock{}) } - if diff := cmp.Diff(stack.LinkResolutionResult{LinkAddress: utils.LinkAddr2, Success: true}, <-ch); diff != "" { + if diff := cmp.Diff(stack.LinkResolutionResult{LinkAddress: utils.LinkAddr2, Err: nil}, <-ch); diff != "" { t.Fatalf("link resolution mismatch (-want +got):\n%s", diff) } } -- cgit v1.2.3