gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/stack/nic_test.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package stack 16 17 import ( 18 "reflect" 19 "testing" 20 21 "gvisor.dev/gvisor/pkg/atomicbitops" 22 "gvisor.dev/gvisor/pkg/buffer" 23 "gvisor.dev/gvisor/pkg/tcpip" 24 "gvisor.dev/gvisor/pkg/tcpip/header" 25 "gvisor.dev/gvisor/pkg/tcpip/testutil" 26 ) 27 28 var _ AddressableEndpoint = (*testIPv6Endpoint)(nil) 29 var _ NetworkEndpoint = (*testIPv6Endpoint)(nil) 30 var _ NDPEndpoint = (*testIPv6Endpoint)(nil) 31 32 // An IPv6 NetworkEndpoint that throws away outgoing packets. 33 // 34 // We use this instead of ipv6.endpoint because the ipv6 package depends on 35 // the stack package which this test lives in, causing a cyclic dependency. 36 type testIPv6Endpoint struct { 37 AddressableEndpointState 38 39 nic NetworkInterface 40 protocol *testIPv6Protocol 41 42 invalidatedRtr tcpip.Address 43 } 44 45 func (*testIPv6Endpoint) Enable() tcpip.Error { 46 return nil 47 } 48 49 func (*testIPv6Endpoint) Enabled() bool { 50 return true 51 } 52 53 func (*testIPv6Endpoint) Disable() {} 54 55 // DefaultTTL implements NetworkEndpoint.DefaultTTL. 56 func (*testIPv6Endpoint) DefaultTTL() uint8 { 57 return 0 58 } 59 60 // MTU implements NetworkEndpoint.MTU. 61 func (e *testIPv6Endpoint) MTU() uint32 { 62 return e.nic.MTU() - header.IPv6MinimumSize 63 } 64 65 // MaxHeaderLength implements NetworkEndpoint.MaxHeaderLength. 66 func (e *testIPv6Endpoint) MaxHeaderLength() uint16 { 67 return e.nic.MaxHeaderLength() + header.IPv6MinimumSize 68 } 69 70 // WritePacket implements NetworkEndpoint.WritePacket. 71 func (*testIPv6Endpoint) WritePacket(*Route, NetworkHeaderParams, *PacketBuffer) tcpip.Error { 72 return nil 73 } 74 75 // WriteHeaderIncludedPacket implements 76 // NetworkEndpoint.WriteHeaderIncludedPacket. 77 func (*testIPv6Endpoint) WriteHeaderIncludedPacket(*Route, *PacketBuffer) tcpip.Error { 78 // Our tests don't use this so we don't support it. 79 return &tcpip.ErrNotSupported{} 80 } 81 82 // HandlePacket implements NetworkEndpoint.HandlePacket. 83 func (*testIPv6Endpoint) HandlePacket(*PacketBuffer) {} 84 85 // Close implements NetworkEndpoint.Close. 86 func (e *testIPv6Endpoint) Close() { 87 e.AddressableEndpointState.Cleanup() 88 } 89 90 // NetworkProtocolNumber implements NetworkEndpoint.NetworkProtocolNumber. 91 func (*testIPv6Endpoint) NetworkProtocolNumber() tcpip.NetworkProtocolNumber { 92 return header.IPv6ProtocolNumber 93 } 94 95 func (e *testIPv6Endpoint) InvalidateDefaultRouter(rtr tcpip.Address) { 96 e.invalidatedRtr = rtr 97 } 98 99 // Stats implements NetworkEndpoint. 100 func (*testIPv6Endpoint) Stats() NetworkEndpointStats { 101 return &testIPv6EndpointStats{} 102 } 103 104 var _ NetworkEndpointStats = (*testIPv6EndpointStats)(nil) 105 106 type testIPv6EndpointStats struct{} 107 108 // IsNetworkEndpointStats implements stack.NetworkEndpointStats. 109 func (*testIPv6EndpointStats) IsNetworkEndpointStats() {} 110 111 // We use this instead of ipv6.protocol because the ipv6 package depends on 112 // the stack package which this test lives in, causing a cyclic dependency. 113 type testIPv6Protocol struct{} 114 115 // Number implements NetworkProtocol.Number. 116 func (*testIPv6Protocol) Number() tcpip.NetworkProtocolNumber { 117 return header.IPv6ProtocolNumber 118 } 119 120 // MinimumPacketSize implements NetworkProtocol.MinimumPacketSize. 121 func (*testIPv6Protocol) MinimumPacketSize() int { 122 return header.IPv6MinimumSize 123 } 124 125 // ParseAddresses implements NetworkProtocol.ParseAddresses. 126 func (*testIPv6Protocol) ParseAddresses(v []byte) (src, dst tcpip.Address) { 127 h := header.IPv6(v) 128 return h.SourceAddress(), h.DestinationAddress() 129 } 130 131 // NewEndpoint implements NetworkProtocol.NewEndpoint. 132 func (p *testIPv6Protocol) NewEndpoint(nic NetworkInterface, _ TransportDispatcher) NetworkEndpoint { 133 e := &testIPv6Endpoint{ 134 nic: nic, 135 protocol: p, 136 } 137 e.AddressableEndpointState.Init(e, AddressableEndpointStateOptions{HiddenWhileDisabled: false}) 138 return e 139 } 140 141 // SetOption implements NetworkProtocol.SetOption. 142 func (*testIPv6Protocol) SetOption(tcpip.SettableNetworkProtocolOption) tcpip.Error { 143 return nil 144 } 145 146 // Option implements NetworkProtocol.Option. 147 func (*testIPv6Protocol) Option(tcpip.GettableNetworkProtocolOption) tcpip.Error { 148 return nil 149 } 150 151 // Close implements NetworkProtocol.Close. 152 func (*testIPv6Protocol) Close() {} 153 154 // Wait implements NetworkProtocol.Wait. 155 func (*testIPv6Protocol) Wait() {} 156 157 // Parse implements NetworkProtocol.Parse. 158 func (*testIPv6Protocol) Parse(*PacketBuffer) (tcpip.TransportProtocolNumber, bool, bool) { 159 return 0, false, false 160 } 161 162 func TestDisabledRxStatsWhenNICDisabled(t *testing.T) { 163 // When the NIC is disabled, the only field that matters is the stats field. 164 // This test is limited to stats counter checks. 165 nic := nic{ 166 stats: makeNICStats(tcpip.NICStats{}.FillIn()), 167 } 168 169 if got := nic.stats.local.DisabledRx.Packets.Value(); got != 0 { 170 t.Errorf("got DisabledRx.Packets = %d, want = 0", got) 171 } 172 if got := nic.stats.local.DisabledRx.Bytes.Value(); got != 0 { 173 t.Errorf("got DisabledRx.Bytes = %d, want = 0", got) 174 } 175 if got := nic.stats.local.Rx.Packets.Value(); got != 0 { 176 t.Errorf("got Rx.Packets = %d, want = 0", got) 177 } 178 if got := nic.stats.local.Rx.Bytes.Value(); got != 0 { 179 t.Errorf("got Rx.Bytes = %d, want = 0", got) 180 } 181 182 if t.Failed() { 183 t.FailNow() 184 } 185 186 nic.DeliverNetworkPacket(0, NewPacketBuffer(PacketBufferOptions{ 187 Payload: buffer.MakeWithData([]byte{1, 2, 3, 4}), 188 })) 189 190 if got := nic.stats.local.DisabledRx.Packets.Value(); got != 1 { 191 t.Errorf("got DisabledRx.Packets = %d, want = 1", got) 192 } 193 if got := nic.stats.local.DisabledRx.Bytes.Value(); got != 4 { 194 t.Errorf("got DisabledRx.Bytes = %d, want = 4", got) 195 } 196 if got := nic.stats.local.Rx.Packets.Value(); got != 0 { 197 t.Errorf("got Rx.Packets = %d, want = 0", got) 198 } 199 if got := nic.stats.local.Rx.Bytes.Value(); got != 0 { 200 t.Errorf("got Rx.Bytes = %d, want = 0", got) 201 } 202 } 203 204 func TestPacketWithUnknownNetworkProtocolNumber(t *testing.T) { 205 nic := nic{ 206 stats: makeNICStats(tcpip.NICStats{}.FillIn()), 207 enabled: atomicbitops.FromBool(true), 208 } 209 // IPv4 isn't recognized since we haven't initialized the NIC with an IPv4 210 // endpoint. 211 nic.DeliverNetworkPacket(header.IPv4ProtocolNumber, NewPacketBuffer(PacketBufferOptions{ 212 Payload: buffer.MakeWithData([]byte{1, 2, 3, 4}), 213 })) 214 var count uint64 215 if got, ok := nic.stats.local.UnknownL3ProtocolRcvdPacketCounts.Get(uint64(header.IPv4ProtocolNumber)); ok { 216 count = got.Value() 217 } 218 if count != 1 { 219 t.Errorf("got UnknownL3ProtocolRcvdPacketCounts[header.IPv4ProtocolNumber] = %d, want = 1", count) 220 } 221 } 222 223 func TestPacketWithUnknownTransportProtocolNumber(t *testing.T) { 224 nic := nic{ 225 stack: &Stack{}, 226 stats: makeNICStats(tcpip.NICStats{}.FillIn()), 227 enabled: atomicbitops.FromBool(true), 228 } 229 // UDP isn't recognized since we haven't initialized the NIC with a UDP 230 // protocol. 231 nic.DeliverTransportPacket(header.UDPProtocolNumber, NewPacketBuffer(PacketBufferOptions{ 232 Payload: buffer.MakeWithData([]byte{1, 2, 3, 4}), 233 })) 234 var count uint64 235 if got, ok := nic.stats.local.UnknownL4ProtocolRcvdPacketCounts.Get(uint64(header.UDPProtocolNumber)); ok { 236 count = got.Value() 237 } 238 if count != 1 { 239 t.Errorf("got UnknownL4ProtocolRcvdPacketCounts[header.UDPProtocolNumber] = %d, want = 1", count) 240 } 241 } 242 243 func TestMultiCounterStatsInitialization(t *testing.T) { 244 global := tcpip.NICStats{}.FillIn() 245 nic := nic{ 246 stats: makeNICStats(global), 247 } 248 multi := nic.stats.multiCounterNICStats 249 local := nic.stats.local 250 if err := testutil.ValidateMultiCounterStats(reflect.ValueOf(&multi).Elem(), []reflect.Value{reflect.ValueOf(&local).Elem(), reflect.ValueOf(&global).Elem()}, testutil.ValidateMultiCounterStatsOptions{ 251 ExpectMultiCounterStat: true, 252 ExpectMultiIntegralStatCounterMap: true, 253 }); err != nil { 254 t.Error(err) 255 } 256 }