Don't transition from V1 -> V2 unless requested

Leave the generic multicast protocol in V1 mode even when transitioning
all groups to non-member state (when interface is disabled).

Updates #8346

PiperOrigin-RevId: 508448263
This commit is contained in:
Ghanan Gowripalan
2023-02-09 12:43:14 -08:00
committed by gVisor bot
parent ec1abcf521
commit 89cc675c29
2 changed files with 56 additions and 38 deletions
@@ -397,14 +397,15 @@ func (g *GenericMulticastProtocolState) MakeAllNonMemberLocked() {
groupAddress,
)
}
case protocolModeV1Compatibility, protocolModeV1:
case protocolModeV1Compatibility:
g.mode = protocolModeV2
fallthrough
case protocolModeV1:
handler = g.transitionToNonMemberLocked
default:
panic(fmt.Sprintf("unrecognized mode = %d", g.mode))
}
g.mode = protocolModeV2
for groupAddress, info := range g.memberships {
if !g.shouldPerformForGroup(groupAddress) {
continue
@@ -1153,13 +1153,28 @@ func TestJoinCount(t *testing.T) {
}
func TestMakeAllNonMemberAndInitialize(t *testing.T) {
const unsolicitedTransmissionCount = 2
tests := []struct {
name string
v1 bool
v1Compatibility bool
checkFields func([]tcpip.Address, bool) checkFields
}{
{
name: "V1",
v1: true,
v1Compatibility: false,
checkFields: func(addrs []tcpip.Address, leave bool) checkFields {
if leave {
return checkFields{sendLeaveGroupAddresses: addrs}
}
return checkFields{sendReportGroupAddresses: addrs}
},
},
{
name: "V1 Compatibility",
v1: false,
v1Compatibility: true,
checkFields: func(addrs []tcpip.Address, leave bool) checkFields {
if leave {
@@ -1170,6 +1185,7 @@ func TestMakeAllNonMemberAndInitialize(t *testing.T) {
},
{
name: "V2",
v1: false,
v1Compatibility: false,
checkFields: func(addrs []tcpip.Address, leave bool) checkFields {
recordType := ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode
@@ -1198,7 +1214,13 @@ func TestMakeAllNonMemberAndInitialize(t *testing.T) {
Rand: rand.New(rand.NewSource(3)),
Clock: clock,
MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
}, test.v1Compatibility)
}, test.v1)
if test.v1Compatibility {
// V1 query targetting an unjoined group should drop us into V1
// compatibility mode without sending any packets, affecting tests.
mgp.handleQuery(addr3, 0)
}
mgp.joinGroup(addr1)
if diff := mgp.check(test.checkFields([]tcpip.Address{addr1}, false /* leave */)); diff != "" {
@@ -1216,8 +1238,7 @@ func TestMakeAllNonMemberAndInitialize(t *testing.T) {
// Should send the leave reports for each but still consider them locally
// joined.
mgp.makeAllNonMember()
expectedLeaveFields := test.checkFields([]tcpip.Address{addr1, addr2}, true /* leave */)
if diff := mgp.check(expectedLeaveFields); diff != "" {
if diff := mgp.check(test.checkFields([]tcpip.Address{addr1, addr2}, true /* leave */)); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}
@@ -1234,42 +1255,34 @@ func TestMakeAllNonMemberAndInitialize(t *testing.T) {
// Should send the initial set of unsolcited V2 reports.
mgp.initializeGroups()
if diff := mgp.check(checkFields{sentV2Reports: []mockReportV2{
{
records: []mockReportV2Record{
for i := 0; i < unsolicitedTransmissionCount; i++ {
if test.v1 {
if diff := mgp.check(test.checkFields([]tcpip.Address{addr1, addr2}, false /* leave */)); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}
} else {
if diff := mgp.check(checkFields{sentV2Reports: []mockReportV2{
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr1,
},
},
},
{
records: []mockReportV2Record{
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr2,
},
},
},
}}); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}
clock.Advance(maxUnsolicitedReportDelay)
if diff := mgp.check(checkFields{sentV2Reports: []mockReportV2{
{
records: []mockReportV2Record{
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr1,
records: []mockReportV2Record{
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr1,
},
},
},
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr2,
records: []mockReportV2Record{
{
recordType: ip.MulticastGroupProtocolV2ReportRecordChangeToExcludeMode,
groupAddress: addr2,
},
},
},
},
},
}}); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}}); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}
}
clock.Advance(maxUnsolicitedReportDelay)
}
// Should have no more messages to send.
@@ -1277,6 +1290,10 @@ func TestMakeAllNonMemberAndInitialize(t *testing.T) {
if diff := mgp.check(checkFields{}); diff != "" {
t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
}
if got := mgp.getV1Mode(); got != test.v1 {
t.Errorf("got mgp.getV1Mode() = %t, want = %t", got, test.v1)
}
})
}
}