Coalesce records sent by the state changed timer

When the state changed timer fires, instead of sending a single record
per report, send as many records as possible per report message.

Updates #8346

PiperOrigin-RevId: 501932735
This commit is contained in:
Ghanan Gowripalan
2023-01-13 14:00:29 -08:00
committed by gVisor bot
parent 12e13426be
commit c76b03723e
3 changed files with 25 additions and 8 deletions
@@ -520,6 +520,7 @@ func (g *GenericMulticastProtocolState) sendV2ReportAndMaybeScheduleChangedTimer
g.protocolMU.Lock()
defer g.protocolMU.Unlock()
reportBuilder := g.opts.Protocol.NewReportV2Builder()
nonEmptyReport := false
for groupAddress, info := range g.memberships {
if info.transmissionLeft == 0 || !g.shouldPerformForGroup(groupAddress) {
@@ -529,15 +530,11 @@ func (g *GenericMulticastProtocolState) sendV2ReportAndMaybeScheduleChangedTimer
info.transmissionLeft--
nonEmptyReport = true
reportBuilder := g.opts.Protocol.NewReportV2Builder()
mode := MulticastGroupProtocolV2ReportRecordChangeToExcludeMode
if info.deleteScheduled {
mode = MulticastGroupProtocolV2ReportRecordChangeToIncludeMode
}
reportBuilder.AddRecord(mode, groupAddress)
// Nothing meaningful we can do with the error here. We will retry
// sending a state changed report again anyways.
_, _ = reportBuilder.Send()
if info.deleteScheduled && info.transmissionLeft == 0 {
// No more transmissions left so we can actually delete the
@@ -548,6 +545,10 @@ func (g *GenericMulticastProtocolState) sendV2ReportAndMaybeScheduleChangedTimer
}
}
// Nothing meaningful we can do with the error here. We will retry
// sending a state changed report again anyways.
_, _ = reportBuilder.Send()
if nonEmptyReport {
g.stateChangedReportV2Timer.Reset(g.calculateDelayTimerDuration(g.opts.MaxUnsolicitedReportDelay))
} else {
+10 -1
View File
@@ -332,7 +332,16 @@ func TestSendQueuedIGMPReports(t *testing.T) {
// We expect two batches of reports to be sent (1 batch when the address
// is assigned, and another after the maximum unsolicited report interval.
for i := 0; i < 2; i++ {
reportCounter += uint64(len(multicastAddrs))
// IGMPv2 always sends a single message per group.
//
// IGMPv3 sends a single message per group when we first get an
// address assigned, but later reports (sent by the state changed
// timer) coalesce records for groups.
if test.v2Compatibility || i == 0 {
reportCounter += uint64(len(multicastAddrs))
} else {
reportCounter++
}
test.checkStats(t, s, reportCounter, doneCounter, reportV2Counter)
test.validate(t, e, stackAddr, multicastAddrs)
+10 -3
View File
@@ -405,9 +405,16 @@ func TestSendQueuedMLDReports(t *testing.T) {
// link-local address is assigned, and another after the maximum
// unsolicited report interval.
for i := 0; i < 2; i++ {
// We expect reports to be sent (one for globalMulticastAddr and another
// for linkLocalAddrSNMC).
reportCounter += maxReports
// MLDv1 always sends a single message per group.
//
// MLDv2 sends a single message per group when we first get an
// IPv6 link-local address assigned, but later reports (sent by
// the state changed timer) coalesce records for groups.
if subTest.v1Compatibility || i == 0 {
reportCounter += maxReports
} else {
reportCounter++
}
subTest.checkStats(t, s, reportCounter, doneCounter, reportV2Counter)
subTest.validate(