Attach LinkEndpoint to NetworkDispatcher immediately
Tests: stack_test.TestAttachToLinkEndpointImmediately PiperOrigin-RevId: 296474068
This commit is contained in:
parent
d8e60e7867
commit
a155a23480
|
@ -45,7 +45,6 @@ type NIC struct {
|
|||
context NICContext
|
||||
|
||||
stats NICStats
|
||||
attach sync.Once
|
||||
|
||||
mu struct {
|
||||
sync.RWMutex
|
||||
|
@ -141,6 +140,8 @@ func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, ctx NICC
|
|||
nic.mu.packetEPs[netProto.Number()] = []PacketEndpoint{}
|
||||
}
|
||||
|
||||
nic.linkEP.Attach(nic)
|
||||
|
||||
return nic
|
||||
}
|
||||
|
||||
|
@ -200,14 +201,16 @@ func (n *NIC) disable() *tcpip.Error {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(b/147015577): Should n detach from its LinkEndpoint?
|
||||
|
||||
n.mu.enabled = false
|
||||
return nil
|
||||
}
|
||||
|
||||
// enable enables n. enable will attach the nic to its LinkEndpoint and
|
||||
// join the IPv6 All-Nodes Multicast address (ff02::1).
|
||||
// enable enables n.
|
||||
//
|
||||
// If the stack has IPv6 enabled, enable will join the IPv6 All-Nodes Multicast
|
||||
// address (ff02::1), start DAD for permanent addresses, and start soliciting
|
||||
// routers if the stack is not operating as a router. If the stack is also
|
||||
// configured to auto-generate a link-local address, one will be generated.
|
||||
func (n *NIC) enable() *tcpip.Error {
|
||||
n.mu.RLock()
|
||||
enabled := n.mu.enabled
|
||||
|
@ -225,8 +228,6 @@ func (n *NIC) enable() *tcpip.Error {
|
|||
|
||||
n.mu.enabled = true
|
||||
|
||||
n.attachLinkEndpoint()
|
||||
|
||||
// Create an endpoint to receive broadcast packets on this interface.
|
||||
if _, ok := n.stack.networkProtocols[header.IPv4ProtocolNumber]; ok {
|
||||
if _, err := n.addAddressLocked(ipv4BroadcastAddr, NeverPrimaryEndpoint, permanent, static, false /* deprecated */); err != nil {
|
||||
|
@ -321,14 +322,6 @@ func (n *NIC) becomeIPv6Host() {
|
|||
n.mu.ndp.startSolicitingRouters()
|
||||
}
|
||||
|
||||
// attachLinkEndpoint attaches the NIC to the endpoint, which will enable it
|
||||
// to start delivering packets.
|
||||
func (n *NIC) attachLinkEndpoint() {
|
||||
n.attach.Do(func() {
|
||||
n.linkEP.Attach(n)
|
||||
})
|
||||
}
|
||||
|
||||
// setPromiscuousMode enables or disables promiscuous mode.
|
||||
func (n *NIC) setPromiscuousMode(enable bool) {
|
||||
n.mu.Lock()
|
||||
|
|
|
@ -881,6 +881,8 @@ type NICOptions struct {
|
|||
// CreateNICWithOptions creates a NIC with the provided id, LinkEndpoint, and
|
||||
// NICOptions. See the documentation on type NICOptions for details on how
|
||||
// NICs can be configured.
|
||||
//
|
||||
// LinkEndpoint.Attach will be called to bind ep with a NetworkDispatcher.
|
||||
func (s *Stack) CreateNICWithOptions(id tcpip.NICID, ep LinkEndpoint, opts NICOptions) *tcpip.Error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
@ -900,7 +902,6 @@ func (s *Stack) CreateNICWithOptions(id tcpip.NICID, ep LinkEndpoint, opts NICOp
|
|||
}
|
||||
|
||||
n := newNIC(s, id, opts.Name, ep, opts.Context)
|
||||
|
||||
s.nics[id] = n
|
||||
if !opts.Disabled {
|
||||
return n.enable()
|
||||
|
@ -910,7 +911,7 @@ func (s *Stack) CreateNICWithOptions(id tcpip.NICID, ep LinkEndpoint, opts NICOp
|
|||
}
|
||||
|
||||
// CreateNIC creates a NIC with the provided id and LinkEndpoint and calls
|
||||
// `LinkEndpoint.Attach` to start delivering packets to it.
|
||||
// LinkEndpoint.Attach to bind ep with a NetworkDispatcher.
|
||||
func (s *Stack) CreateNIC(id tcpip.NICID, ep LinkEndpoint) *tcpip.Error {
|
||||
return s.CreateNICWithOptions(id, ep, NICOptions{})
|
||||
}
|
||||
|
|
|
@ -239,6 +239,23 @@ func fakeNetFactory() stack.NetworkProtocol {
|
|||
return &fakeNetworkProtocol{}
|
||||
}
|
||||
|
||||
// linkEPWithMockedAttach is a stack.LinkEndpoint that tests can use to verify
|
||||
// that LinkEndpoint.Attach was called.
|
||||
type linkEPWithMockedAttach struct {
|
||||
stack.LinkEndpoint
|
||||
attached bool
|
||||
}
|
||||
|
||||
// Attach implements stack.LinkEndpoint.Attach.
|
||||
func (l *linkEPWithMockedAttach) Attach(d stack.NetworkDispatcher) {
|
||||
l.LinkEndpoint.Attach(d)
|
||||
l.attached = true
|
||||
}
|
||||
|
||||
func (l *linkEPWithMockedAttach) isAttached() bool {
|
||||
return l.attached
|
||||
}
|
||||
|
||||
func TestNetworkReceive(t *testing.T) {
|
||||
// Create a stack with the fake network protocol, one nic, and two
|
||||
// addresses attached to it: 1 & 2.
|
||||
|
@ -510,6 +527,45 @@ func testNoRoute(t *testing.T, s *stack.Stack, nic tcpip.NICID, srcAddr, dstAddr
|
|||
}
|
||||
}
|
||||
|
||||
// TestAttachToLinkEndpointImmediately tests that a LinkEndpoint is attached to
|
||||
// a NetworkDispatcher when the NIC is created.
|
||||
func TestAttachToLinkEndpointImmediately(t *testing.T) {
|
||||
const nicID = 1
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
nicOpts stack.NICOptions
|
||||
}{
|
||||
{
|
||||
name: "Create enabled NIC",
|
||||
nicOpts: stack.NICOptions{Disabled: false},
|
||||
},
|
||||
{
|
||||
name: "Create disabled NIC",
|
||||
nicOpts: stack.NICOptions{Disabled: true},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
s := stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{fakeNetFactory()},
|
||||
})
|
||||
|
||||
e := linkEPWithMockedAttach{
|
||||
LinkEndpoint: loopback.New(),
|
||||
}
|
||||
|
||||
if err := s.CreateNICWithOptions(nicID, &e, test.nicOpts); err != nil {
|
||||
t.Fatalf("CreateNICWithOptions(%d, _, %+v) = %s", nicID, test.nicOpts, err)
|
||||
}
|
||||
if !e.isAttached() {
|
||||
t.Fatalf("link endpoint not attached to a network disatcher")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableUnknownNIC(t *testing.T) {
|
||||
s := stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{fakeNetFactory()},
|
||||
|
|
Loading…
Reference in New Issue