Return current IGMP/MLD version

Updates #8346

PiperOrigin-RevId: 508218820
This commit is contained in:
Ghanan Gowripalan
2023-02-08 16:48:42 -08:00
committed by gVisor bot
parent c15ea6da04
commit a5ac059e27
8 changed files with 123 additions and 33 deletions
@@ -292,38 +292,45 @@ type GenericMulticastProtocolState struct {
stateChangedReportV2TimerSet bool
}
// GetV1ModeLocked returns the V1 configuration.
//
// Precondition: g.protocolMU must be read locked.
func (g *GenericMulticastProtocolState) GetV1ModeLocked() bool {
switch g.mode {
case protocolModeV2, protocolModeV1Compatibility:
return false
case protocolModeV1:
return true
default:
panic(fmt.Sprintf("unrecognized mode = %d", g.mode))
}
}
func (g *GenericMulticastProtocolState) stopModeTimer() {
if g.modeTimer != nil {
g.modeTimer.Stop()
}
}
// SetV1ModeLocked sets the V1 configuration.
//
// Returns the previous configuration.
//
// Precondition: g.protocolMU must be locked.
func (g *GenericMulticastProtocolState) SetV1ModeLocked(v bool) bool {
if g.GetV1ModeLocked() == v {
return v
}
if v {
switch g.mode {
case protocolModeV2:
g.cancelV2ReportTimers()
case protocolModeV1Compatibility:
g.modeTimer.Stop()
case protocolModeV1:
// Already in V1 mode; nothing to do.
return true
default:
panic(fmt.Sprintf("unrecognized mode = %d", g.mode))
}
g.stopModeTimer()
g.cancelV2ReportTimers()
g.mode = protocolModeV1
return false
}
switch g.mode {
case protocolModeV2, protocolModeV1Compatibility:
// Not in V1 mode; nothing to do.
return false
case protocolModeV1:
g.mode = protocolModeV2
return true
default:
panic(fmt.Sprintf("unrecognized mode = %d", g.mode))
}
g.mode = protocolModeV2
return true
}
func (g *GenericMulticastProtocolState) cancelV2ReportTimers() {
@@ -375,9 +382,7 @@ func (g *GenericMulticastProtocolState) MakeAllNonMemberLocked() {
return
}
if g.modeTimer != nil {
g.modeTimer.Stop()
}
g.stopModeTimer()
g.cancelV2ReportTimers()
var v2ReportBuilder MulticastGroupProtocolV2ReportBuilder
@@ -88,6 +88,12 @@ func (m *mockMulticastGroupProtocol) setV1Mode(v bool) bool {
return m.mu.genericMulticastGroup.SetV1ModeLocked(v)
}
func (m *mockMulticastGroupProtocol) getV1Mode() bool {
m.mu.RLock()
defer m.mu.RUnlock()
return m.mu.genericMulticastGroup.GetV1ModeLocked()
}
func (m *mockMulticastGroupProtocol) joinGroup(addr tcpip.Address) {
m.mu.Lock()
defer m.mu.Unlock()
@@ -1506,7 +1512,7 @@ func TestQueuedPackets(t *testing.T) {
}
}
func TestSetV1Mode(t *testing.T) {
func TestGetSetV1Mode(t *testing.T) {
clock := faketime.NewManualClock()
mgp := mockMulticastGroupProtocol{t: t}
mgp.init(ip.GenericMulticastProtocolOptions{
@@ -1515,6 +1521,10 @@ func TestSetV1Mode(t *testing.T) {
MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
}, false /* v1Compatibility */)
if mgp.getV1Mode() {
t.Error("got mgp.getV1Mode() = true, want = false")
}
mgp.joinGroup(addr1)
if diff := mgp.check(checkFields{sentV2Reports: []mockReportV2{{records: []mockReportV2Record{
{
@@ -1528,6 +1538,9 @@ func TestSetV1Mode(t *testing.T) {
if mgp.setV1Mode(true) {
t.Error("got mgp.setV1Mode(true) = true, want = false")
}
if !mgp.getV1Mode() {
t.Error("got mgp.getV1Mode() = false, want = true")
}
mgp.joinGroup(addr2)
if diff := mgp.check(checkFields{sendReportGroupAddresses: []tcpip.Address{addr2}}); diff != "" {
t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
@@ -1536,6 +1549,9 @@ func TestSetV1Mode(t *testing.T) {
if !mgp.setV1Mode(false) {
t.Error("got mgp.setV1Mode(false) = false, want = true")
}
if mgp.getV1Mode() {
t.Error("got mgp.getV1Mode() = true, want = false")
}
mgp.joinGroup(addr3)
if diff := mgp.check(checkFields{sentV2Reports: []mockReportV2{{records: []mockReportV2Record{
{
+18 -4
View File
@@ -80,10 +80,13 @@ const (
// IGMPEndpoint is a network endpoint that supports IGMP.
type IGMPEndpoint interface {
// Sets the IGMP version.
// SetIGMPVersion sets the IGMP version.
//
// Returns the previous IGMP version.
SetIGMPVersion(IGMPVersion) IGMPVersion
// GetIGMPVersion returns the IGMP version.
GetIGMPVersion() IGMPVersion
}
// IGMPOptions holds options for IGMP.
@@ -622,15 +625,26 @@ func (igmp *igmpState) setVersion(v IGMPVersion) IGMPVersion {
panic(fmt.Sprintf("unrecognized version = %d", v))
}
switch prev {
return toIGMPVersion(prev, prevGenericModeV1)
}
func toIGMPVersion(mode protocolMode, genericV1 bool) IGMPVersion {
switch mode {
case protocolModeV2OrV3, protocolModeV1Compatibility:
if prevGenericModeV1 {
if genericV1 {
return IGMPVersion2
}
return IGMPVersion3
case protocolModeV1:
return IGMPVersion1
default:
panic(fmt.Sprintf("unrecognized mode = %d", igmp.mode))
panic(fmt.Sprintf("unrecognized mode = %d", mode))
}
}
// getVersion returns the IGMP version.
//
// +checklocksread:igmp.ep.mu
func (igmp *igmpState) getVersion() IGMPVersion {
return toIGMPVersion(igmp.mode, igmp.genericMulticastProtocol.GetV1ModeLocked())
}
+13 -1
View File
@@ -509,7 +509,7 @@ func TestIGMPPacketValidation(t *testing.T) {
}
}
func TestSetIGMPVersion(t *testing.T) {
func TestGetSetIGMPVersion(t *testing.T) {
const nicID = 1
c := newIGMPTestContext(t, true /* igmpEnabled */)
@@ -525,6 +525,9 @@ func TestSetIGMPVersion(t *testing.T) {
if !ok {
t.Fatalf("got (%T).(%T) = (_, false), want = (_ true)", ep, igmpEP)
}
if got := igmpEP.GetIGMPVersion(); got != ipv4.IGMPVersion3 {
t.Errorf("got igmpEP.GetIGMPVersion() = %d, want = %d", got, ipv4.IGMPVersion3)
}
protocolAddr := tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
@@ -547,6 +550,9 @@ func TestSetIGMPVersion(t *testing.T) {
if got := igmpEP.SetIGMPVersion(ipv4.IGMPVersion2); got != ipv4.IGMPVersion3 {
t.Errorf("got igmpEP.SetIGMPVersion(%d) = %d, want = %d", ipv4.IGMPVersion2, got, ipv4.IGMPVersion3)
}
if got := igmpEP.GetIGMPVersion(); got != ipv4.IGMPVersion2 {
t.Errorf("got igmpEP.GetIGMPVersion() = %d, want = %d", got, ipv4.IGMPVersion2)
}
if err := s.JoinGroup(ipv4.ProtocolNumber, nicID, multicastAddr2); err != nil {
t.Fatalf("JoinGroup(ipv4, nic, %s) = %s", multicastAddr2, err)
}
@@ -560,6 +566,9 @@ func TestSetIGMPVersion(t *testing.T) {
if got := igmpEP.SetIGMPVersion(ipv4.IGMPVersion1); got != ipv4.IGMPVersion2 {
t.Errorf("got igmpEP.SetIGMPVersion(%d) = %d, want = %d", ipv4.IGMPVersion1, got, ipv4.IGMPVersion2)
}
if got := igmpEP.GetIGMPVersion(); got != ipv4.IGMPVersion1 {
t.Errorf("got igmpEP.GetIGMPVersion() = %d, want = %d", got, ipv4.IGMPVersion1)
}
if err := s.JoinGroup(ipv4.ProtocolNumber, nicID, multicastAddr3); err != nil {
t.Fatalf("JoinGroup(ipv4, nic, %s) = %s", multicastAddr3, err)
}
@@ -573,6 +582,9 @@ func TestSetIGMPVersion(t *testing.T) {
if got := igmpEP.SetIGMPVersion(ipv4.IGMPVersion3); got != ipv4.IGMPVersion1 {
t.Errorf("got igmpEP.SetIGMPVersion(%d) = %d, want = %d", ipv4.IGMPVersion3, got, ipv4.IGMPVersion1)
}
if got := igmpEP.GetIGMPVersion(); got != ipv4.IGMPVersion3 {
t.Errorf("got igmpEP.GetIGMPVersion() = %d, want = %d", got, ipv4.IGMPVersion3)
}
if err := s.JoinGroup(ipv4.ProtocolNumber, nicID, multicastAddr4); err != nil {
t.Fatalf("JoinGroup(ipv4, nic, %s) = %s", multicastAddr4, err)
}
+13
View File
@@ -117,12 +117,25 @@ func (e *endpoint) SetIGMPVersion(v IGMPVersion) IGMPVersion {
return e.setIGMPVersionLocked(v)
}
// GetIGMPVersion implements IGMPEndpoint.
func (e *endpoint) GetIGMPVersion() IGMPVersion {
e.mu.RLock()
defer e.mu.RUnlock()
return e.getIGMPVersionLocked()
}
// +checklocks:e.mu
// +checklocksalias:e.igmp.ep.mu=e.mu
func (e *endpoint) setIGMPVersionLocked(v IGMPVersion) IGMPVersion {
return e.igmp.setVersion(v)
}
// +checklocksread:e.mu
// +checklocksalias:e.igmp.ep.mu=e.mu
func (e *endpoint) getIGMPVersionLocked() IGMPVersion {
return e.igmp.getVersion()
}
// HandleLinkResolutionFailure implements stack.LinkResolvableNetworkEndpoint.
func (e *endpoint) HandleLinkResolutionFailure(pkt stack.PacketBufferPtr) {
// If we are operating as a router, return an ICMP error to the original
+7
View File
@@ -364,6 +364,13 @@ func (e *endpoint) SetMLDVersion(v MLDVersion) MLDVersion {
return e.mu.mld.setVersion(v)
}
// GetMLDVersion implements MLDEndpoint.
func (e *endpoint) GetMLDVersion() MLDVersion {
e.mu.RLock()
defer e.mu.RUnlock()
return e.mu.mld.getVersion()
}
// SetNDPConfigurations implements NDPEndpoint.
func (e *endpoint) SetNDPConfigurations(c NDPConfigurations) {
c.validate()
+16 -2
View File
@@ -47,10 +47,13 @@ const (
// MLDEndpoint is a network endpoint that supports MLD.
type MLDEndpoint interface {
// Sets the MLD version.
// SetMLDVersions sets the MLD version.
//
// Returns the previous MLD version.
SetMLDVersion(MLDVersion) MLDVersion
// GetMLDVersion returns the MLD version.
GetMLDVersion() MLDVersion
}
// MLDOptions holds options for MLD.
@@ -334,12 +337,23 @@ func (mld *mldState) setVersion(v MLDVersion) MLDVersion {
panic(fmt.Sprintf("unrecognized version = %d", v))
}
if prev {
return toMLDVersion(prev)
}
func toMLDVersion(v1Generic bool) MLDVersion {
if v1Generic {
return MLDVersion1
}
return MLDVersion2
}
// getVersion returns the MLD version.
//
// Precondition: mld.ep.mu must be read locked.
func (mld *mldState) getVersion() MLDVersion {
return toMLDVersion(mld.genericMulticastProtocol.GetV1ModeLocked())
}
// writePacket assembles and sends an MLD packet.
//
// Precondition: mld.ep.mu must be read locked.
+10 -1
View File
@@ -759,7 +759,7 @@ func TestMLDSkipProtocol(t *testing.T) {
}
}
func TestSetMLDVersion(t *testing.T) {
func TestGetSetMLDVersion(t *testing.T) {
const nicID = 1
c := newMLDTestContext()
@@ -781,6 +781,9 @@ func TestSetMLDVersion(t *testing.T) {
if !ok {
t.Fatalf("got (%T).(%T) = (_, false), want = (_ true)", ep, mldEP)
}
if got := mldEP.GetMLDVersion(); got != ipv6.MLDVersion2 {
t.Errorf("got mldEP.GetMLDVersion() = %d, want = %d", got, ipv6.MLDVersion2)
}
protocolAddr := tcpip.ProtocolAddress{
Protocol: ipv6.ProtocolNumber,
@@ -799,6 +802,9 @@ func TestSetMLDVersion(t *testing.T) {
if got := mldEP.SetMLDVersion(ipv6.MLDVersion1); got != ipv6.MLDVersion2 {
t.Errorf("got mldEP.SetMLDVersion(%d) = %d, want = %d", ipv6.MLDVersion1, got, ipv6.MLDVersion2)
}
if got := mldEP.GetMLDVersion(); got != ipv6.MLDVersion1 {
t.Errorf("got mldEP.GetMLDVersion() = %d, want = %d", got, ipv6.MLDVersion1)
}
if err := s.JoinGroup(ipv6.ProtocolNumber, nicID, globalMulticastAddr); err != nil {
t.Fatalf("s.JoinGroup(%d, %d, %s): %s", ipv6.ProtocolNumber, nicID, globalMulticastAddr, err)
}
@@ -812,6 +818,9 @@ func TestSetMLDVersion(t *testing.T) {
if got := mldEP.SetMLDVersion(ipv6.MLDVersion2); got != ipv6.MLDVersion1 {
t.Errorf("got mldEP.SetMLDVersion(%d) = %d, want = %d", ipv6.MLDVersion2, got, ipv6.MLDVersion1)
}
if got := mldEP.GetMLDVersion(); got != ipv6.MLDVersion2 {
t.Errorf("got mldEP.GetMLDVersion() = %d, want = %d", got, ipv6.MLDVersion2)
}
if err := s.LeaveGroup(ipv6.ProtocolNumber, nicID, globalMulticastAddr); err != nil {
t.Fatalf("s.LeaveGroup(%d, %d, %s): %s", ipv6.ProtocolNumber, nicID, globalMulticastAddr, err)
}