mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Don't cleanup NDP state when enabling forwarding
...to match linux behaviour:
```
$ sudo sysctl net.ipv6.conf.eno1.forwarding
net.ipv6.conf.eno1.forwarding = 0
$ ip addr list dev eno1
2: eno1: <...> ...
inet6 PREFIX:TEMP_IID/64 scope global temporary dynamic
valid_lft 209363sec preferred_lft 64024sec
inet6 PREFIX:GLOBAL_STABLE_IID/64 scope global dynamic mngtmpaddr ...
valid_lft 209363sec preferred_lft 209363sec
inet6 fe80::LINKLOCAL_STABLE_IID/64 scope link
valid_lft forever preferred_lft forever
$ sudo sysctl -w "net.ipv6.conf.all.forwarding=1"
net.ipv6.conf.all.forwarding = 1
$ sudo sysctl net.ipv6.conf.eno1.forwarding
net.ipv6.conf.eno1.forwarding = 1
$ ip addr list dev eno1
2: eno1: <...> ...
inet6 PREFIX:TEMP_IID/64 scope global temporary dynamic
valid_lft 209339sec preferred_lft 64000sec
inet6 PREFIX:GLOBAL_STABLE_IID/64 scope global dynamic mngtmpaddr ...
valid_lft 209339sec preferred_lft 209339sec
inet6 fe80::LINKLOCAL_STABLE_IID/64 scope link
valid_lft forever preferred_lft forever
$ ip -6 route list
...
PREFIX::/64 dev eno1 proto ra metric 100 expires 209241sec pref medium
default via fe80::ROUTER_IID dev eno1 proto ra ...
```
PiperOrigin-RevId: 372146689
This commit is contained in:
committed by
gVisor bot
parent
61615f3f15
commit
bf49a847ab
@@ -420,11 +420,7 @@ func (e *endpoint) transitionForwarding(forwarding bool) {
|
||||
defer e.mu.Unlock()
|
||||
|
||||
if forwarding {
|
||||
// When transitioning into an IPv6 router, host-only state (NDP discovered
|
||||
// routers, discovered on-link prefixes, and auto-generated addresses) is
|
||||
// cleaned up/invalidated and NDP router solicitations are stopped.
|
||||
e.mu.ndp.stopSolicitingRouters()
|
||||
e.mu.ndp.cleanupState(true /* hostOnly */)
|
||||
|
||||
// As per RFC 4291 section 2.8:
|
||||
//
|
||||
@@ -613,7 +609,7 @@ func (e *endpoint) disableLocked() {
|
||||
|
||||
return true
|
||||
})
|
||||
e.mu.ndp.cleanupState(false /* hostOnly */)
|
||||
e.mu.ndp.cleanupState()
|
||||
|
||||
// The endpoint may have already left the multicast group.
|
||||
switch err := e.leaveGroupLocked(header.IPv6AllNodesMulticastAddress).(type) {
|
||||
|
||||
@@ -1609,44 +1609,16 @@ func (ndp *ndpState) cleanupTempSLAACAddrResourcesAndNotifyInner(tempAddrs map[t
|
||||
delete(tempAddrs, tempAddr)
|
||||
}
|
||||
|
||||
// removeSLAACAddresses removes all SLAAC addresses.
|
||||
//
|
||||
// If keepLinkLocal is false, the SLAAC generated link-local address is removed.
|
||||
//
|
||||
// The IPv6 endpoint that ndp belongs to MUST be locked.
|
||||
func (ndp *ndpState) removeSLAACAddresses(keepLinkLocal bool) {
|
||||
linkLocalSubnet := header.IPv6LinkLocalPrefix.Subnet()
|
||||
var linkLocalPrefixes int
|
||||
for prefix, state := range ndp.slaacPrefixes {
|
||||
// RFC 4862 section 5 states that routers are also expected to generate a
|
||||
// link-local address so we do not invalidate them if we are cleaning up
|
||||
// host-only state.
|
||||
if keepLinkLocal && prefix == linkLocalSubnet {
|
||||
linkLocalPrefixes++
|
||||
continue
|
||||
}
|
||||
|
||||
ndp.invalidateSLAACPrefix(prefix, state)
|
||||
}
|
||||
|
||||
if got := len(ndp.slaacPrefixes); got != linkLocalPrefixes {
|
||||
panic(fmt.Sprintf("ndp: still have non-linklocal SLAAC prefixes after cleaning up; found = %d prefixes, of which %d are link-local", got, linkLocalPrefixes))
|
||||
}
|
||||
}
|
||||
|
||||
// cleanupState cleans up ndp's state.
|
||||
//
|
||||
// If hostOnly is true, then only host-specific state is cleaned up.
|
||||
//
|
||||
// This function invalidates all discovered on-link prefixes, discovered
|
||||
// routers, and auto-generated addresses.
|
||||
//
|
||||
// If hostOnly is true, then the link-local auto-generated address aren't
|
||||
// invalidated as routers are also expected to generate a link-local address.
|
||||
//
|
||||
// The IPv6 endpoint that ndp belongs to MUST be locked.
|
||||
func (ndp *ndpState) cleanupState(hostOnly bool) {
|
||||
ndp.removeSLAACAddresses(hostOnly /* keepLinkLocal */)
|
||||
func (ndp *ndpState) cleanupState() {
|
||||
for prefix, state := range ndp.slaacPrefixes {
|
||||
ndp.invalidateSLAACPrefix(prefix, state)
|
||||
}
|
||||
|
||||
for prefix := range ndp.onLinkPrefixes {
|
||||
ndp.invalidateOnLinkPrefix(prefix)
|
||||
|
||||
+104
-14
@@ -4629,8 +4629,110 @@ func TestNDPDNSSearchListDispatch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCleanupNDPState tests that all discovered routers and prefixes, and
|
||||
// auto-generated addresses are invalidated when a NIC becomes a router.
|
||||
func TestNoCleanupNDPStateWhenForwardingEnabled(t *testing.T) {
|
||||
const (
|
||||
lifetimeSeconds = 999
|
||||
nicID = 1
|
||||
)
|
||||
|
||||
ndpDisp := ndpDispatcher{
|
||||
routerC: make(chan ndpRouterEvent, 1),
|
||||
rememberRouter: true,
|
||||
prefixC: make(chan ndpPrefixEvent, 1),
|
||||
rememberPrefix: true,
|
||||
autoGenAddrC: make(chan ndpAutoGenAddrEvent, 1),
|
||||
}
|
||||
s := stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocolWithOptions(ipv6.Options{
|
||||
AutoGenLinkLocal: true,
|
||||
NDPConfigs: ipv6.NDPConfigurations{
|
||||
HandleRAs: true,
|
||||
DiscoverDefaultRouters: true,
|
||||
DiscoverOnLinkPrefixes: true,
|
||||
AutoGenGlobalAddresses: true,
|
||||
},
|
||||
NDPDisp: &ndpDisp,
|
||||
})},
|
||||
})
|
||||
|
||||
e1 := channel.New(0, header.IPv6MinimumMTU, linkAddr1)
|
||||
if err := s.CreateNIC(nicID, e1); err != nil {
|
||||
t.Fatalf("CreateNIC(%d, _) = %s", nicID, err)
|
||||
}
|
||||
llAddr := tcpip.AddressWithPrefix{Address: llAddr1, PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen}
|
||||
select {
|
||||
case e := <-ndpDisp.autoGenAddrC:
|
||||
if diff := checkAutoGenAddrEvent(e, llAddr, newAddr); diff != "" {
|
||||
t.Errorf("auto-gen addr mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
default:
|
||||
t.Errorf("expected auto-gen addr event for %s on NIC(%d)", llAddr, nicID)
|
||||
}
|
||||
|
||||
prefix, subnet, addr := prefixSubnetAddr(0, linkAddr1)
|
||||
e1.InjectInbound(
|
||||
header.IPv6ProtocolNumber,
|
||||
raBufWithPI(
|
||||
llAddr3,
|
||||
lifetimeSeconds,
|
||||
prefix,
|
||||
true, /* onLink */
|
||||
true, /* auto */
|
||||
lifetimeSeconds,
|
||||
lifetimeSeconds,
|
||||
),
|
||||
)
|
||||
select {
|
||||
case e := <-ndpDisp.routerC:
|
||||
if diff := checkRouterEvent(e, llAddr3, true /* discovered */); diff != "" {
|
||||
t.Errorf("router event mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
default:
|
||||
t.Errorf("expected router event for %s on NIC(%d)", llAddr3, nicID)
|
||||
}
|
||||
select {
|
||||
case e := <-ndpDisp.prefixC:
|
||||
if diff := checkPrefixEvent(e, subnet, true /* discovered */); diff != "" {
|
||||
t.Errorf("router event mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
default:
|
||||
t.Errorf("expected prefix event for %s on NIC(%d)", prefix, nicID)
|
||||
}
|
||||
select {
|
||||
case e := <-ndpDisp.autoGenAddrC:
|
||||
if diff := checkAutoGenAddrEvent(e, addr, newAddr); diff != "" {
|
||||
t.Errorf("auto-gen addr mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
default:
|
||||
t.Errorf("expected auto-gen addr event for %s on NIC(%d)", addr, nicID)
|
||||
}
|
||||
|
||||
// Enabling or disabling forwarding should not invalidate discovered prefixes
|
||||
// or routers, or auto-generated address.
|
||||
for _, forwarding := range [...]bool{true, false} {
|
||||
t.Run(fmt.Sprintf("Transition forwarding to %t", forwarding), func(t *testing.T) {
|
||||
if err := s.SetForwarding(ipv6.ProtocolNumber, forwarding); err != nil {
|
||||
t.Fatalf("SetForwarding(%d, %t): %s", ipv6.ProtocolNumber, forwarding, err)
|
||||
}
|
||||
select {
|
||||
case e := <-ndpDisp.routerC:
|
||||
t.Errorf("unexpected router event = %#v", e)
|
||||
default:
|
||||
}
|
||||
select {
|
||||
case e := <-ndpDisp.prefixC:
|
||||
t.Errorf("unexpected prefix event = %#v", e)
|
||||
default:
|
||||
}
|
||||
select {
|
||||
case e := <-ndpDisp.autoGenAddrC:
|
||||
t.Errorf("unexpected auto-gen addr event = %#v", e)
|
||||
default:
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupNDPState(t *testing.T) {
|
||||
const (
|
||||
lifetimeSeconds = 5
|
||||
@@ -4659,18 +4761,6 @@ func TestCleanupNDPState(t *testing.T) {
|
||||
maxAutoGenAddrEvents int
|
||||
skipFinalAddrCheck bool
|
||||
}{
|
||||
// A NIC should still keep its auto-generated link-local address when
|
||||
// becoming a router.
|
||||
{
|
||||
name: "Enable forwarding",
|
||||
cleanupFn: func(t *testing.T, s *stack.Stack) {
|
||||
t.Helper()
|
||||
s.SetForwarding(ipv6.ProtocolNumber, true)
|
||||
},
|
||||
keepAutoGenLinkLocal: true,
|
||||
maxAutoGenAddrEvents: 4,
|
||||
},
|
||||
|
||||
// A NIC should cleanup all NDP state when it is disabled.
|
||||
{
|
||||
name: "Disable NIC",
|
||||
|
||||
Reference in New Issue
Block a user