Attach LinkEndpoint to NetworkDispatcher immediately
Tests: stack_test.TestAttachToLinkEndpointImmediately PiperOrigin-RevId: 296474068
This commit is contained in:
parent
d8e60e7867
commit
a155a23480
|
@ -44,8 +44,7 @@ type NIC struct {
|
||||||
linkEP LinkEndpoint
|
linkEP LinkEndpoint
|
||||||
context NICContext
|
context NICContext
|
||||||
|
|
||||||
stats NICStats
|
stats NICStats
|
||||||
attach sync.Once
|
|
||||||
|
|
||||||
mu struct {
|
mu struct {
|
||||||
sync.RWMutex
|
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.mu.packetEPs[netProto.Number()] = []PacketEndpoint{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nic.linkEP.Attach(nic)
|
||||||
|
|
||||||
return 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
|
n.mu.enabled = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable enables n. enable will attach the nic to its LinkEndpoint and
|
// enable enables n.
|
||||||
// join the IPv6 All-Nodes Multicast address (ff02::1).
|
//
|
||||||
|
// 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 {
|
func (n *NIC) enable() *tcpip.Error {
|
||||||
n.mu.RLock()
|
n.mu.RLock()
|
||||||
enabled := n.mu.enabled
|
enabled := n.mu.enabled
|
||||||
|
@ -225,8 +228,6 @@ func (n *NIC) enable() *tcpip.Error {
|
||||||
|
|
||||||
n.mu.enabled = true
|
n.mu.enabled = true
|
||||||
|
|
||||||
n.attachLinkEndpoint()
|
|
||||||
|
|
||||||
// Create an endpoint to receive broadcast packets on this interface.
|
// Create an endpoint to receive broadcast packets on this interface.
|
||||||
if _, ok := n.stack.networkProtocols[header.IPv4ProtocolNumber]; ok {
|
if _, ok := n.stack.networkProtocols[header.IPv4ProtocolNumber]; ok {
|
||||||
if _, err := n.addAddressLocked(ipv4BroadcastAddr, NeverPrimaryEndpoint, permanent, static, false /* deprecated */); err != nil {
|
if _, err := n.addAddressLocked(ipv4BroadcastAddr, NeverPrimaryEndpoint, permanent, static, false /* deprecated */); err != nil {
|
||||||
|
@ -321,14 +322,6 @@ func (n *NIC) becomeIPv6Host() {
|
||||||
n.mu.ndp.startSolicitingRouters()
|
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.
|
// setPromiscuousMode enables or disables promiscuous mode.
|
||||||
func (n *NIC) setPromiscuousMode(enable bool) {
|
func (n *NIC) setPromiscuousMode(enable bool) {
|
||||||
n.mu.Lock()
|
n.mu.Lock()
|
||||||
|
|
|
@ -881,6 +881,8 @@ type NICOptions struct {
|
||||||
// CreateNICWithOptions creates a NIC with the provided id, LinkEndpoint, and
|
// CreateNICWithOptions creates a NIC with the provided id, LinkEndpoint, and
|
||||||
// NICOptions. See the documentation on type NICOptions for details on how
|
// NICOptions. See the documentation on type NICOptions for details on how
|
||||||
// NICs can be configured.
|
// 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 {
|
func (s *Stack) CreateNICWithOptions(id tcpip.NICID, ep LinkEndpoint, opts NICOptions) *tcpip.Error {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
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)
|
n := newNIC(s, id, opts.Name, ep, opts.Context)
|
||||||
|
|
||||||
s.nics[id] = n
|
s.nics[id] = n
|
||||||
if !opts.Disabled {
|
if !opts.Disabled {
|
||||||
return n.enable()
|
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
|
// 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 {
|
func (s *Stack) CreateNIC(id tcpip.NICID, ep LinkEndpoint) *tcpip.Error {
|
||||||
return s.CreateNICWithOptions(id, ep, NICOptions{})
|
return s.CreateNICWithOptions(id, ep, NICOptions{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,23 @@ func fakeNetFactory() stack.NetworkProtocol {
|
||||||
return &fakeNetworkProtocol{}
|
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) {
|
func TestNetworkReceive(t *testing.T) {
|
||||||
// Create a stack with the fake network protocol, one nic, and two
|
// Create a stack with the fake network protocol, one nic, and two
|
||||||
// addresses attached to it: 1 & 2.
|
// 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) {
|
func TestDisableUnknownNIC(t *testing.T) {
|
||||||
s := stack.New(stack.Options{
|
s := stack.New(stack.Options{
|
||||||
NetworkProtocols: []stack.NetworkProtocol{fakeNetFactory()},
|
NetworkProtocols: []stack.NetworkProtocol{fakeNetFactory()},
|
||||||
|
|
Loading…
Reference in New Issue