summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/internal/ip
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/network/internal/ip')
-rw-r--r--pkg/tcpip/network/internal/ip/BUILD40
-rw-r--r--pkg/tcpip/network/internal/ip/duplicate_address_detection_test.go381
-rw-r--r--pkg/tcpip/network/internal/ip/generic_multicast_protocol_test.go808
-rw-r--r--pkg/tcpip/network/internal/ip/ip_state_autogen.go32
4 files changed, 32 insertions, 1229 deletions
diff --git a/pkg/tcpip/network/internal/ip/BUILD b/pkg/tcpip/network/internal/ip/BUILD
deleted file mode 100644
index fd944ce99..000000000
--- a/pkg/tcpip/network/internal/ip/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "ip",
- srcs = [
- "duplicate_address_detection.go",
- "errors.go",
- "generic_multicast_protocol.go",
- "stats.go",
- ],
- visibility = [
- "//pkg/tcpip/network/arp:__pkg__",
- "//pkg/tcpip/network/ipv4:__pkg__",
- "//pkg/tcpip/network/ipv6:__pkg__",
- ],
- deps = [
- "//pkg/sync",
- "//pkg/tcpip",
- "//pkg/tcpip/stack",
- ],
-)
-
-go_test(
- name = "ip_x_test",
- size = "small",
- srcs = [
- "duplicate_address_detection_test.go",
- "generic_multicast_protocol_test.go",
- ],
- deps = [
- ":ip",
- "//pkg/sync",
- "//pkg/tcpip",
- "//pkg/tcpip/faketime",
- "//pkg/tcpip/stack",
- "@com_github_google_go_cmp//cmp:go_default_library",
- ],
-)
diff --git a/pkg/tcpip/network/internal/ip/duplicate_address_detection_test.go b/pkg/tcpip/network/internal/ip/duplicate_address_detection_test.go
deleted file mode 100644
index 24687cf06..000000000
--- a/pkg/tcpip/network/internal/ip/duplicate_address_detection_test.go
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2021 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ip_test
-
-import (
- "bytes"
- "testing"
- "time"
-
- "github.com/google/go-cmp/cmp"
- "gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/faketime"
- "gvisor.dev/gvisor/pkg/tcpip/network/internal/ip"
- "gvisor.dev/gvisor/pkg/tcpip/stack"
-)
-
-type mockDADProtocol struct {
- t *testing.T
-
- mu struct {
- sync.Mutex
-
- dad ip.DAD
- sentNonces map[tcpip.Address][][]byte
- }
-}
-
-func (m *mockDADProtocol) init(t *testing.T, c stack.DADConfigurations, opts ip.DADOptions) {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- m.t = t
- opts.Protocol = m
- m.mu.dad.Init(&m.mu, c, opts)
- m.initLocked()
-}
-
-func (m *mockDADProtocol) initLocked() {
- m.mu.sentNonces = make(map[tcpip.Address][][]byte)
-}
-
-func (m *mockDADProtocol) SendDADMessage(addr tcpip.Address, nonce []byte) tcpip.Error {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.sentNonces[addr] = append(m.mu.sentNonces[addr], nonce)
- return nil
-}
-
-func (m *mockDADProtocol) check(addrs []tcpip.Address) string {
- sentNonces := make(map[tcpip.Address][][]byte)
- for _, a := range addrs {
- sentNonces[a] = append(sentNonces[a], nil)
- }
-
- return m.checkWithNonce(sentNonces)
-}
-
-func (m *mockDADProtocol) checkWithNonce(expectedSentNonces map[tcpip.Address][][]byte) string {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- diff := cmp.Diff(expectedSentNonces, m.mu.sentNonces)
- m.initLocked()
- return diff
-}
-
-func (m *mockDADProtocol) checkDuplicateAddress(addr tcpip.Address, h stack.DADCompletionHandler) stack.DADCheckAddressDisposition {
- m.mu.Lock()
- defer m.mu.Unlock()
- return m.mu.dad.CheckDuplicateAddressLocked(addr, h)
-}
-
-func (m *mockDADProtocol) stop(addr tcpip.Address, reason stack.DADResult) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.dad.StopLocked(addr, reason)
-}
-
-func (m *mockDADProtocol) extendIfNonceEqual(addr tcpip.Address, nonce []byte) ip.ExtendIfNonceEqualLockedDisposition {
- m.mu.Lock()
- defer m.mu.Unlock()
- return m.mu.dad.ExtendIfNonceEqualLocked(addr, nonce)
-}
-
-func (m *mockDADProtocol) setConfigs(c stack.DADConfigurations) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.dad.SetConfigsLocked(c)
-}
-
-const (
- addr1 = tcpip.Address("\x01")
- addr2 = tcpip.Address("\x02")
- addr3 = tcpip.Address("\x03")
- addr4 = tcpip.Address("\x04")
-)
-
-type dadResult struct {
- Addr tcpip.Address
- R stack.DADResult
-}
-
-func handler(ch chan<- dadResult, a tcpip.Address) func(stack.DADResult) {
- return func(r stack.DADResult) {
- ch <- dadResult{Addr: a, R: r}
- }
-}
-
-func TestDADCheckDuplicateAddress(t *testing.T) {
- var dad mockDADProtocol
- clock := faketime.NewManualClock()
- dad.init(t, stack.DADConfigurations{}, ip.DADOptions{
- Clock: clock,
- })
-
- ch := make(chan dadResult, 2)
-
- // DAD should initially be disabled.
- if res := dad.checkDuplicateAddress(addr1, handler(nil, "")); res != stack.DADDisabled {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADDisabled)
- }
- // Wait for any initially fired timers to complete.
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check(nil); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
-
- // Enable and request DAD.
- dadConfigs1 := stack.DADConfigurations{
- DupAddrDetectTransmits: 1,
- RetransmitTimer: time.Second,
- }
- dad.setConfigs(dadConfigs1)
- if res := dad.checkDuplicateAddress(addr1, handler(ch, addr1)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADStarting)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check([]tcpip.Address{addr1}); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
- // The second request for DAD on the same address should use the original
- // request since it has not completed yet.
- if res := dad.checkDuplicateAddress(addr1, handler(ch, addr1)); res != stack.DADAlreadyRunning {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADAlreadyRunning)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check(nil); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
-
- dadConfigs2 := stack.DADConfigurations{
- DupAddrDetectTransmits: 2,
- RetransmitTimer: time.Second,
- }
- dad.setConfigs(dadConfigs2)
- // A new address should start a new DAD process.
- if res := dad.checkDuplicateAddress(addr2, handler(ch, addr2)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr2, res, stack.DADStarting)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check([]tcpip.Address{addr2}); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
-
- // Make sure DAD for addr1 only resolves after the expected timeout.
- const delta = time.Nanosecond
- dadConfig1Duration := time.Duration(dadConfigs1.DupAddrDetectTransmits) * dadConfigs1.RetransmitTimer
- clock.Advance(dadConfig1Duration - delta)
- select {
- case r := <-ch:
- t.Fatalf("unexpectedly got a DAD result before the expected timeout of %s; r = %#v", dadConfig1Duration, r)
- default:
- }
- clock.Advance(delta)
- for i := 0; i < 2; i++ {
- if diff := cmp.Diff(dadResult{Addr: addr1, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("(i=%d) dad result mismatch (-want +got):\n%s", i, diff)
- }
- }
-
- // Make sure DAD for addr2 only resolves after the expected timeout.
- dadConfig2Duration := time.Duration(dadConfigs2.DupAddrDetectTransmits) * dadConfigs2.RetransmitTimer
- clock.Advance(dadConfig2Duration - dadConfig1Duration - delta)
- select {
- case r := <-ch:
- t.Fatalf("unexpectedly got a DAD result before the expected timeout of %s; r = %#v", dadConfig2Duration, r)
- default:
- }
- clock.Advance(delta)
- if diff := cmp.Diff(dadResult{Addr: addr2, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- // Should be able to restart DAD for addr2 after it resolved.
- if res := dad.checkDuplicateAddress(addr2, handler(ch, addr2)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr2, res, stack.DADStarting)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check([]tcpip.Address{addr2, addr2}); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
- clock.Advance(dadConfig2Duration)
- if diff := cmp.Diff(dadResult{Addr: addr2, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anymore results.
- select {
- case r := <-ch:
- t.Fatalf("unexpectedly got an extra DAD result; r = %#v", r)
- default:
- }
-}
-
-func TestDADStop(t *testing.T) {
- var dad mockDADProtocol
- clock := faketime.NewManualClock()
- dadConfigs := stack.DADConfigurations{
- DupAddrDetectTransmits: 1,
- RetransmitTimer: time.Second,
- }
- dad.init(t, dadConfigs, ip.DADOptions{
- Clock: clock,
- })
-
- ch := make(chan dadResult, 1)
-
- if res := dad.checkDuplicateAddress(addr1, handler(ch, addr1)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADStarting)
- }
- if res := dad.checkDuplicateAddress(addr2, handler(ch, addr2)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr2, res, stack.DADStarting)
- }
- if res := dad.checkDuplicateAddress(addr3, handler(ch, addr3)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr2, res, stack.DADStarting)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check([]tcpip.Address{addr1, addr2, addr3}); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
-
- dad.stop(addr1, &stack.DADAborted{})
- if diff := cmp.Diff(dadResult{Addr: addr1, R: &stack.DADAborted{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- dad.stop(addr2, &stack.DADDupAddrDetected{})
- if diff := cmp.Diff(dadResult{Addr: addr2, R: &stack.DADDupAddrDetected{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- dadResolutionDuration := time.Duration(dadConfigs.DupAddrDetectTransmits) * dadConfigs.RetransmitTimer
- clock.Advance(dadResolutionDuration)
- if diff := cmp.Diff(dadResult{Addr: addr3, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- // Should be able to restart DAD for an address we stopped DAD on.
- if res := dad.checkDuplicateAddress(addr1, handler(ch, addr1)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADStarting)
- }
- clock.RunImmediatelyScheduledJobs()
- if diff := dad.check([]tcpip.Address{addr1}); diff != "" {
- t.Errorf("dad check mismatch (-want +got):\n%s", diff)
- }
- clock.Advance(dadResolutionDuration)
- if diff := cmp.Diff(dadResult{Addr: addr1, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anymore updates.
- select {
- case r := <-ch:
- t.Fatalf("unexpectedly got an extra DAD result; r = %#v", r)
- default:
- }
-}
-
-func TestNonce(t *testing.T) {
- const (
- nonceSize = 2
-
- extendRequestAttempts = 2
-
- dupAddrDetectTransmits = 2
- extendTransmits = 5
- )
-
- var secureRNGBytes [nonceSize * (dupAddrDetectTransmits + extendTransmits)]byte
- for i := range secureRNGBytes {
- secureRNGBytes[i] = byte(i)
- }
-
- tests := []struct {
- name string
- mockedReceivedNonce []byte
- expectedResults [extendRequestAttempts]ip.ExtendIfNonceEqualLockedDisposition
- expectedTransmits int
- }{
- {
- name: "not matching",
- mockedReceivedNonce: []byte{0, 0},
- expectedResults: [extendRequestAttempts]ip.ExtendIfNonceEqualLockedDisposition{ip.NonceNotEqual, ip.NonceNotEqual},
- expectedTransmits: dupAddrDetectTransmits,
- },
- {
- name: "matching nonce",
- mockedReceivedNonce: secureRNGBytes[:nonceSize],
- expectedResults: [extendRequestAttempts]ip.ExtendIfNonceEqualLockedDisposition{ip.Extended, ip.AlreadyExtended},
- expectedTransmits: dupAddrDetectTransmits + extendTransmits,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var dad mockDADProtocol
- clock := faketime.NewManualClock()
- dadConfigs := stack.DADConfigurations{
- DupAddrDetectTransmits: dupAddrDetectTransmits,
- RetransmitTimer: time.Second,
- }
-
- var secureRNG bytes.Reader
- secureRNG.Reset(secureRNGBytes[:])
- dad.init(t, dadConfigs, ip.DADOptions{
- Clock: clock,
- SecureRNG: &secureRNG,
- NonceSize: nonceSize,
- ExtendDADTransmits: extendTransmits,
- })
-
- ch := make(chan dadResult, 1)
- if res := dad.checkDuplicateAddress(addr1, handler(ch, addr1)); res != stack.DADStarting {
- t.Errorf("got dad.checkDuplicateAddress(%s, _) = %d, want = %d", addr1, res, stack.DADStarting)
- }
-
- clock.RunImmediatelyScheduledJobs()
- for i, want := range test.expectedResults {
- if got := dad.extendIfNonceEqual(addr1, test.mockedReceivedNonce); got != want {
- t.Errorf("(i=%d) got dad.extendIfNonceEqual(%s, _) = %d, want = %d", i, addr1, got, want)
- }
- }
-
- for i := 0; i < test.expectedTransmits; i++ {
- if diff := dad.checkWithNonce(map[tcpip.Address][][]byte{
- addr1: {
- secureRNGBytes[nonceSize*i:][:nonceSize],
- },
- }); diff != "" {
- t.Errorf("(i=%d) dad check mismatch (-want +got):\n%s", i, diff)
- }
-
- clock.Advance(dadConfigs.RetransmitTimer)
- }
-
- if diff := cmp.Diff(dadResult{Addr: addr1, R: &stack.DADSucceeded{}}, <-ch); diff != "" {
- t.Errorf("dad result mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anymore updates.
- select {
- case r := <-ch:
- t.Fatalf("unexpectedly got an extra DAD result; r = %#v", r)
- default:
- }
- })
- }
-}
diff --git a/pkg/tcpip/network/internal/ip/generic_multicast_protocol_test.go b/pkg/tcpip/network/internal/ip/generic_multicast_protocol_test.go
deleted file mode 100644
index 1261ad414..000000000
--- a/pkg/tcpip/network/internal/ip/generic_multicast_protocol_test.go
+++ /dev/null
@@ -1,808 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ip_test
-
-import (
- "math/rand"
- "testing"
- "time"
-
- "github.com/google/go-cmp/cmp"
- "gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/faketime"
- "gvisor.dev/gvisor/pkg/tcpip/network/internal/ip"
-)
-
-const maxUnsolicitedReportDelay = time.Second
-
-var _ ip.MulticastGroupProtocol = (*mockMulticastGroupProtocol)(nil)
-
-type mockMulticastGroupProtocolProtectedFields struct {
- sync.RWMutex
-
- genericMulticastGroup ip.GenericMulticastProtocolState
- sendReportGroupAddrCount map[tcpip.Address]int
- sendLeaveGroupAddrCount map[tcpip.Address]int
- makeQueuePackets bool
- disabled bool
-}
-
-type mockMulticastGroupProtocol struct {
- t *testing.T
-
- skipProtocolAddress tcpip.Address
-
- mu mockMulticastGroupProtocolProtectedFields
-}
-
-func (m *mockMulticastGroupProtocol) init(opts ip.GenericMulticastProtocolOptions) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.initLocked()
- opts.Protocol = m
- m.mu.genericMulticastGroup.Init(&m.mu.RWMutex, opts)
-}
-
-func (m *mockMulticastGroupProtocol) initLocked() {
- m.mu.sendReportGroupAddrCount = make(map[tcpip.Address]int)
- m.mu.sendLeaveGroupAddrCount = make(map[tcpip.Address]int)
-}
-
-func (m *mockMulticastGroupProtocol) setEnabled(v bool) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.disabled = !v
-}
-
-func (m *mockMulticastGroupProtocol) setQueuePackets(v bool) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.makeQueuePackets = v
-}
-
-func (m *mockMulticastGroupProtocol) joinGroup(addr tcpip.Address) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.JoinGroupLocked(addr)
-}
-
-func (m *mockMulticastGroupProtocol) leaveGroup(addr tcpip.Address) bool {
- m.mu.Lock()
- defer m.mu.Unlock()
- return m.mu.genericMulticastGroup.LeaveGroupLocked(addr)
-}
-
-func (m *mockMulticastGroupProtocol) handleReport(addr tcpip.Address) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.HandleReportLocked(addr)
-}
-
-func (m *mockMulticastGroupProtocol) handleQuery(addr tcpip.Address, maxRespTime time.Duration) {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.HandleQueryLocked(addr, maxRespTime)
-}
-
-func (m *mockMulticastGroupProtocol) isLocallyJoined(addr tcpip.Address) bool {
- m.mu.RLock()
- defer m.mu.RUnlock()
- return m.mu.genericMulticastGroup.IsLocallyJoinedRLocked(addr)
-}
-
-func (m *mockMulticastGroupProtocol) makeAllNonMember() {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.MakeAllNonMemberLocked()
-}
-
-func (m *mockMulticastGroupProtocol) initializeGroups() {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.InitializeGroupsLocked()
-}
-
-func (m *mockMulticastGroupProtocol) sendQueuedReports() {
- m.mu.Lock()
- defer m.mu.Unlock()
- m.mu.genericMulticastGroup.SendQueuedReportsLocked()
-}
-
-// Enabled implements ip.MulticastGroupProtocol.
-//
-// Precondition: m.mu must be read locked.
-func (m *mockMulticastGroupProtocol) Enabled() bool {
- if m.mu.TryLock() {
- m.mu.Unlock() // +checklocksforce: TryLock.
- m.t.Fatal("got write lock, expected to not take the lock; generic multicast protocol must take the read or write lock before calling Enabled")
- }
-
- return !m.mu.disabled
-}
-
-// SendReport implements ip.MulticastGroupProtocol.
-//
-// Precondition: m.mu must be locked.
-func (m *mockMulticastGroupProtocol) SendReport(groupAddress tcpip.Address) (bool, tcpip.Error) {
- if m.mu.TryLock() {
- m.mu.Unlock() // +checklocksforce: TryLock.
- m.t.Fatalf("got write lock, expected to not take the lock; generic multicast protocol must take the write lock before sending report for %s", groupAddress)
- }
- if m.mu.TryRLock() {
- m.mu.RUnlock() // +checklocksforce: TryLock.
- m.t.Fatalf("got read lock, expected to not take the lock; generic multicast protocol must take the write lock before sending report for %s", groupAddress)
- }
-
- m.mu.sendReportGroupAddrCount[groupAddress]++
- return !m.mu.makeQueuePackets, nil
-}
-
-// SendLeave implements ip.MulticastGroupProtocol.
-//
-// Precondition: m.mu must be locked.
-func (m *mockMulticastGroupProtocol) SendLeave(groupAddress tcpip.Address) tcpip.Error {
- if m.mu.TryLock() {
- m.mu.Unlock() // +checklocksforce: TryLock.
- m.t.Fatalf("got write lock, expected to not take the lock; generic multicast protocol must take the write lock before sending leave for %s", groupAddress)
- }
- if m.mu.TryRLock() {
- m.mu.RUnlock() // +checklocksforce: TryLock.
- m.t.Fatalf("got read lock, expected to not take the lock; generic multicast protocol must take the write lock before sending leave for %s", groupAddress)
- }
-
- m.mu.sendLeaveGroupAddrCount[groupAddress]++
- return nil
-}
-
-// ShouldPerformProtocol implements ip.MulticastGroupProtocol.
-func (m *mockMulticastGroupProtocol) ShouldPerformProtocol(groupAddress tcpip.Address) bool {
- return groupAddress != m.skipProtocolAddress
-}
-
-func (m *mockMulticastGroupProtocol) check(sendReportGroupAddresses []tcpip.Address, sendLeaveGroupAddresses []tcpip.Address) string {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- sendReportGroupAddrCount := make(map[tcpip.Address]int)
- for _, a := range sendReportGroupAddresses {
- sendReportGroupAddrCount[a] = 1
- }
-
- sendLeaveGroupAddrCount := make(map[tcpip.Address]int)
- for _, a := range sendLeaveGroupAddresses {
- sendLeaveGroupAddrCount[a] = 1
- }
-
- diff := cmp.Diff(
- &mockMulticastGroupProtocol{
- mu: mockMulticastGroupProtocolProtectedFields{
- sendReportGroupAddrCount: sendReportGroupAddrCount,
- sendLeaveGroupAddrCount: sendLeaveGroupAddrCount,
- },
- },
- m,
- cmp.AllowUnexported(mockMulticastGroupProtocol{}),
- cmp.AllowUnexported(mockMulticastGroupProtocolProtectedFields{}),
- // ignore mockMulticastGroupProtocol.mu and mockMulticastGroupProtocol.t
- cmp.FilterPath(
- func(p cmp.Path) bool {
- switch p.Last().String() {
- case ".RWMutex", ".t", ".makeQueuePackets", ".disabled", ".genericMulticastGroup", ".skipProtocolAddress":
- return true
- default:
- return false
- }
- },
- cmp.Ignore(),
- ),
- )
- m.initLocked()
- return diff
-}
-
-func TestJoinGroup(t *testing.T) {
- tests := []struct {
- name string
- addr tcpip.Address
- shouldSendReports bool
- }{
- {
- name: "Normal group",
- addr: addr1,
- shouldSendReports: true,
- },
- {
- name: "All-nodes group",
- addr: addr2,
- shouldSendReports: false,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t, skipProtocolAddress: addr2}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(0)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- // Joining a group should send a report immediately and another after
- // a random interval between 0 and the maximum unsolicited report delay.
- mgp.joinGroup(test.addr)
- if test.shouldSendReports {
- if diff := mgp.check([]tcpip.Address{test.addr} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check([]tcpip.Address{test.addr} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- }
-
- // Should have no more messages to send.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- })
- }
-}
-
-func TestLeaveGroup(t *testing.T) {
- tests := []struct {
- name string
- addr tcpip.Address
- shouldSendMessages bool
- }{
- {
- name: "Normal group",
- addr: addr1,
- shouldSendMessages: true,
- },
- {
- name: "All-nodes group",
- addr: addr2,
- shouldSendMessages: false,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t, skipProtocolAddress: addr2}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(1)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- mgp.joinGroup(test.addr)
- if test.shouldSendMessages {
- if diff := mgp.check([]tcpip.Address{test.addr} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- }
-
- // Leaving a group should send a leave report immediately and cancel any
- // delayed reports.
- {
-
- if !mgp.leaveGroup(test.addr) {
- t.Fatalf("got mgp.leaveGroup(%s) = false, want = true", test.addr)
- }
- }
- if test.shouldSendMessages {
- if diff := mgp.check(nil /* sendReportGroupAddresses */, []tcpip.Address{test.addr} /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- }
-
- // Should have no more messages to send.
- //
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- })
- }
-}
-
-func TestHandleReport(t *testing.T) {
- tests := []struct {
- name string
- reportAddr tcpip.Address
- expectReportsFor []tcpip.Address
- }{
- {
- name: "Unpecified empty",
- reportAddr: "",
- expectReportsFor: []tcpip.Address{addr1, addr2},
- },
- {
- name: "Unpecified any",
- reportAddr: "\x00",
- expectReportsFor: []tcpip.Address{addr1, addr2},
- },
- {
- name: "Specified",
- reportAddr: addr1,
- expectReportsFor: []tcpip.Address{addr2},
- },
- {
- name: "Specified all-nodes",
- reportAddr: addr3,
- expectReportsFor: []tcpip.Address{addr1, addr2},
- },
- {
- name: "Specified other",
- reportAddr: addr4,
- expectReportsFor: []tcpip.Address{addr1, addr2},
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t, skipProtocolAddress: addr3}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(2)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- mgp.joinGroup(addr1)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr2)
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr3)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receiving a report for a group we have a timer scheduled for should
- // cancel our delayed report timer for the group.
- mgp.handleReport(test.reportAddr)
- if len(test.expectReportsFor) != 0 {
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check(test.expectReportsFor /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- }
-
- // Should have no more messages to send.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- })
- }
-}
-
-func TestHandleQuery(t *testing.T) {
- tests := []struct {
- name string
- queryAddr tcpip.Address
- maxDelay time.Duration
- expectQueriedReportsFor []tcpip.Address
- expectDelayedReportsFor []tcpip.Address
- }{
- {
- name: "Unpecified empty",
- queryAddr: "",
- maxDelay: 0,
- expectQueriedReportsFor: []tcpip.Address{addr1, addr2},
- expectDelayedReportsFor: nil,
- },
- {
- name: "Unpecified any",
- queryAddr: "\x00",
- maxDelay: 1,
- expectQueriedReportsFor: []tcpip.Address{addr1, addr2},
- expectDelayedReportsFor: nil,
- },
- {
- name: "Specified",
- queryAddr: addr1,
- maxDelay: 2,
- expectQueriedReportsFor: []tcpip.Address{addr1},
- expectDelayedReportsFor: []tcpip.Address{addr2},
- },
- {
- name: "Specified all-nodes",
- queryAddr: addr3,
- maxDelay: 3,
- expectQueriedReportsFor: nil,
- expectDelayedReportsFor: []tcpip.Address{addr1, addr2},
- },
- {
- name: "Specified other",
- queryAddr: addr4,
- maxDelay: 4,
- expectQueriedReportsFor: nil,
- expectDelayedReportsFor: []tcpip.Address{addr1, addr2},
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t, skipProtocolAddress: addr3}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(3)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- mgp.joinGroup(addr1)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr2)
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr3)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receiving a query should make us reschedule our delayed report timer
- // to some time within the new max response delay.
- mgp.handleQuery(test.queryAddr, test.maxDelay)
- clock.Advance(test.maxDelay)
- if diff := mgp.check(test.expectQueriedReportsFor /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // The groups that were not affected by the query should still send a
- // report after the max unsolicited report delay.
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check(test.expectDelayedReportsFor /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should have no more messages to send.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- })
- }
-}
-
-func TestJoinCount(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(4)),
- Clock: clock,
- MaxUnsolicitedReportDelay: time.Second,
- })
-
- // Set the join count to 2 for a group.
- mgp.joinGroup(addr1)
- if !mgp.isLocallyJoined(addr1) {
- t.Fatalf("got mgp.isLocallyJoined(%s) = false, want = true", addr1)
- }
- // Only the first join should trigger a report to be sent.
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr1)
- if !mgp.isLocallyJoined(addr1) {
- t.Errorf("got mgp.isLocallyJoined(%s) = false, want = true", addr1)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- if t.Failed() {
- t.FailNow()
- }
-
- // Group should still be considered joined after leaving once.
- if !mgp.leaveGroup(addr1) {
- t.Errorf("got mgp.leaveGroup(%s) = false, want = true", addr1)
- }
- if !mgp.isLocallyJoined(addr1) {
- t.Errorf("got mgp.isLocallyJoined(%s) = false, want = true", addr1)
- }
- // A leave report should only be sent once the join count reaches 0.
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- if t.Failed() {
- t.FailNow()
- }
-
- // Leaving once more should actually remove us from the group.
- if !mgp.leaveGroup(addr1) {
- t.Errorf("got mgp.leaveGroup(%s) = false, want = true", addr1)
- }
- if mgp.isLocallyJoined(addr1) {
- t.Errorf("got mgp.isLocallyJoined(%s) = true, want = false", addr1)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, []tcpip.Address{addr1} /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- if t.Failed() {
- t.FailNow()
- }
-
- // Group should no longer be joined so we should not have anything to
- // leave.
- if mgp.leaveGroup(addr1) {
- t.Errorf("got mgp.leaveGroup(%s) = true, want = false", addr1)
- }
- if mgp.isLocallyJoined(addr1) {
- t.Errorf("got mgp.isLocallyJoined(%s) = true, want = false", addr1)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should have no more messages to send.
- //
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-}
-
-func TestMakeAllNonMemberAndInitialize(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t, skipProtocolAddress: addr3}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(3)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- mgp.joinGroup(addr1)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr2)
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr3)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should send the leave reports for each but still consider them locally
- // joined.
- mgp.makeAllNonMember()
- if diff := mgp.check(nil /* sendReportGroupAddresses */, []tcpip.Address{addr1, addr2} /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- for _, group := range []tcpip.Address{addr1, addr2, addr3} {
- if !mgp.isLocallyJoined(group) {
- t.Fatalf("got mgp.isLocallyJoined(%s) = false, want = true", group)
- }
- }
-
- // Should send the initial set of unsolcited reports.
- mgp.initializeGroups()
- if diff := mgp.check([]tcpip.Address{addr1, addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check([]tcpip.Address{addr1, addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should have no more messages to send.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-}
-
-// TestGroupStateNonMember tests that groups do not send packets when in the
-// non-member state, but are still considered locally joined.
-func TestGroupStateNonMember(t *testing.T) {
- mgp := mockMulticastGroupProtocol{t: t}
- clock := faketime.NewManualClock()
-
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(3)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
- mgp.setEnabled(false)
-
- // Joining groups should not send any reports.
- mgp.joinGroup(addr1)
- if !mgp.isLocallyJoined(addr1) {
- t.Fatalf("got mgp.isLocallyJoined(%s) = false, want = true", addr1)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.joinGroup(addr2)
- if !mgp.isLocallyJoined(addr1) {
- t.Fatalf("got mgp.isLocallyJoined(%s) = false, want = true", addr2)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receiving a query should not send any reports.
- mgp.handleQuery(addr1, time.Nanosecond)
- // Generic multicast protocol timers are expected to take the job mutex.
- clock.Advance(time.Nanosecond)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Leaving groups should not send any leave messages.
- if !mgp.leaveGroup(addr1) {
- t.Errorf("got mgp.leaveGroup(%s) = false, want = true", addr2)
- }
- if mgp.isLocallyJoined(addr1) {
- t.Errorf("got mgp.isLocallyJoined(%s) = true, want = false", addr2)
- }
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-}
-
-func TestQueuedPackets(t *testing.T) {
- clock := faketime.NewManualClock()
- mgp := mockMulticastGroupProtocol{t: t}
- mgp.init(ip.GenericMulticastProtocolOptions{
- Rand: rand.New(rand.NewSource(4)),
- Clock: clock,
- MaxUnsolicitedReportDelay: maxUnsolicitedReportDelay,
- })
-
- // Joining should trigger a SendReport, but mgp should report that we did not
- // send the packet.
- mgp.setQueuePackets(true)
- mgp.joinGroup(addr1)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // The delayed report timer should have been cancelled since we did not send
- // the initial report earlier.
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Mock being able to successfully send the report.
- mgp.setQueuePackets(false)
- mgp.sendQueuedReports()
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // The delayed report (sent after the initial report) should now be sent.
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anything else to send (we should be idle).
- mgp.sendQueuedReports()
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receive a query but mock being unable to send reports again.
- mgp.setQueuePackets(true)
- mgp.handleQuery(addr1, time.Nanosecond)
- clock.Advance(time.Nanosecond)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Mock being able to send reports again - we should have a packet queued to
- // send.
- mgp.setQueuePackets(false)
- mgp.sendQueuedReports()
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anything else to send.
- mgp.sendQueuedReports()
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receive a query again, but mock being unable to send reports.
- mgp.setQueuePackets(true)
- mgp.handleQuery(addr1, time.Nanosecond)
- clock.Advance(time.Nanosecond)
- if diff := mgp.check([]tcpip.Address{addr1} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Receiving a report should should transition us into the idle member state,
- // even if we had a packet queued. We should no longer have any packets to
- // send.
- mgp.handleReport(addr1)
- mgp.sendQueuedReports()
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // When we fail to send the initial set of reports, incoming reports should
- // not affect a newly joined group's reports from being sent.
- mgp.setQueuePackets(true)
- mgp.joinGroup(addr2)
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- mgp.handleReport(addr2)
- // Attempting to send queued reports while still unable to send reports should
- // not change the host state.
- mgp.sendQueuedReports()
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- // Mock being able to successfully send the report.
- mgp.setQueuePackets(false)
- mgp.sendQueuedReports()
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
- // The delayed report (sent after the initial report) should now be sent.
- clock.Advance(maxUnsolicitedReportDelay)
- if diff := mgp.check([]tcpip.Address{addr2} /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Errorf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-
- // Should not have anything else to send.
- mgp.sendQueuedReports()
- clock.Advance(time.Hour)
- if diff := mgp.check(nil /* sendReportGroupAddresses */, nil /* sendLeaveGroupAddresses */); diff != "" {
- t.Fatalf("mockMulticastGroupProtocol mismatch (-want +got):\n%s", diff)
- }
-}
diff --git a/pkg/tcpip/network/internal/ip/ip_state_autogen.go b/pkg/tcpip/network/internal/ip/ip_state_autogen.go
new file mode 100644
index 000000000..360922bfe
--- /dev/null
+++ b/pkg/tcpip/network/internal/ip/ip_state_autogen.go
@@ -0,0 +1,32 @@
+// automatically generated by stateify.
+
+package ip
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (e *ErrMessageTooLong) StateTypeName() string {
+ return "pkg/tcpip/network/internal/ip.ErrMessageTooLong"
+}
+
+func (e *ErrMessageTooLong) StateFields() []string {
+ return []string{}
+}
+
+func (e *ErrMessageTooLong) beforeSave() {}
+
+// +checklocksignore
+func (e *ErrMessageTooLong) StateSave(stateSinkObject state.Sink) {
+ e.beforeSave()
+}
+
+func (e *ErrMessageTooLong) afterLoad() {}
+
+// +checklocksignore
+func (e *ErrMessageTooLong) StateLoad(stateSourceObject state.Source) {
+}
+
+func init() {
+ state.Register((*ErrMessageTooLong)(nil))
+}