summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/tcpip/network/ip/generic_multicast_protocol.go11
-rw-r--r--pkg/tcpip/network/ipv4/igmp.go12
-rw-r--r--pkg/tcpip/network/ipv6/mld.go7
3 files changed, 23 insertions, 7 deletions
diff --git a/pkg/tcpip/network/ip/generic_multicast_protocol.go b/pkg/tcpip/network/ip/generic_multicast_protocol.go
index bc7f7f637..c8c17ab15 100644
--- a/pkg/tcpip/network/ip/generic_multicast_protocol.go
+++ b/pkg/tcpip/network/ip/generic_multicast_protocol.go
@@ -161,7 +161,8 @@ type GenericMulticastProtocolState struct {
// Init initializes the Generic Multicast Protocol state.
//
-// Must only be called once for the lifetime of g.
+// Must only be called once for the lifetime of g; Init will panic if it is
+// called twice.
//
// The GenericMulticastProtocolState will only grab the lock when timers/jobs
// fire.
@@ -170,9 +171,11 @@ func (g *GenericMulticastProtocolState) Init(protocolMU *sync.RWMutex, opts Gene
panic("attempted to initialize generic membership protocol state twice")
}
- g.opts = opts
- g.memberships = make(map[tcpip.Address]multicastGroupState)
- g.protocolMU = protocolMU
+ *g = GenericMulticastProtocolState{
+ opts: opts,
+ memberships: make(map[tcpip.Address]multicastGroupState),
+ protocolMU: protocolMU,
+ }
}
// MakeAllNonMemberLocked transitions all groups to the non-member state.
diff --git a/pkg/tcpip/network/ipv4/igmp.go b/pkg/tcpip/network/ipv4/igmp.go
index 2ee4c6445..a3a7176a0 100644
--- a/pkg/tcpip/network/ipv4/igmp.go
+++ b/pkg/tcpip/network/ipv4/igmp.go
@@ -57,6 +57,9 @@ type IGMPOptions struct {
// When enabled, IGMP may transmit IGMP report and leave messages when
// joining and leaving multicast groups respectively, and handle incoming
// IGMP packets.
+ //
+ // This field is ignored and is always assumed to be false for interfaces
+ // without neighbouring nodes (e.g. loopback).
Enabled bool
}
@@ -69,6 +72,8 @@ type igmpState struct {
// The IPv4 endpoint this igmpState is for.
ep *endpoint
+ enabled bool
+
genericMulticastProtocol ip.GenericMulticastProtocolState
// igmpV1Present is for maintaining compatibility with IGMPv1 Routers, from
@@ -117,8 +122,11 @@ func (igmp *igmpState) SendLeave(groupAddress tcpip.Address) *tcpip.Error {
// Must only be called once for the lifetime of igmp.
func (igmp *igmpState) init(ep *endpoint) {
igmp.ep = ep
+ // No need to perform IGMP on loopback interfaces since they don't have
+ // neighbouring nodes.
+ igmp.enabled = ep.protocol.options.IGMP.Enabled && !igmp.ep.nic.IsLoopback()
igmp.genericMulticastProtocol.Init(&ep.mu.RWMutex, ip.GenericMulticastProtocolOptions{
- Enabled: ep.protocol.options.IGMP.Enabled,
+ Enabled: igmp.enabled,
Rand: ep.protocol.stack.Rand(),
Clock: ep.protocol.stack.Clock(),
Protocol: igmp,
@@ -210,7 +218,7 @@ func (igmp *igmpState) handleMembershipQuery(groupAddress tcpip.Address, maxResp
// As per RFC 2236 Section 6, Page 10: If the maximum response time is zero
// then change the state to note that an IGMPv1 router is present and
// schedule the query received Job.
- if maxRespTime == 0 && igmp.ep.protocol.options.IGMP.Enabled {
+ if igmp.enabled && maxRespTime == 0 {
igmp.igmpV1Job.Cancel()
igmp.igmpV1Job.Schedule(v1RouterPresentTimeout)
igmp.setV1Present(true)
diff --git a/pkg/tcpip/network/ipv6/mld.go b/pkg/tcpip/network/ipv6/mld.go
index 6face17c6..b67eafdba 100644
--- a/pkg/tcpip/network/ipv6/mld.go
+++ b/pkg/tcpip/network/ipv6/mld.go
@@ -40,6 +40,9 @@ type MLDOptions struct {
// When enabled, MLD may transmit MLD report and done messages when
// joining and leaving multicast groups respectively, and handle incoming
// MLD packets.
+ //
+ // This field is ignored and is always assumed to be false for interfaces
+ // without neighbouring nodes (e.g. loopback).
Enabled bool
}
@@ -72,7 +75,9 @@ func (mld *mldState) SendLeave(groupAddress tcpip.Address) *tcpip.Error {
func (mld *mldState) init(ep *endpoint) {
mld.ep = ep
mld.genericMulticastProtocol.Init(&ep.mu.RWMutex, ip.GenericMulticastProtocolOptions{
- Enabled: ep.protocol.options.MLD.Enabled,
+ // No need to perform MLD on loopback interfaces since they don't have
+ // neighbouring nodes.
+ Enabled: ep.protocol.options.MLD.Enabled && !mld.ep.nic.IsLoopback(),
Rand: ep.protocol.stack.Rand(),
Clock: ep.protocol.stack.Clock(),
Protocol: mld,