gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/stack/forwarding_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 "encoding/binary" 19 "math" 20 "testing" 21 "time" 22 23 "gvisor.dev/gvisor/pkg/buffer" 24 "gvisor.dev/gvisor/pkg/sync" 25 "gvisor.dev/gvisor/pkg/tcpip" 26 "gvisor.dev/gvisor/pkg/tcpip/faketime" 27 "gvisor.dev/gvisor/pkg/tcpip/header" 28 ) 29 30 const ( 31 fwdTestNetNumber tcpip.NetworkProtocolNumber = math.MaxUint32 32 fwdTestNetHeaderLen = 12 33 fwdTestNetDefaultPrefixLen = 8 34 35 // fwdTestNetDefaultMTU is the MTU, in bytes, used throughout the tests, 36 // except where another value is explicitly used. It is chosen to match 37 // the MTU of loopback interfaces on linux systems. 38 fwdTestNetDefaultMTU = 65536 39 40 dstAddrOffset = 0 41 srcAddrOffset = 4 42 protocolNumberOffset = 8 43 ) 44 45 var _ LinkAddressResolver = (*fwdTestNetworkEndpoint)(nil) 46 var _ NetworkEndpoint = (*fwdTestNetworkEndpoint)(nil) 47 48 // fwdTestNetworkEndpoint is a network-layer protocol endpoint. 49 // Headers of this protocol are fwdTestNetHeaderLen bytes, but we currently only 50 // use the first three: destination address, source address, and transport 51 // protocol. They're all one byte fields to simplify parsing. 52 type fwdTestNetworkEndpoint struct { 53 AddressableEndpointState 54 55 nic NetworkInterface 56 proto *fwdTestNetworkProtocol 57 dispatcher TransportDispatcher 58 59 mu struct { 60 sync.RWMutex 61 forwarding bool 62 } 63 } 64 65 func (*fwdTestNetworkEndpoint) Enable() tcpip.Error { 66 return nil 67 } 68 69 func (*fwdTestNetworkEndpoint) Enabled() bool { 70 return true 71 } 72 73 func (*fwdTestNetworkEndpoint) Disable() {} 74 75 func (f *fwdTestNetworkEndpoint) MTU() uint32 { 76 return f.nic.MTU() - uint32(f.MaxHeaderLength()) 77 } 78 79 func (*fwdTestNetworkEndpoint) DefaultTTL() uint8 { 80 return 123 81 } 82 83 func (f *fwdTestNetworkEndpoint) HandlePacket(pkt *PacketBuffer) { 84 if _, _, ok := f.proto.Parse(pkt); !ok { 85 return 86 } 87 88 netHdr := pkt.NetworkHeader().Slice() 89 _, dst := f.proto.ParseAddresses(netHdr) 90 91 addressEndpoint := f.AcquireAssignedAddress(dst, f.nic.Promiscuous(), CanBePrimaryEndpoint, true /* readOnly */) 92 if addressEndpoint != nil { 93 // Dispatch the packet to the transport protocol. 94 f.dispatcher.DeliverTransportPacket(tcpip.TransportProtocolNumber(netHdr[protocolNumberOffset]), pkt) 95 return 96 } 97 98 r, err := f.proto.stack.FindRoute(0, tcpip.Address{}, dst, fwdTestNetNumber, false /* multicastLoop */) 99 if err != nil { 100 return 101 } 102 defer r.Release() 103 104 pkt = NewPacketBuffer(PacketBufferOptions{ 105 ReserveHeaderBytes: int(r.MaxHeaderLength()), 106 Payload: pkt.ToBuffer(), 107 }) 108 // TODO(gvisor.dev/issue/1085) Decrease the TTL field in forwarded packets. 109 _ = r.WriteHeaderIncludedPacket(pkt) 110 } 111 112 func (f *fwdTestNetworkEndpoint) MaxHeaderLength() uint16 { 113 return f.nic.MaxHeaderLength() + fwdTestNetHeaderLen 114 } 115 116 func (f *fwdTestNetworkEndpoint) NetworkProtocolNumber() tcpip.NetworkProtocolNumber { 117 return f.proto.Number() 118 } 119 120 func (f *fwdTestNetworkEndpoint) WritePacket(r *Route, params NetworkHeaderParams, pkt *PacketBuffer) tcpip.Error { 121 // Add the protocol's header to the packet and send it to the link 122 // endpoint. 123 b := pkt.NetworkHeader().Push(fwdTestNetHeaderLen) 124 remote := r.RemoteAddress() 125 local := r.LocalAddress() 126 copy(b[dstAddrOffset:], remote.AsSlice()) 127 copy(b[srcAddrOffset:], local.AsSlice()) 128 b[protocolNumberOffset] = byte(params.Protocol) 129 pkt.NetworkProtocolNumber = fwdTestNetNumber 130 131 return f.nic.WritePacket(r, pkt) 132 } 133 134 func (f *fwdTestNetworkEndpoint) WriteHeaderIncludedPacket(r *Route, pkt *PacketBuffer) tcpip.Error { 135 // The network header should not already be populated. 136 if _, ok := pkt.NetworkHeader().Consume(fwdTestNetHeaderLen); !ok { 137 return &tcpip.ErrMalformedHeader{} 138 } 139 pkt.NetworkProtocolNumber = fwdTestNetNumber 140 141 return f.nic.WritePacket(r, pkt) 142 } 143 144 func (f *fwdTestNetworkEndpoint) Close() { 145 f.AddressableEndpointState.Cleanup() 146 } 147 148 // Stats implements stack.NetworkEndpoint. 149 func (*fwdTestNetworkEndpoint) Stats() NetworkEndpointStats { 150 return &fwdTestNetworkEndpointStats{} 151 } 152 153 var _ NetworkEndpointStats = (*fwdTestNetworkEndpointStats)(nil) 154 155 type fwdTestNetworkEndpointStats struct{} 156 157 // IsNetworkEndpointStats implements stack.NetworkEndpointStats. 158 func (*fwdTestNetworkEndpointStats) IsNetworkEndpointStats() {} 159 160 var _ NetworkProtocol = (*fwdTestNetworkProtocol)(nil) 161 162 // fwdTestNetworkProtocol is a network-layer protocol that implements Address 163 // resolution. 164 type fwdTestNetworkProtocol struct { 165 stack *Stack 166 167 neigh *neighborCache 168 addrResolveDelay time.Duration 169 onLinkAddressResolved func(*neighborCache, tcpip.Address, tcpip.LinkAddress) 170 onResolveStaticAddress func(tcpip.Address) (tcpip.LinkAddress, bool) 171 } 172 173 func (*fwdTestNetworkProtocol) Number() tcpip.NetworkProtocolNumber { 174 return fwdTestNetNumber 175 } 176 177 func (*fwdTestNetworkProtocol) MinimumPacketSize() int { 178 return fwdTestNetHeaderLen 179 } 180 181 func (*fwdTestNetworkProtocol) ParseAddresses(v []byte) (src, dst tcpip.Address) { 182 return tcpip.AddrFrom4Slice(v[srcAddrOffset : srcAddrOffset+4]), tcpip.AddrFrom4Slice(v[dstAddrOffset : dstAddrOffset+4]) 183 } 184 185 func (*fwdTestNetworkProtocol) Parse(pkt *PacketBuffer) (tcpip.TransportProtocolNumber, bool, bool) { 186 netHeader, ok := pkt.NetworkHeader().Consume(fwdTestNetHeaderLen) 187 if !ok { 188 return 0, false, false 189 } 190 return tcpip.TransportProtocolNumber(netHeader[protocolNumberOffset]), true, true 191 } 192 193 func (f *fwdTestNetworkProtocol) NewEndpoint(nic NetworkInterface, dispatcher TransportDispatcher) NetworkEndpoint { 194 e := &fwdTestNetworkEndpoint{ 195 nic: nic, 196 proto: f, 197 dispatcher: dispatcher, 198 } 199 e.AddressableEndpointState.Init(e, AddressableEndpointStateOptions{HiddenWhileDisabled: false}) 200 return e 201 } 202 203 func (*fwdTestNetworkProtocol) SetOption(tcpip.SettableNetworkProtocolOption) tcpip.Error { 204 return &tcpip.ErrUnknownProtocolOption{} 205 } 206 207 func (*fwdTestNetworkProtocol) Option(tcpip.GettableNetworkProtocolOption) tcpip.Error { 208 return &tcpip.ErrUnknownProtocolOption{} 209 } 210 211 func (*fwdTestNetworkProtocol) Close() {} 212 213 func (*fwdTestNetworkProtocol) Wait() {} 214 215 func (f *fwdTestNetworkEndpoint) LinkAddressRequest(addr, _ tcpip.Address, remoteLinkAddr tcpip.LinkAddress) tcpip.Error { 216 if fn := f.proto.onLinkAddressResolved; fn != nil { 217 f.proto.stack.clock.AfterFunc(f.proto.addrResolveDelay, func() { 218 fn(f.proto.neigh, addr, remoteLinkAddr) 219 }) 220 } 221 return nil 222 } 223 224 func (f *fwdTestNetworkEndpoint) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) { 225 if fn := f.proto.onResolveStaticAddress; fn != nil { 226 return fn(addr) 227 } 228 return "", false 229 } 230 231 func (*fwdTestNetworkEndpoint) LinkAddressProtocol() tcpip.NetworkProtocolNumber { 232 return fwdTestNetNumber 233 } 234 235 // Forwarding implements stack.ForwardingNetworkEndpoint. 236 func (f *fwdTestNetworkEndpoint) Forwarding() bool { 237 f.mu.RLock() 238 defer f.mu.RUnlock() 239 return f.mu.forwarding 240 241 } 242 243 // SetForwarding implements stack.ForwardingNetworkEndpoint. 244 func (f *fwdTestNetworkEndpoint) SetForwarding(v bool) bool { 245 f.mu.Lock() 246 defer f.mu.Unlock() 247 prev := f.mu.forwarding 248 f.mu.forwarding = v 249 return prev 250 } 251 252 var _ LinkEndpoint = (*fwdTestLinkEndpoint)(nil) 253 254 type fwdTestLinkEndpoint struct { 255 dispatcher NetworkDispatcher 256 mtu uint32 257 linkAddr tcpip.LinkAddress 258 259 // C is where outbound packets are queued. 260 C chan *PacketBuffer 261 } 262 263 // InjectInbound injects an inbound packet. 264 func (e *fwdTestLinkEndpoint) InjectInbound(protocol tcpip.NetworkProtocolNumber, pkt *PacketBuffer) { 265 e.InjectLinkAddr(protocol, "", pkt) 266 } 267 268 // InjectLinkAddr injects an inbound packet with a remote link address. 269 func (e *fwdTestLinkEndpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remote tcpip.LinkAddress, pkt *PacketBuffer) { 270 e.dispatcher.DeliverNetworkPacket(protocol, pkt) 271 } 272 273 // Attach saves the stack network-layer dispatcher for use later when packets 274 // are injected. 275 func (e *fwdTestLinkEndpoint) Attach(dispatcher NetworkDispatcher) { 276 e.dispatcher = dispatcher 277 } 278 279 // IsAttached implements stack.LinkEndpoint.IsAttached. 280 func (e *fwdTestLinkEndpoint) IsAttached() bool { 281 return e.dispatcher != nil 282 } 283 284 // MTU implements stack.LinkEndpoint.MTU. It returns the value initialized 285 // during construction. 286 func (e *fwdTestLinkEndpoint) MTU() uint32 { 287 return e.mtu 288 } 289 290 // Capabilities implements stack.LinkEndpoint.Capabilities. 291 func (e fwdTestLinkEndpoint) Capabilities() LinkEndpointCapabilities { 292 caps := LinkEndpointCapabilities(0) 293 return caps | CapabilityResolutionRequired 294 } 295 296 // MaxHeaderLength returns the maximum size of the link layer header. Given it 297 // doesn't have a header, it just returns 0. 298 func (*fwdTestLinkEndpoint) MaxHeaderLength() uint16 { 299 return 0 300 } 301 302 // LinkAddress returns the link address of this endpoint. 303 func (e *fwdTestLinkEndpoint) LinkAddress() tcpip.LinkAddress { 304 return e.linkAddr 305 } 306 307 // WritePackets stores outbound packets into the channel. 308 func (e *fwdTestLinkEndpoint) WritePackets(pkts PacketBufferList) (int, tcpip.Error) { 309 n := 0 310 for _, pkt := range pkts.AsSlice() { 311 select { 312 case e.C <- pkt: 313 default: 314 } 315 316 n++ 317 } 318 319 return n, nil 320 } 321 322 // Wait implements stack.LinkEndpoint.Wait. 323 func (*fwdTestLinkEndpoint) Wait() {} 324 325 // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType. 326 func (*fwdTestLinkEndpoint) ARPHardwareType() header.ARPHardwareType { 327 panic("not implemented") 328 } 329 330 // AddHeader implements stack.LinkEndpoint.AddHeader. 331 func (*fwdTestLinkEndpoint) AddHeader(*PacketBuffer) {} 332 333 // ParseHeader implements stack.LinkEndpoint.ParseHeader. 334 func (*fwdTestLinkEndpoint) ParseHeader(*PacketBuffer) bool { return true } 335 336 func fwdTestNetFactory(t *testing.T, proto *fwdTestNetworkProtocol) (*faketime.ManualClock, *fwdTestLinkEndpoint, *fwdTestLinkEndpoint) { 337 clock := faketime.NewManualClock() 338 // Create a stack with the network protocol and two NICs. 339 s := New(Options{ 340 NetworkProtocols: []NetworkProtocolFactory{func(s *Stack) NetworkProtocol { 341 proto.stack = s 342 return proto 343 }}, 344 Clock: clock, 345 }) 346 347 protoNum := proto.Number() 348 if err := s.SetForwardingDefaultAndAllNICs(protoNum, true); err != nil { 349 t.Fatalf("SetForwardingDefaultAndAllNICs(%d, true): %s", protoNum, err) 350 } 351 352 // NIC 1 has the link address "a", and added the network address 1. 353 ep1 := &fwdTestLinkEndpoint{ 354 C: make(chan *PacketBuffer, 300), 355 mtu: fwdTestNetDefaultMTU, 356 linkAddr: "a", 357 } 358 if err := s.CreateNIC(1, ep1); err != nil { 359 t.Fatal("CreateNIC #1 failed:", err) 360 } 361 protocolAddr1 := tcpip.ProtocolAddress{ 362 Protocol: fwdTestNetNumber, 363 AddressWithPrefix: tcpip.AddressWithPrefix{ 364 Address: tcpip.AddrFrom4Slice([]byte("\x01\x00\x00\x00")), 365 PrefixLen: fwdTestNetDefaultPrefixLen, 366 }, 367 } 368 if err := s.AddProtocolAddress(1, protocolAddr1, AddressProperties{}); err != nil { 369 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", 1, protocolAddr1, err) 370 } 371 372 // NIC 2 has the link address "b", and added the network address 2. 373 ep2 := &fwdTestLinkEndpoint{ 374 C: make(chan *PacketBuffer, 300), 375 mtu: fwdTestNetDefaultMTU, 376 linkAddr: "b", 377 } 378 if err := s.CreateNIC(2, ep2); err != nil { 379 t.Fatal("CreateNIC #2 failed:", err) 380 } 381 protocolAddr2 := tcpip.ProtocolAddress{ 382 Protocol: fwdTestNetNumber, 383 AddressWithPrefix: tcpip.AddressWithPrefix{ 384 Address: tcpip.AddrFrom4Slice([]byte("\x02\x00\x00\x00")), 385 PrefixLen: fwdTestNetDefaultPrefixLen, 386 }, 387 } 388 if err := s.AddProtocolAddress(2, protocolAddr2, AddressProperties{}); err != nil { 389 t.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", 2, protocolAddr2, err) 390 } 391 392 s.mu.RLock() 393 nic, ok := s.nics[2] 394 s.mu.RUnlock() 395 if !ok { 396 t.Fatal("NIC 2 does not exist") 397 } 398 399 if l, ok := nic.linkAddrResolvers[fwdTestNetNumber]; ok { 400 proto.neigh = &l.neigh 401 } 402 403 // Route all packets to NIC 2. 404 { 405 subnet, err := tcpip.NewSubnet(tcpip.AddrFrom4Slice([]byte("\x00\x00\x00\x00")), tcpip.MaskFrom("\x00\x00\x00\x00")) 406 if err != nil { 407 t.Fatal(err) 408 } 409 s.SetRouteTable([]tcpip.Route{{Destination: subnet, NIC: 2}}) 410 } 411 412 return clock, ep1, ep2 413 } 414 415 func TestForwardingWithStaticResolver(t *testing.T) { 416 // Create a network protocol with a static resolver. 417 proto := &fwdTestNetworkProtocol{ 418 onResolveStaticAddress: 419 // The network address 3 is resolved to the link address "c". 420 func(addr tcpip.Address) (tcpip.LinkAddress, bool) { 421 if addr == tcpip.AddrFrom4Slice([]byte("\x03\x00\x00\x00")) { 422 return "c", true 423 } 424 return "", false 425 }, 426 } 427 428 clock, ep1, ep2 := fwdTestNetFactory(t, proto) 429 430 // Inject an inbound packet to address 3 on NIC 1, and see if it is 431 // forwarded to NIC 2. 432 buf := make([]byte, 30) 433 copy(buf[dstAddrOffset:], []byte("\x03\x00\x00\x00")) 434 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 435 Payload: buffer.MakeWithData(buf), 436 })) 437 438 var p *PacketBuffer 439 440 clock.Advance(proto.addrResolveDelay) 441 select { 442 case p = <-ep2.C: 443 default: 444 t.Fatal("packet not forwarded") 445 } 446 447 // Test that the static address resolution happened correctly. 448 if p.EgressRoute.RemoteLinkAddress != "c" { 449 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 450 } 451 if p.EgressRoute.LocalLinkAddress != "b" { 452 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 453 } 454 } 455 456 func TestForwardingWithFakeResolver(t *testing.T) { 457 proto := fwdTestNetworkProtocol{ 458 addrResolveDelay: 500 * time.Millisecond, 459 onLinkAddressResolved: func(neigh *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress) { 460 t.Helper() 461 if len(linkAddr) != 0 { 462 t.Fatalf("got linkAddr=%q, want unspecified", linkAddr) 463 } 464 // Any address will be resolved to the link address "c". 465 neigh.handleConfirmation(addr, "c", ReachabilityConfirmationFlags{ 466 Solicited: true, 467 Override: false, 468 IsRouter: false, 469 }) 470 }, 471 } 472 clock, ep1, ep2 := fwdTestNetFactory(t, &proto) 473 474 // Inject an inbound packet to address 3 on NIC 1, and see if it is 475 // forwarded to NIC 2. 476 buf := make([]byte, 30) 477 buf[dstAddrOffset] = 3 478 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 479 Payload: buffer.MakeWithData(buf), 480 })) 481 482 var p *PacketBuffer 483 484 clock.Advance(proto.addrResolveDelay) 485 select { 486 case p = <-ep2.C: 487 default: 488 t.Fatal("packet not forwarded") 489 } 490 491 // Test that the address resolution happened correctly. 492 if p.EgressRoute.RemoteLinkAddress != "c" { 493 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 494 } 495 if p.EgressRoute.LocalLinkAddress != "b" { 496 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 497 } 498 } 499 500 func TestForwardingWithNoResolver(t *testing.T) { 501 // Create a network protocol without a resolver. 502 proto := &fwdTestNetworkProtocol{} 503 504 // Whether or not we use the neighbor cache here does not matter since 505 // neither linkAddrCache nor neighborCache will be used. 506 clock, ep1, ep2 := fwdTestNetFactory(t, proto) 507 508 // inject an inbound packet to address 3 on NIC 1, and see if it is 509 // forwarded to NIC 2. 510 buf := make([]byte, 30) 511 buf[dstAddrOffset] = 3 512 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 513 Payload: buffer.MakeWithData(buf), 514 })) 515 516 clock.Advance(proto.addrResolveDelay) 517 select { 518 case <-ep2.C: 519 t.Fatal("Packet should not be forwarded") 520 default: 521 } 522 } 523 524 func TestForwardingResolutionFailsForQueuedPackets(t *testing.T) { 525 proto := &fwdTestNetworkProtocol{ 526 addrResolveDelay: 50 * time.Millisecond, 527 onLinkAddressResolved: func(*neighborCache, tcpip.Address, tcpip.LinkAddress) { 528 // Don't resolve the link address. 529 }, 530 } 531 532 clock, ep1, ep2 := fwdTestNetFactory(t, proto) 533 534 const numPackets int = 5 535 // These packets will all be enqueued in the packet queue to wait for link 536 // address resolution. 537 for i := 0; i < numPackets; i++ { 538 buf := make([]byte, 30) 539 buf[dstAddrOffset] = 3 540 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 541 Payload: buffer.MakeWithData(buf), 542 })) 543 } 544 545 // All packets should fail resolution. 546 for i := 0; i < numPackets; i++ { 547 clock.Advance(proto.addrResolveDelay) 548 select { 549 case got := <-ep2.C: 550 t.Fatalf("got %#v; packets should have failed resolution and not been forwarded", got) 551 default: 552 } 553 } 554 } 555 556 func TestForwardingWithFakeResolverPartialTimeout(t *testing.T) { 557 proto := fwdTestNetworkProtocol{ 558 addrResolveDelay: 500 * time.Millisecond, 559 onLinkAddressResolved: func(neigh *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress) { 560 t.Helper() 561 if len(linkAddr) != 0 { 562 t.Fatalf("got linkAddr=%q, want unspecified", linkAddr) 563 } 564 // Only packets to address 3 will be resolved to the 565 // link address "c". 566 if addr == tcpip.AddrFrom4Slice([]byte("\x03\x00\x00\x00")) { 567 neigh.handleConfirmation(addr, "c", ReachabilityConfirmationFlags{ 568 Solicited: true, 569 Override: false, 570 IsRouter: false, 571 }) 572 } 573 }, 574 } 575 clock, ep1, ep2 := fwdTestNetFactory(t, &proto) 576 577 // Inject an inbound packet to address 4 on NIC 1. This packet should 578 // not be forwarded. 579 buf := make([]byte, 30) 580 buf[dstAddrOffset] = 4 581 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 582 Payload: buffer.MakeWithData(buf), 583 })) 584 585 // Inject an inbound packet to address 3 on NIC 1, and see if it is 586 // forwarded to NIC 2. 587 buf = make([]byte, 30) 588 buf[dstAddrOffset] = 3 589 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 590 Payload: buffer.MakeWithData(buf), 591 })) 592 593 var p *PacketBuffer 594 595 clock.Advance(proto.addrResolveDelay) 596 select { 597 case p = <-ep2.C: 598 default: 599 t.Fatal("packet not forwarded") 600 } 601 602 nh := PayloadSince(p.NetworkHeader()) 603 defer nh.Release() 604 if nh.AsSlice()[dstAddrOffset] != 3 { 605 t.Fatalf("got p.NetworkHeader[dstAddrOffset] = %d, want = 3", nh.AsSlice()[dstAddrOffset]) 606 } 607 608 // Test that the address resolution happened correctly. 609 if p.EgressRoute.RemoteLinkAddress != "c" { 610 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 611 } 612 if p.EgressRoute.LocalLinkAddress != "b" { 613 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 614 } 615 } 616 617 func TestForwardingWithFakeResolverTwoPackets(t *testing.T) { 618 proto := fwdTestNetworkProtocol{ 619 addrResolveDelay: 500 * time.Millisecond, 620 onLinkAddressResolved: func(neigh *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress) { 621 t.Helper() 622 if len(linkAddr) != 0 { 623 t.Fatalf("got linkAddr=%q, want unspecified", linkAddr) 624 } 625 // Any packets will be resolved to the link address "c". 626 neigh.handleConfirmation(addr, "c", ReachabilityConfirmationFlags{ 627 Solicited: true, 628 Override: false, 629 IsRouter: false, 630 }) 631 }, 632 } 633 clock, ep1, ep2 := fwdTestNetFactory(t, &proto) 634 635 // Inject two inbound packets to address 3 on NIC 1. 636 for i := 0; i < 2; i++ { 637 buf := make([]byte, 30) 638 buf[dstAddrOffset] = 3 639 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 640 Payload: buffer.MakeWithData(buf), 641 })) 642 } 643 644 for i := 0; i < 2; i++ { 645 var p *PacketBuffer 646 647 clock.Advance(proto.addrResolveDelay) 648 select { 649 case p = <-ep2.C: 650 default: 651 t.Fatal("packet not forwarded") 652 } 653 654 nh := PayloadSince(p.NetworkHeader()) 655 defer nh.Release() 656 if nh.AsSlice()[dstAddrOffset] != 3 { 657 t.Fatalf("got p.NetworkHeader[dstAddrOffset] = %d, want = 3", nh.AsSlice()[dstAddrOffset]) 658 } 659 660 // Test that the address resolution happened correctly. 661 if p.EgressRoute.RemoteLinkAddress != "c" { 662 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 663 } 664 if p.EgressRoute.LocalLinkAddress != "b" { 665 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 666 } 667 } 668 } 669 670 func TestForwardingWithFakeResolverManyPackets(t *testing.T) { 671 proto := fwdTestNetworkProtocol{ 672 addrResolveDelay: 500 * time.Millisecond, 673 onLinkAddressResolved: func(neigh *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress) { 674 t.Helper() 675 if len(linkAddr) != 0 { 676 t.Fatalf("got linkAddr=%q, want unspecified", linkAddr) 677 } 678 // Any packets will be resolved to the link address "c". 679 neigh.handleConfirmation(addr, "c", ReachabilityConfirmationFlags{ 680 Solicited: true, 681 Override: false, 682 IsRouter: false, 683 }) 684 }, 685 } 686 clock, ep1, ep2 := fwdTestNetFactory(t, &proto) 687 688 for i := 0; i < maxPendingPacketsPerResolution+5; i++ { 689 // Inject inbound 'maxPendingPacketsPerResolution + 5' packets on NIC 1. 690 buf := make([]byte, 30) 691 buf[dstAddrOffset] = 3 692 // Set the packet sequence number. 693 binary.BigEndian.PutUint16(buf[fwdTestNetHeaderLen:], uint16(i)) 694 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 695 Payload: buffer.MakeWithData(buf), 696 })) 697 } 698 699 for i := 0; i < maxPendingPacketsPerResolution; i++ { 700 var p *PacketBuffer 701 702 clock.Advance(proto.addrResolveDelay) 703 select { 704 case p = <-ep2.C: 705 default: 706 t.Fatal("packet not forwarded") 707 } 708 709 b := PayloadSince(p.NetworkHeader()) 710 defer b.Release() 711 if b.AsSlice()[dstAddrOffset] != 3 { 712 t.Fatalf("got b[dstAddrOffset] = %d, want = 3", b.AsSlice()[dstAddrOffset]) 713 } 714 if b.Size() < fwdTestNetHeaderLen+2 { 715 t.Fatalf("packet is too short to hold a sequence number: len(b) = %d", b.Size()) 716 } 717 seqNumBuf := b.AsSlice()[fwdTestNetHeaderLen:] 718 719 // The first 5 packets should not be forwarded so the sequence number should 720 // start with 5. 721 want := uint16(i + 5) 722 if n := binary.BigEndian.Uint16(seqNumBuf); n != want { 723 t.Fatalf("got the packet #%d, want = #%d", n, want) 724 } 725 726 // Test that the address resolution happened correctly. 727 if p.EgressRoute.RemoteLinkAddress != "c" { 728 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 729 } 730 if p.EgressRoute.LocalLinkAddress != "b" { 731 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 732 } 733 } 734 } 735 736 func TestForwardingWithFakeResolverManyResolutions(t *testing.T) { 737 proto := fwdTestNetworkProtocol{ 738 addrResolveDelay: 500 * time.Millisecond, 739 onLinkAddressResolved: func(neigh *neighborCache, addr tcpip.Address, linkAddr tcpip.LinkAddress) { 740 t.Helper() 741 if len(linkAddr) != 0 { 742 t.Fatalf("got linkAddr=%q, want unspecified", linkAddr) 743 } 744 // Any packets will be resolved to the link address "c". 745 neigh.handleConfirmation(addr, "c", ReachabilityConfirmationFlags{ 746 Solicited: true, 747 Override: false, 748 IsRouter: false, 749 }) 750 }, 751 } 752 clock, ep1, ep2 := fwdTestNetFactory(t, &proto) 753 754 for i := 0; i < maxPendingResolutions+5; i++ { 755 // Inject inbound 'maxPendingResolutions + 5' packets on NIC 1. 756 // Each packet has a different destination address (3 to 757 // maxPendingResolutions + 7). 758 buf := make([]byte, 30) 759 buf[dstAddrOffset] = byte(3 + i) 760 ep1.InjectInbound(fwdTestNetNumber, NewPacketBuffer(PacketBufferOptions{ 761 Payload: buffer.MakeWithData(buf), 762 })) 763 } 764 765 for i := 0; i < maxPendingResolutions; i++ { 766 var p *PacketBuffer 767 768 clock.Advance(proto.addrResolveDelay) 769 select { 770 case p = <-ep2.C: 771 default: 772 t.Fatal("packet not forwarded") 773 } 774 775 // The first 5 packets (address 3 to 7) should not be forwarded 776 // because their address resolutions are interrupted. 777 nh := PayloadSince(p.NetworkHeader()) 778 defer nh.Release() 779 if nh.AsSlice()[dstAddrOffset] < 8 { 780 t.Fatalf("got p.NetworkHeader[dstAddrOffset] = %d, want p.NetworkHeader[dstAddrOffset] >= 8", nh.AsSlice()[dstAddrOffset]) 781 } 782 783 // Test that the address resolution happened correctly. 784 if p.EgressRoute.RemoteLinkAddress != "c" { 785 t.Fatalf("got p.EgressRoute.RemoteLinkAddress = %s, want = c", p.EgressRoute.RemoteLinkAddress) 786 } 787 if p.EgressRoute.LocalLinkAddress != "b" { 788 t.Fatalf("got p.EgressRoute.LocalLinkAddress = %s, want = b", p.EgressRoute.LocalLinkAddress) 789 } 790 } 791 }