summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-02-08 19:03:54 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-08 19:05:45 -0800
commit39251f31cb92d6c2b053416d04e195e290b106f2 (patch)
treebf3c80dc631655f48fc0b9686cfe2af2e6a4ab74 /pkg/tcpip/stack
parentcfa4633c3d206aa2f9abdaac60d053162244ee6d (diff)
Support performing DAD for any address
...as long as the network protocol supports duplicate address detection. This CL provides the facilities for a netstack integrator to perform DAD. DHCP recommends that clients effectively perform DAD before accepting an offer. As per RFC 2131 section 4.4.1 pg 38, The client SHOULD perform a check on the suggested address to ensure that the address is not already in use. For example, if the client is on a network that supports ARP, the client may issue an ARP request for the suggested request. The implementation of ARP-based IPv4 DAD effectively operates the same as IPv6's NDP DAD - using ARP requests and responses in place of NDP neighbour solicitations and advertisements, respectively. DAD performed by calls to (*Stack).CheckDuplicateAddress don't interfere with DAD performed when a new IPv6 address is added. This is so that integrator requests to check for duplicate addresses aren't unexpectedly aborted when addresses are removed. A network package internal package provides protocol agnostic DAD state management that specific protocols that provide DAD can use. Fixes #4550. Tests: - internal/ip_test.* - integration_test.TestDAD - arp_test.TestDADARPRequestPacket - ipv6.TestCheckDuplicateAddress PiperOrigin-RevId: 356405593
Diffstat (limited to 'pkg/tcpip/stack')
-rw-r--r--pkg/tcpip/stack/ndp_test.go108
-rw-r--r--pkg/tcpip/stack/nic.go33
-rw-r--r--pkg/tcpip/stack/registration.go93
-rw-r--r--pkg/tcpip/stack/stack.go11
-rw-r--r--pkg/tcpip/stack/stack_test.go10
5 files changed, 187 insertions, 68 deletions
diff --git a/pkg/tcpip/stack/ndp_test.go b/pkg/tcpip/stack/ndp_test.go
index 4fa4101b0..3b6ba9509 100644
--- a/pkg/tcpip/stack/ndp_test.go
+++ b/pkg/tcpip/stack/ndp_test.go
@@ -424,7 +424,7 @@ func TestDADResolve(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
NDPDisp: &ndpDisp,
- NDPConfigs: ipv6.NDPConfigurations{
+ DADConfigs: stack.DADConfigurations{
RetransmitTimer: test.retransTimer,
DupAddrDetectTransmits: test.dupAddrDetectTransmits,
},
@@ -642,14 +642,14 @@ func TestDADFail(t *testing.T) {
ndpDisp := ndpDispatcher{
dadC: make(chan ndpDADEvent, 1),
}
- ndpConfigs := ipv6.DefaultNDPConfigurations()
- ndpConfigs.RetransmitTimer = time.Second * 2
+ dadConfigs := stack.DefaultDADConfigurations()
+ dadConfigs.RetransmitTimer = time.Second * 2
e := channel.New(0, 1280, linkAddr1)
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
NDPDisp: &ndpDisp,
- NDPConfigs: ndpConfigs,
+ DADConfigs: dadConfigs,
})},
})
if err := s.CreateNIC(nicID, e); err != nil {
@@ -677,7 +677,7 @@ func TestDADFail(t *testing.T) {
// Wait for DAD to fail and make sure the address did
// not get resolved.
select {
- case <-time.After(time.Duration(ndpConfigs.DupAddrDetectTransmits)*ndpConfigs.RetransmitTimer + time.Second):
+ case <-time.After(time.Duration(dadConfigs.DupAddrDetectTransmits)*dadConfigs.RetransmitTimer + time.Second):
// If we don't get a failure event after the
// expected resolution time + extra 1s buffer,
// something is wrong.
@@ -748,7 +748,7 @@ func TestDADStop(t *testing.T) {
dadC: make(chan ndpDADEvent, 1),
}
- ndpConfigs := ipv6.NDPConfigurations{
+ dadConfigs := stack.DADConfigurations{
RetransmitTimer: time.Second,
DupAddrDetectTransmits: 2,
}
@@ -757,7 +757,7 @@ func TestDADStop(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
NDPDisp: &ndpDisp,
- NDPConfigs: ndpConfigs,
+ DADConfigs: dadConfigs,
})},
})
if err := s.CreateNIC(nicID, e); err != nil {
@@ -777,12 +777,12 @@ func TestDADStop(t *testing.T) {
// Wait for DAD to fail (since the address was removed during DAD).
select {
- case <-time.After(time.Duration(ndpConfigs.DupAddrDetectTransmits)*ndpConfigs.RetransmitTimer + time.Second):
+ case <-time.After(time.Duration(dadConfigs.DupAddrDetectTransmits)*dadConfigs.RetransmitTimer + time.Second):
// If we don't get a failure event after the expected resolution
// time + extra 1s buffer, something is wrong.
t.Fatal("timed out waiting for DAD failure")
case e := <-ndpDisp.dadC:
- if diff := checkDADEvent(e, nicID, addr1, false, nil); diff != "" {
+ if diff := checkDADEvent(e, nicID, addr1, false, &tcpip.ErrAborted{}); diff != "" {
t.Errorf("dad event mismatch (-want +got):\n%s", diff)
}
}
@@ -865,16 +865,15 @@ func TestSetNDPConfigurations(t *testing.T) {
t.Fatalf("CreateNIC(%d, _) = %s", nicID2, err)
}
- // Update the NDP configurations on NIC(1) to use DAD.
- configs := ipv6.NDPConfigurations{
- DupAddrDetectTransmits: test.dupAddrDetectTransmits,
- RetransmitTimer: test.retransmitTimer,
- }
+ // Update the configurations on NIC(1) to use DAD.
if ipv6Ep, err := s.GetNetworkEndpoint(nicID1, header.IPv6ProtocolNumber); err != nil {
t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID1, header.IPv6ProtocolNumber, err)
} else {
- ndpEP := ipv6Ep.(ipv6.NDPEndpoint)
- ndpEP.SetNDPConfigurations(configs)
+ dad := ipv6Ep.(stack.DuplicateAddressDetector)
+ dad.SetDADConfigurations(stack.DADConfigurations{
+ DupAddrDetectTransmits: test.dupAddrDetectTransmits,
+ RetransmitTimer: test.retransmitTimer,
+ })
}
// Created after updating NIC(1)'s NDP configurations
@@ -1903,9 +1902,11 @@ func TestAutoGenTempAddr(t *testing.T) {
e := channel.New(0, 1280, linkAddr1)
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
+ DADConfigs: stack.DADConfigurations{
+ DupAddrDetectTransmits: test.dupAddrTransmits,
+ RetransmitTimer: test.retransmitTimer,
+ },
NDPConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: test.dupAddrTransmits,
- RetransmitTimer: test.retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
AutoGenTempGlobalAddresses: true,
@@ -2202,9 +2203,11 @@ func TestNoAutoGenTempAddrWithoutStableAddr(t *testing.T) {
e := channel.New(0, 1280, linkAddr1)
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
+ DADConfigs: stack.DADConfigurations{
+ DupAddrDetectTransmits: dadTransmits,
+ RetransmitTimer: retransmitTimer,
+ },
NDPConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
AutoGenTempGlobalAddresses: true,
@@ -2635,16 +2638,15 @@ func TestMixedSLAACAddrConflictRegen(t *testing.T) {
autoGenAddrC: make(chan ndpAutoGenAddrEvent, 2),
}
e := channel.New(0, 1280, linkAddr1)
- ndpConfigs := ipv6.NDPConfigurations{
- HandleRAs: true,
- AutoGenGlobalAddresses: true,
- AutoGenTempGlobalAddresses: test.tempAddrs,
- AutoGenAddressConflictRetries: 1,
- }
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
- NDPConfigs: ndpConfigs,
- NDPDisp: &ndpDisp,
+ NDPConfigs: ipv6.NDPConfigurations{
+ HandleRAs: true,
+ AutoGenGlobalAddresses: true,
+ AutoGenTempGlobalAddresses: test.tempAddrs,
+ AutoGenAddressConflictRetries: 1,
+ },
+ NDPDisp: &ndpDisp,
OpaqueIIDOpts: ipv6.OpaqueInterfaceIdentifierOptions{
NICNameFromID: test.nicNameFromID,
},
@@ -2718,13 +2720,14 @@ func TestMixedSLAACAddrConflictRegen(t *testing.T) {
// Enable DAD.
ndpDisp.dadC = make(chan ndpDADEvent, 2)
- ndpConfigs.DupAddrDetectTransmits = dupAddrTransmits
- ndpConfigs.RetransmitTimer = retransmitTimer
if ipv6Ep, err := s.GetNetworkEndpoint(nicID, header.IPv6ProtocolNumber); err != nil {
t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID, header.IPv6ProtocolNumber, err)
} else {
- ndpEP := ipv6Ep.(ipv6.NDPEndpoint)
- ndpEP.SetNDPConfigurations(ndpConfigs)
+ ndpEP := ipv6Ep.(stack.DuplicateAddressDetector)
+ ndpEP.SetDADConfigurations(stack.DADConfigurations{
+ DupAddrDetectTransmits: dupAddrTransmits,
+ RetransmitTimer: retransmitTimer,
+ })
}
// Do SLAAC for prefix.
@@ -3830,12 +3833,12 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
}
}
- expectDADEvent := func(t *testing.T, ndpDisp *ndpDispatcher, addr tcpip.Address, resolved bool) {
+ expectDADEvent := func(t *testing.T, ndpDisp *ndpDispatcher, addr tcpip.Address, resolved bool, err tcpip.Error) {
t.Helper()
select {
case e := <-ndpDisp.dadC:
- if diff := checkDADEvent(e, nicID, addr, resolved, nil); diff != "" {
+ if diff := checkDADEvent(e, nicID, addr, resolved, err); diff != "" {
t.Errorf("dad event mismatch (-want +got):\n%s", diff)
}
default:
@@ -3868,8 +3871,6 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
{
name: "Global address",
ndpConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
},
@@ -3884,11 +3885,8 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
},
},
{
- name: "LinkLocal address",
- ndpConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
- },
+ name: "LinkLocal address",
+ ndpConfigs: ipv6.NDPConfigurations{},
autoGenLinkLocal: true,
prepareFn: func(*testing.T, *ndpDispatcher, *channel.Endpoint, []byte) []tcpip.AddressWithPrefix {
return nil
@@ -3900,8 +3898,6 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
{
name: "Temporary address",
ndpConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
AutoGenTempGlobalAddresses: true,
@@ -3953,8 +3949,12 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
AutoGenLinkLocal: addrType.autoGenLinkLocal,
- NDPConfigs: ndpConfigs,
- NDPDisp: &ndpDisp,
+ DADConfigs: stack.DADConfigurations{
+ DupAddrDetectTransmits: dadTransmits,
+ RetransmitTimer: retransmitTimer,
+ },
+ NDPConfigs: ndpConfigs,
+ NDPDisp: &ndpDisp,
OpaqueIIDOpts: ipv6.OpaqueInterfaceIdentifierOptions{
NICNameFromID: func(_ tcpip.NICID, nicName string) string {
return nicName
@@ -3984,7 +3984,7 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
// Simulate a DAD conflict.
rxNDPSolicit(e, addr.Address)
expectAutoGenAddrEvent(t, &ndpDisp, addr, invalidatedAddr)
- expectDADEvent(t, &ndpDisp, addr.Address, false)
+ expectDADEvent(t, &ndpDisp, addr.Address, false, nil)
// Attempting to add the address manually should not fail if the
// address's state was cleaned up when DAD failed.
@@ -3994,7 +3994,7 @@ func TestAutoGenAddrInResponseToDADConflicts(t *testing.T) {
if err := s.RemoveAddress(nicID, addr.Address); err != nil {
t.Fatalf("RemoveAddress(%d, %s) = %s", nicID, addr.Address, err)
}
- expectDADEvent(t, &ndpDisp, addr.Address, false)
+ expectDADEvent(t, &ndpDisp, addr.Address, false, &tcpip.ErrAborted{})
}
// Should not have any new addresses assigned to the NIC.
@@ -4048,8 +4048,6 @@ func TestAutoGenAddrWithEUI64IIDNoDADRetries(t *testing.T) {
{
name: "Global address",
ndpConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
AutoGenAddressConflictRetries: maxRetries,
@@ -4064,8 +4062,6 @@ func TestAutoGenAddrWithEUI64IIDNoDADRetries(t *testing.T) {
{
name: "LinkLocal address",
ndpConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
AutoGenAddressConflictRetries: maxRetries,
},
autoGenLinkLocal: true,
@@ -4090,6 +4086,10 @@ func TestAutoGenAddrWithEUI64IIDNoDADRetries(t *testing.T) {
AutoGenLinkLocal: addrType.autoGenLinkLocal,
NDPConfigs: addrType.ndpConfigs,
NDPDisp: &ndpDisp,
+ DADConfigs: stack.DADConfigurations{
+ DupAddrDetectTransmits: dadTransmits,
+ RetransmitTimer: retransmitTimer,
+ },
})},
})
if err := s.CreateNIC(nicID, e); err != nil {
@@ -4171,9 +4171,11 @@ func TestAutoGenAddrContinuesLifetimesAfterRetry(t *testing.T) {
e := channel.New(0, 1280, linkAddr1)
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
+ DADConfigs: stack.DADConfigurations{
+ DupAddrDetectTransmits: dadTransmits,
+ RetransmitTimer: retransmitTimer,
+ },
NDPConfigs: ipv6.NDPConfigurations{
- DupAddrDetectTransmits: dadTransmits,
- RetransmitTimer: retransmitTimer,
HandleRAs: true,
AutoGenGlobalAddresses: true,
AutoGenAddressConflictRetries: maxRetries,
diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go
index 00cfba35a..f66db16a7 100644
--- a/pkg/tcpip/stack/nic.go
+++ b/pkg/tcpip/stack/nic.go
@@ -55,8 +55,9 @@ type nic struct {
// The network endpoints themselves may be modified by calling the interface's
// methods, but the map reference and entries must be constant.
- networkEndpoints map[tcpip.NetworkProtocolNumber]NetworkEndpoint
- linkAddrResolvers map[tcpip.NetworkProtocolNumber]*linkResolver
+ networkEndpoints map[tcpip.NetworkProtocolNumber]NetworkEndpoint
+ linkAddrResolvers map[tcpip.NetworkProtocolNumber]*linkResolver
+ duplicateAddressDetectors map[tcpip.NetworkProtocolNumber]DuplicateAddressDetector
// enabled is set to 1 when the NIC is enabled and 0 when it is disabled.
//
@@ -145,13 +146,14 @@ func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, ctx NICC
nic := &nic{
LinkEndpoint: ep,
- stack: stack,
- id: id,
- name: name,
- context: ctx,
- stats: makeNICStats(),
- networkEndpoints: make(map[tcpip.NetworkProtocolNumber]NetworkEndpoint),
- linkAddrResolvers: make(map[tcpip.NetworkProtocolNumber]*linkResolver),
+ stack: stack,
+ id: id,
+ name: name,
+ context: ctx,
+ stats: makeNICStats(),
+ networkEndpoints: make(map[tcpip.NetworkProtocolNumber]NetworkEndpoint),
+ linkAddrResolvers: make(map[tcpip.NetworkProtocolNumber]*linkResolver),
+ duplicateAddressDetectors: make(map[tcpip.NetworkProtocolNumber]DuplicateAddressDetector),
}
nic.linkResQueue.init(nic)
nic.mu.packetEPs = make(map[tcpip.NetworkProtocolNumber]*packetEndpointList)
@@ -176,6 +178,10 @@ func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, ctx NICC
nic.linkAddrResolvers[r.LinkAddressProtocol()] = l
}
}
+
+ if d, ok := netEP.(DuplicateAddressDetector); ok {
+ nic.duplicateAddressDetectors[d.DuplicateAddressProtocol()] = d
+ }
}
nic.LinkEndpoint.Attach(nic)
@@ -991,3 +997,12 @@ func (n *nic) CheckLocalAddress(protocol tcpip.NetworkProtocolNumber, addr tcpip
return false
}
+
+func (n *nic) checkDuplicateAddress(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, h DADCompletionHandler) (DADCheckAddressDisposition, tcpip.Error) {
+ d, ok := n.duplicateAddressDetectors[protocol]
+ if !ok {
+ return 0, &tcpip.ErrNotSupported{}
+ }
+
+ return d.CheckDuplicateAddress(addr, h), nil
+}
diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go
index 2bc1c4270..43e9e4beb 100644
--- a/pkg/tcpip/stack/registration.go
+++ b/pkg/tcpip/stack/registration.go
@@ -16,6 +16,7 @@ package stack
import (
"fmt"
+ "time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
@@ -851,7 +852,97 @@ type InjectableLinkEndpoint interface {
InjectOutbound(dest tcpip.Address, packet []byte) tcpip.Error
}
-// A LinkAddressResolver handles link address resolution for a network protocol.
+// DADResult is the result of a duplicate address detection process.
+type DADResult struct {
+ // Resolved is true when DAD completed without detecting a duplicate address
+ // on the link.
+ //
+ // Ignored when Err is non-nil.
+ Resolved bool
+
+ // Err is an error encountered while performing DAD.
+ Err tcpip.Error
+}
+
+// DADCompletionHandler is a handler for DAD completion.
+type DADCompletionHandler func(DADResult)
+
+// DADCheckAddressDisposition enumerates the possible return values from
+// DAD.CheckDuplicateAddress.
+type DADCheckAddressDisposition int
+
+const (
+ _ DADCheckAddressDisposition = iota
+
+ // DADDisabled indicates that DAD is disabled.
+ DADDisabled
+
+ // DADStarting indicates that DAD is starting for an address.
+ DADStarting
+
+ // DADAlreadyRunning indicates that DAD was already started for an address.
+ DADAlreadyRunning
+)
+
+const (
+ // defaultDupAddrDetectTransmits is the default number of NDP Neighbor
+ // Solicitation messages to send when doing Duplicate Address Detection
+ // for a tentative address.
+ //
+ // Default = 1 (from RFC 4862 section 5.1)
+ defaultDupAddrDetectTransmits = 1
+)
+
+// DADConfigurations holds configurations for duplicate address detection.
+type DADConfigurations struct {
+ // The number of Neighbor Solicitation messages to send when doing
+ // Duplicate Address Detection for a tentative address.
+ //
+ // Note, a value of zero effectively disables DAD.
+ DupAddrDetectTransmits uint8
+
+ // The amount of time to wait between sending Neighbor Solicitation
+ // messages.
+ //
+ // Must be greater than or equal to 1ms.
+ RetransmitTimer time.Duration
+}
+
+// DefaultDADConfigurations returns the default DAD configurations.
+func DefaultDADConfigurations() DADConfigurations {
+ return DADConfigurations{
+ DupAddrDetectTransmits: defaultDupAddrDetectTransmits,
+ RetransmitTimer: defaultRetransmitTimer,
+ }
+}
+
+// Validate modifies the configuration with valid values. If invalid values are
+// present in the configurations, the corresponding default values are used
+// instead.
+func (c *DADConfigurations) Validate() {
+ if c.RetransmitTimer < minimumRetransmitTimer {
+ c.RetransmitTimer = defaultRetransmitTimer
+ }
+}
+
+// DuplicateAddressDetector handles checking if an address is already assigned
+// to some neighboring node on the link.
+type DuplicateAddressDetector interface {
+ // CheckDuplicateAddress checks if an address is assigned to a neighbor.
+ //
+ // If DAD is already being performed for the address, the handler will be
+ // called with the result of the original DAD request.
+ CheckDuplicateAddress(tcpip.Address, DADCompletionHandler) DADCheckAddressDisposition
+
+ // SetDADConfiguations sets the configurations for DAD.
+ SetDADConfigurations(c DADConfigurations)
+
+ // DuplicateAddressProtocol returns the network protocol the receiver can
+ // perform duplicate address detection for.
+ DuplicateAddressProtocol() tcpip.NetworkProtocolNumber
+}
+
+// LinkAddressResolver handles link address resolution for a network protocol.
type LinkAddressResolver interface {
// LinkAddressRequest sends a request for the link address of the target
// address. The request is broadcasted on the local network if a remote link
diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go
index 46c1817ea..674c9a1ff 100644
--- a/pkg/tcpip/stack/stack.go
+++ b/pkg/tcpip/stack/stack.go
@@ -1466,6 +1466,17 @@ func (s *Stack) CheckNetworkProtocol(protocol tcpip.NetworkProtocolNumber) bool
return ok
}
+// CheckDuplicateAddress performs duplicate address detection for the address on
+// the specified interface.
+func (s *Stack) CheckDuplicateAddress(nicID tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, h DADCompletionHandler) (DADCheckAddressDisposition, tcpip.Error) {
+ nic, ok := s.nics[nicID]
+ if !ok {
+ return 0, &tcpip.ErrUnknownNICID{}
+ }
+
+ return nic.checkDuplicateAddress(protocol, addr, h)
+}
+
// CheckLocalAddress determines if the given local address exists, and if it
// does, returns the id of the NIC it's bound to. Returns 0 if the address
// does not exist.
diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go
index 62066b3aa..92a0cb401 100644
--- a/pkg/tcpip/stack/stack_test.go
+++ b/pkg/tcpip/stack/stack_test.go
@@ -2573,16 +2573,16 @@ func TestNICAutoGenAddrDoesDAD(t *testing.T) {
ndpDisp := ndpDispatcher{
dadC: make(chan ndpDADEvent),
}
- ndpConfigs := ipv6.DefaultNDPConfigurations()
+ dadConfigs := stack.DefaultDADConfigurations()
opts := stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
- NDPConfigs: ndpConfigs,
AutoGenLinkLocal: true,
NDPDisp: &ndpDisp,
+ DADConfigs: dadConfigs,
})},
}
- e := channel.New(int(ndpConfigs.DupAddrDetectTransmits), 1280, linkAddr1)
+ e := channel.New(int(dadConfigs.DupAddrDetectTransmits), 1280, linkAddr1)
s := stack.New(opts)
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("CreateNIC(%d, _) = %s", nicID, err)
@@ -2598,7 +2598,7 @@ func TestNICAutoGenAddrDoesDAD(t *testing.T) {
// Wait for DAD to resolve.
select {
- case <-time.After(time.Duration(ndpConfigs.DupAddrDetectTransmits)*ndpConfigs.RetransmitTimer + time.Second):
+ case <-time.After(time.Duration(dadConfigs.DupAddrDetectTransmits)*dadConfigs.RetransmitTimer + time.Second):
// We should get a resolution event after 1s (default time to
// resolve as per default NDP configurations). Waiting for that
// resolution time + an extra 1s without a resolution event
@@ -3235,7 +3235,7 @@ func TestDoDADWhenNICEnabled(t *testing.T) {
}
opts := stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
- NDPConfigs: ipv6.NDPConfigurations{
+ DADConfigs: stack.DADConfigurations{
DupAddrDetectTransmits: dadTransmits,
RetransmitTimer: retransmitTimer,
},