summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-11-30 22:27:48 +0000
committergVisor bot <gvisor-bot@google.com>2020-11-30 22:27:48 +0000
commite236d392b180e164b6631d18d64ff2f69a374446 (patch)
tree6cbb7f1e4727d4d552034960cb267c1429263902 /pkg
parent5b624f21ee562ccc0b9fe64bb8a0243b0daffc40 (diff)
parente813008664ffb361211936dda8631754411cca4f (diff)
Merge release-20201117.0-78-ge81300866 (automated)
Diffstat (limited to 'pkg')
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go34
-rw-r--r--pkg/tcpip/network/ipv6/ipv6.go34
-rw-r--r--pkg/tcpip/stack/addressable_endpoint_state.go11
3 files changed, 67 insertions, 12 deletions
diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index be9c8e2f9..ce2087002 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -123,6 +123,15 @@ func (e *endpoint) Enable() *tcpip.Error {
// We have no need for the address endpoint.
ep.DecRef()
+ // Groups may have been joined while the endpoint was disabled, or the
+ // endpoint may have left groups from the perspective of IGMP when the
+ // endpoint was disabled. Either way, we need to let routers know to
+ // send us multicast traffic.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.igmp.joinGroup(group)
+ }
+
// As per RFC 1122 section 3.3.7, all hosts should join the all-hosts
// multicast group. Note, the IANA calls the all-hosts multicast group the
// all-systems multicast group.
@@ -168,6 +177,13 @@ func (e *endpoint) disableLocked() {
panic(fmt.Sprintf("unexpected error when leaving group = %s: %s", header.IPv4AllSystems, err))
}
+ // Leave groups from the perspective of IGMP so that routers know that
+ // we are no longer interested in the group.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.igmp.leaveGroup(group)
+ }
+
// The address may have already been removed.
if err := e.mu.addressableEndpointState.RemovePermanentAddress(ipv4BroadcastAddr.Address); err != nil && err != tcpip.ErrBadLocalAddress {
panic(fmt.Sprintf("unexpected error when removing address = %s: %s", ipv4BroadcastAddr.Address, err))
@@ -853,6 +869,15 @@ func (e *endpoint) joinGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
return joined, err
}
+ // Only join the group from the perspective of IGMP when the endpoint is
+ // enabled.
+ //
+ // If we are not enabled right now, we will join the group from the
+ // perspective of IGMP when the endpoint is enabled.
+ if !e.Enabled() {
+ return true, nil
+ }
+
// joinGroup only returns an error if we try to join a group twice, but we
// checked above to make sure that the group was newly joined.
if err := e.igmp.joinGroup(addr); err != nil {
@@ -874,15 +899,12 @@ func (e *endpoint) LeaveGroup(addr tcpip.Address) (bool, *tcpip.Error) {
// Precondition: e.mu must be locked.
func (e *endpoint) leaveGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
left, err := e.mu.addressableEndpointState.LeaveGroup(addr)
- if err != nil {
+ if err != nil || !left {
return left, err
}
- if left {
- e.igmp.leaveGroup(addr)
- }
-
- return left, nil
+ e.igmp.leaveGroup(addr)
+ return true, nil
}
// IsInGroup implements stack.GroupAddressableEndpoint.
diff --git a/pkg/tcpip/network/ipv6/ipv6.go b/pkg/tcpip/network/ipv6/ipv6.go
index ac67d4ac5..4d49afcbb 100644
--- a/pkg/tcpip/network/ipv6/ipv6.go
+++ b/pkg/tcpip/network/ipv6/ipv6.go
@@ -228,6 +228,15 @@ func (e *endpoint) Enable() *tcpip.Error {
return nil
}
+ // Groups may have been joined when the endpoint was disabled, or the
+ // endpoint may have left groups from the perspective of MLD when the
+ // endpoint was disabled. Either way, we need to let routers know to
+ // send us multicast traffic.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.mld.joinGroup(group)
+ }
+
// Join the IPv6 All-Nodes Multicast group if the stack is configured to
// use IPv6. This is required to ensure that this node properly receives
// and responds to the various NDP messages that are destined to the
@@ -338,6 +347,13 @@ func (e *endpoint) disableLocked() {
if _, err := e.leaveGroupLocked(header.IPv6AllNodesMulticastAddress); err != nil && err != tcpip.ErrBadLocalAddress {
panic(fmt.Sprintf("unexpected error when leaving group = %s: %s", header.IPv6AllNodesMulticastAddress, err))
}
+
+ // Leave groups from the perspective of MLD so that routers know that
+ // we are no longer interested in the group.
+ joinedGroups := e.mu.addressableEndpointState.JoinedGroups()
+ for _, group := range joinedGroups {
+ e.mld.leaveGroup(group)
+ }
}
// stopDADForPermanentAddressesLocked stops DAD for all permaneent addresses.
@@ -1409,6 +1425,15 @@ func (e *endpoint) joinGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
return joined, err
}
+ // Only join the group from the perspective of IGMP when the endpoint is
+ // enabled.
+ //
+ // If we are not enabled right now, we will join the group from the
+ // perspective of MLD when the endpoint is enabled.
+ if !e.Enabled() {
+ return true, nil
+ }
+
// joinGroup only returns an error if we try to join a group twice, but we
// checked above to make sure that the group was newly joined.
if err := e.mld.joinGroup(addr); err != nil {
@@ -1430,15 +1455,12 @@ func (e *endpoint) LeaveGroup(addr tcpip.Address) (bool, *tcpip.Error) {
// Precondition: e.mu must be locked.
func (e *endpoint) leaveGroupLocked(addr tcpip.Address) (bool, *tcpip.Error) {
left, err := e.mu.addressableEndpointState.LeaveGroup(addr)
- if err != nil {
+ if err != nil || !left {
return left, err
}
- if left {
- e.mld.leaveGroup(addr)
- }
-
- return left, nil
+ e.mld.leaveGroup(addr)
+ return true, nil
}
// IsInGroup implements stack.GroupAddressableEndpoint.
diff --git a/pkg/tcpip/stack/addressable_endpoint_state.go b/pkg/tcpip/stack/addressable_endpoint_state.go
index adeebfe37..6e855d815 100644
--- a/pkg/tcpip/stack/addressable_endpoint_state.go
+++ b/pkg/tcpip/stack/addressable_endpoint_state.go
@@ -625,6 +625,17 @@ func (a *AddressableEndpointState) IsInGroup(group tcpip.Address) bool {
return ok
}
+// JoinedGroups returns a list of groups the endpoint is a member of.
+func (a *AddressableEndpointState) JoinedGroups() []tcpip.Address {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ groups := make([]tcpip.Address, 0, len(a.mu.groups))
+ for g := range a.mu.groups {
+ groups = append(groups, g)
+ }
+ return groups
+}
+
// Cleanup forcefully leaves all groups and removes all permanent addresses.
func (a *AddressableEndpointState) Cleanup() {
a.mu.Lock()