summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/ipv4
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-12-09 23:53:49 +0000
committergVisor bot <gvisor-bot@google.com>2020-12-09 23:53:49 +0000
commit514d725e13413423d5661e7d077560bbaed17bfc (patch)
tree53e80f82fe90e80bd067380af59b8333eaf5dd55 /pkg/tcpip/network/ipv4
parentac25d064734e7113fb7cc66fbeee1aff412ebdef (diff)
parent96d14de0fa51d6c7fd5a34c69f27caf76a26f7aa (diff)
Merge release-20201130.0-65-g96d14de0f (automated)
Diffstat (limited to 'pkg/tcpip/network/ipv4')
-rw-r--r--pkg/tcpip/network/ipv4/igmp.go88
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go20
2 files changed, 54 insertions, 54 deletions
diff --git a/pkg/tcpip/network/ipv4/igmp.go b/pkg/tcpip/network/ipv4/igmp.go
index 0134fadc0..2ee4c6445 100644
--- a/pkg/tcpip/network/ipv4/igmp.go
+++ b/pkg/tcpip/network/ipv4/igmp.go
@@ -16,7 +16,6 @@ package ipv4
import (
"fmt"
- "sync"
"sync/atomic"
"time"
@@ -68,8 +67,9 @@ var _ ip.MulticastGroupProtocol = (*igmpState)(nil)
// igmpState.init() MUST be called after creating an IGMP state.
type igmpState struct {
// The IPv4 endpoint this igmpState is for.
- ep *endpoint
- opts IGMPOptions
+ ep *endpoint
+
+ genericMulticastProtocol ip.GenericMulticastProtocolState
// igmpV1Present is for maintaining compatibility with IGMPv1 Routers, from
// RFC 2236 Section 4 Page 6: "The IGMPv1 router expects Version 1
@@ -84,16 +84,10 @@ type igmpState struct {
// when false.
igmpV1Present uint32
- mu struct {
- sync.RWMutex
-
- genericMulticastProtocol ip.GenericMulticastProtocolState
-
- // igmpV1Job is scheduled when this interface receives an IGMPv1 style
- // message, upon expiration the igmpV1Present flag is cleared.
- // igmpV1Job may not be nil once igmpState is initialized.
- igmpV1Job *tcpip.Job
- }
+ // igmpV1Job is scheduled when this interface receives an IGMPv1 style
+ // message, upon expiration the igmpV1Present flag is cleared.
+ // igmpV1Job may not be nil once igmpState is initialized.
+ igmpV1Job *tcpip.Job
}
// SendReport implements ip.MulticastGroupProtocol.
@@ -119,13 +113,12 @@ func (igmp *igmpState) SendLeave(groupAddress tcpip.Address) *tcpip.Error {
// init sets up an igmpState struct, and is required to be called before using
// a new igmpState.
-func (igmp *igmpState) init(ep *endpoint, opts IGMPOptions) {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
+//
+// Must only be called once for the lifetime of igmp.
+func (igmp *igmpState) init(ep *endpoint) {
igmp.ep = ep
- igmp.opts = opts
- igmp.mu.genericMulticastProtocol.Init(ip.GenericMulticastProtocolOptions{
- Enabled: opts.Enabled,
+ igmp.genericMulticastProtocol.Init(&ep.mu.RWMutex, ip.GenericMulticastProtocolOptions{
+ Enabled: ep.protocol.options.IGMP.Enabled,
Rand: ep.protocol.stack.Rand(),
Clock: ep.protocol.stack.Clock(),
Protocol: igmp,
@@ -133,11 +126,14 @@ func (igmp *igmpState) init(ep *endpoint, opts IGMPOptions) {
AllNodesAddress: header.IPv4AllSystems,
})
igmp.igmpV1Present = igmpV1PresentDefault
- igmp.mu.igmpV1Job = igmp.ep.protocol.stack.NewJob(&igmp.mu, func() {
+ igmp.igmpV1Job = ep.protocol.stack.NewJob(&ep.mu, func() {
igmp.setV1Present(false)
})
}
+// handleIGMP handles an IGMP packet.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) handleIGMP(pkt *stack.PacketBuffer) {
stats := igmp.ep.protocol.stack.Stats()
received := stats.IGMP.PacketsReceived
@@ -207,27 +203,28 @@ func (igmp *igmpState) setV1Present(v bool) {
}
}
+// handleMembershipQuery handles a membership query.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) handleMembershipQuery(groupAddress tcpip.Address, maxRespTime time.Duration) {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
-
// 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.opts.Enabled {
- igmp.mu.igmpV1Job.Cancel()
- igmp.mu.igmpV1Job.Schedule(v1RouterPresentTimeout)
+ if maxRespTime == 0 && igmp.ep.protocol.options.IGMP.Enabled {
+ igmp.igmpV1Job.Cancel()
+ igmp.igmpV1Job.Schedule(v1RouterPresentTimeout)
igmp.setV1Present(true)
maxRespTime = v1MaxRespTime
}
- igmp.mu.genericMulticastProtocol.HandleQuery(groupAddress, maxRespTime)
+ igmp.genericMulticastProtocol.HandleQueryLocked(groupAddress, maxRespTime)
}
+// handleMembershipReport handles a membership report.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) handleMembershipReport(groupAddress tcpip.Address) {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
- igmp.mu.genericMulticastProtocol.HandleReport(groupAddress)
+ igmp.genericMulticastProtocol.HandleReportLocked(groupAddress)
}
// writePacket assembles and sends an IGMP packet with the provided fields,
@@ -278,28 +275,27 @@ func (igmp *igmpState) writePacket(destAddress tcpip.Address, groupAddress tcpip
//
// If the group already exists in the membership map, returns
// tcpip.ErrDuplicateAddress.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) joinGroup(groupAddress tcpip.Address) {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
- igmp.mu.genericMulticastProtocol.JoinGroup(groupAddress, !igmp.ep.Enabled() /* dontInitialize */)
+ igmp.genericMulticastProtocol.JoinGroupLocked(groupAddress, !igmp.ep.Enabled() /* dontInitialize */)
}
// isInGroup returns true if the specified group has been joined locally.
+//
+// Precondition: igmp.ep.mu must be read locked.
func (igmp *igmpState) isInGroup(groupAddress tcpip.Address) bool {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
- return igmp.mu.genericMulticastProtocol.IsLocallyJoined(groupAddress)
+ return igmp.genericMulticastProtocol.IsLocallyJoinedRLocked(groupAddress)
}
// leaveGroup handles removing the group from the membership map, cancels any
// delay timers associated with that group, and sends the Leave Group message
// if required.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) leaveGroup(groupAddress tcpip.Address) *tcpip.Error {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
-
// LeaveGroup returns false only if the group was not joined.
- if igmp.mu.genericMulticastProtocol.LeaveGroup(groupAddress) {
+ if igmp.genericMulticastProtocol.LeaveGroupLocked(groupAddress) {
return nil
}
@@ -308,16 +304,16 @@ func (igmp *igmpState) leaveGroup(groupAddress tcpip.Address) *tcpip.Error {
// softLeaveAll leaves all groups from the perspective of IGMP, but remains
// joined locally.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) softLeaveAll() {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
- igmp.mu.genericMulticastProtocol.MakeAllNonMember()
+ igmp.genericMulticastProtocol.MakeAllNonMemberLocked()
}
// initializeAll attemps to initialize the IGMP state for each group that has
// been joined locally.
+//
+// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) initializeAll() {
- igmp.mu.Lock()
- defer igmp.mu.Unlock()
- igmp.mu.genericMulticastProtocol.InitializeGroups()
+ igmp.genericMulticastProtocol.InitializeGroupsLocked()
}
diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index 3076185cd..c63ecca4a 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -72,7 +72,6 @@ type endpoint struct {
nic stack.NetworkInterface
dispatcher stack.TransportDispatcher
protocol *protocol
- igmp igmpState
// enabled is set to 1 when the enpoint is enabled and 0 when it is
// disabled.
@@ -84,6 +83,7 @@ type endpoint struct {
sync.RWMutex
addressableEndpointState stack.AddressableEndpointState
+ igmp igmpState
}
}
@@ -94,8 +94,10 @@ func (p *protocol) NewEndpoint(nic stack.NetworkInterface, _ stack.LinkAddressCa
dispatcher: dispatcher,
protocol: p,
}
+ e.mu.Lock()
e.mu.addressableEndpointState.Init(e)
- e.igmp.init(e, p.options.IGMP)
+ e.mu.igmp.init(e)
+ e.mu.Unlock()
return e
}
@@ -127,7 +129,7 @@ func (e *endpoint) Enable() *tcpip.Error {
// 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.
- e.igmp.initializeAll()
+ e.mu.igmp.initializeAll()
// 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
@@ -181,7 +183,7 @@ func (e *endpoint) disableLocked() {
// Leave groups from the perspective of IGMP so that routers know that
// we are no longer interested in the group.
- e.igmp.softLeaveAll()
+ e.mu.igmp.softLeaveAll()
// The address may have already been removed.
if err := e.mu.addressableEndpointState.RemovePermanentAddress(ipv4BroadcastAddr.Address); err != nil && err != tcpip.ErrBadLocalAddress {
@@ -718,7 +720,9 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
return
}
if p == header.IGMPProtocolNumber {
- e.igmp.handleIGMP(pkt)
+ e.mu.Lock()
+ e.mu.igmp.handleIGMP(pkt)
+ e.mu.Unlock()
return
}
if opts := h.Options(); len(opts) != 0 {
@@ -843,7 +847,7 @@ func (e *endpoint) joinGroupLocked(addr tcpip.Address) *tcpip.Error {
return tcpip.ErrBadAddress
}
- e.igmp.joinGroup(addr)
+ e.mu.igmp.joinGroup(addr)
return nil
}
@@ -858,14 +862,14 @@ func (e *endpoint) LeaveGroup(addr tcpip.Address) *tcpip.Error {
//
// Precondition: e.mu must be locked.
func (e *endpoint) leaveGroupLocked(addr tcpip.Address) *tcpip.Error {
- return e.igmp.leaveGroup(addr)
+ return e.mu.igmp.leaveGroup(addr)
}
// IsInGroup implements stack.GroupAddressableEndpoint.
func (e *endpoint) IsInGroup(addr tcpip.Address) bool {
e.mu.RLock()
defer e.mu.RUnlock()
- return e.igmp.isInGroup(addr)
+ return e.mu.igmp.isInGroup(addr)
}
var _ stack.ForwardingNetworkProtocol = (*protocol)(nil)