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  }