Send unicast probes when link address is known

When the neighbor table already has link address for a neighbor but is
trying to confirm reachability, it may send unicast probes to the
neighbor.

PiperOrigin-RevId: 336166711
This commit is contained in:
Ghanan Gowripalan
2020-10-08 14:36:14 -07:00
committed by gVisor bot
parent 5124ce579d
commit 40269d0c24
2 changed files with 38 additions and 18 deletions
+9 -6
View File
@@ -646,18 +646,21 @@ func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
// LinkAddressRequest implements stack.LinkAddressResolver.
func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress, linkEP stack.LinkEndpoint) *tcpip.Error {
snaddr := header.SolicitedNodeAddr(addr)
// TODO(b/148672031): Use stack.FindRoute instead of manually creating the
// route here. Note, we would need the nicID to do this properly so the right
// NIC (associated to linkEP) is used to send the NDP NS message.
r := &stack.Route{
r := stack.Route{
LocalAddress: localAddr,
RemoteAddress: snaddr,
RemoteAddress: addr,
RemoteLinkAddress: remoteLinkAddr,
}
// If a remote address is not already known, then send a multicast
// solicitation since multicast addresses have a static mapping to link
// addresses.
if len(r.RemoteLinkAddress) == 0 {
r.RemoteLinkAddress = header.EthernetAddressFromMulticastIPv6Address(snaddr)
r.RemoteAddress = header.SolicitedNodeAddr(addr)
r.RemoteLinkAddress = header.EthernetAddressFromMulticastIPv6Address(r.RemoteAddress)
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
@@ -683,7 +686,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, remoteLinkAdd
})
// TODO(stijlist): count this in ICMP stats.
return linkEP.WritePacket(r, nil /* gso */, ProtocolNumber, pkt)
return linkEP.WritePacket(&r, nil /* gso */, ProtocolNumber, pkt)
}
// ResolveStaticAddress implements stack.LinkAddressResolver.
+29 -12
View File
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/checker"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
@@ -1223,19 +1224,22 @@ func TestLinkAddressRequest(t *testing.T) {
mcaddr := header.EthernetAddressFromMulticastIPv6Address(snaddr)
tests := []struct {
name string
remoteLinkAddr tcpip.LinkAddress
expectLinkAddr tcpip.LinkAddress
name string
remoteLinkAddr tcpip.LinkAddress
expectedLinkAddr tcpip.LinkAddress
expectedAddr tcpip.Address
}{
{
name: "Unicast",
remoteLinkAddr: linkAddr1,
expectLinkAddr: linkAddr1,
name: "Unicast",
remoteLinkAddr: linkAddr1,
expectedLinkAddr: linkAddr1,
expectedAddr: lladdr0,
},
{
name: "Multicast",
remoteLinkAddr: "",
expectLinkAddr: mcaddr,
name: "Multicast",
remoteLinkAddr: "",
expectedLinkAddr: mcaddr,
expectedAddr: snaddr,
},
}
@@ -1258,9 +1262,22 @@ func TestLinkAddressRequest(t *testing.T) {
if !ok {
t.Fatal("expected to send a link address request")
}
if got, want := pkt.Route.RemoteLinkAddress, test.expectLinkAddr; got != want {
t.Errorf("got pkt.Route.RemoteLinkAddress = %s, want = %s", got, want)
if pkt.Route.RemoteLinkAddress != test.expectedLinkAddr {
t.Errorf("got pkt.Route.RemoteLinkAddress = %s, want = %s", pkt.Route.RemoteLinkAddress, test.expectedLinkAddr)
}
if pkt.Route.RemoteAddress != test.expectedAddr {
t.Errorf("got pkt.Route.RemoteAddress = %s, want = %s", pkt.Route.RemoteAddress, test.expectedAddr)
}
if pkt.Route.LocalAddress != lladdr1 {
t.Errorf("got pkt.Route.LocalAddress = %s, want = %s", pkt.Route.LocalAddress, lladdr1)
}
checker.IPv6(t, stack.PayloadSince(pkt.Pkt.NetworkHeader()),
checker.SrcAddr(lladdr1),
checker.DstAddr(test.expectedAddr),
checker.TTL(header.NDPHopLimit),
checker.NDPNS(
checker.NDPNSTargetAddress(lladdr0),
checker.NDPNSOptions([]header.NDPOption{header.NDPSourceLinkLayerAddressOption(linkAddr0)}),
))
}
}