gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/tests/utils/utils.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 utils holds common testing utilities for tcpip.
    16  package utils
    17  
    18  import (
    19  	"testing"
    20  
    21  	"gvisor.dev/gvisor/pkg/buffer"
    22  	"gvisor.dev/gvisor/pkg/tcpip"
    23  	"gvisor.dev/gvisor/pkg/tcpip/checksum"
    24  	"gvisor.dev/gvisor/pkg/tcpip/header"
    25  	"gvisor.dev/gvisor/pkg/tcpip/link/channel"
    26  	"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
    27  	"gvisor.dev/gvisor/pkg/tcpip/link/nested"
    28  	"gvisor.dev/gvisor/pkg/tcpip/link/pipe"
    29  	"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
    30  	"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
    31  	"gvisor.dev/gvisor/pkg/tcpip/prependable"
    32  	"gvisor.dev/gvisor/pkg/tcpip/stack"
    33  	"gvisor.dev/gvisor/pkg/tcpip/testutil"
    34  	"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
    35  )
    36  
    37  // Common NIC IDs used by tests.
    38  const (
    39  	Host1NICID   = 1
    40  	RouterNICID1 = 2
    41  	RouterNICID2 = 3
    42  	Host2NICID   = 4
    43  )
    44  
    45  // Common NIC names used by tests.
    46  const (
    47  	Host1NICName   = "host1NIC"
    48  	RouterNIC1Name = "routerNIC1"
    49  	RouterNIC2Name = "routerNIC2"
    50  	Host2NICName   = "host2NIC"
    51  )
    52  
    53  // Common link addresses used by tests.
    54  const (
    55  	LinkAddr1 = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x06")
    56  	LinkAddr2 = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x07")
    57  	LinkAddr3 = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x08")
    58  	LinkAddr4 = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x09")
    59  )
    60  
    61  // Common IP addresses used by tests.
    62  var (
    63  	Ipv4Addr = tcpip.AddressWithPrefix{
    64  		Address:   testutil.MustParse4("192.168.1.58"),
    65  		PrefixLen: 24,
    66  	}
    67  	Ipv4Subnet      = Ipv4Addr.Subnet()
    68  	Ipv4SubnetBcast = Ipv4Subnet.Broadcast()
    69  
    70  	Ipv6Addr = tcpip.AddressWithPrefix{
    71  		Address:   testutil.MustParse6("200a::1"),
    72  		PrefixLen: 64,
    73  	}
    74  	Ipv6Subnet      = Ipv6Addr.Subnet()
    75  	Ipv6SubnetBcast = Ipv6Subnet.Broadcast()
    76  
    77  	Ipv4Addr1 = tcpip.ProtocolAddress{
    78  		Protocol: ipv4.ProtocolNumber,
    79  		AddressWithPrefix: tcpip.AddressWithPrefix{
    80  			Address:   testutil.MustParse4("192.168.0.1"),
    81  			PrefixLen: 24,
    82  		},
    83  	}
    84  	Ipv4Addr2 = tcpip.ProtocolAddress{
    85  		Protocol: ipv4.ProtocolNumber,
    86  		AddressWithPrefix: tcpip.AddressWithPrefix{
    87  			Address:   testutil.MustParse4("192.168.0.2"),
    88  			PrefixLen: 8,
    89  		},
    90  	}
    91  	Ipv4Addr3 = tcpip.ProtocolAddress{
    92  		Protocol: ipv4.ProtocolNumber,
    93  		AddressWithPrefix: tcpip.AddressWithPrefix{
    94  			Address:   testutil.MustParse4("192.168.0.3"),
    95  			PrefixLen: 8,
    96  		},
    97  	}
    98  	Ipv6Addr1 = tcpip.ProtocolAddress{
    99  		Protocol: ipv6.ProtocolNumber,
   100  		AddressWithPrefix: tcpip.AddressWithPrefix{
   101  			Address:   testutil.MustParse6("a::1"),
   102  			PrefixLen: 64,
   103  		},
   104  	}
   105  	Ipv6Addr2 = tcpip.ProtocolAddress{
   106  		Protocol: ipv6.ProtocolNumber,
   107  		AddressWithPrefix: tcpip.AddressWithPrefix{
   108  			Address:   testutil.MustParse6("a::2"),
   109  			PrefixLen: 64,
   110  		},
   111  	}
   112  	Ipv6Addr3 = tcpip.ProtocolAddress{
   113  		Protocol: ipv6.ProtocolNumber,
   114  		AddressWithPrefix: tcpip.AddressWithPrefix{
   115  			Address:   testutil.MustParse6("a::3"),
   116  			PrefixLen: 64,
   117  		},
   118  	}
   119  
   120  	// Remote addrs.
   121  	RemoteIPv4Addr = testutil.MustParse4("10.0.0.1")
   122  	RemoteIPv6Addr = testutil.MustParse6("200b::1")
   123  )
   124  
   125  // Common ports for testing.
   126  const (
   127  	RemotePort = 5555
   128  	LocalPort  = 80
   129  )
   130  
   131  // Common IP addresses used for testing.
   132  var (
   133  	Host1IPv4Addr = tcpip.ProtocolAddress{
   134  		Protocol: ipv4.ProtocolNumber,
   135  		AddressWithPrefix: tcpip.AddressWithPrefix{
   136  			Address:   testutil.MustParse4("192.168.0.2"),
   137  			PrefixLen: 24,
   138  		},
   139  	}
   140  	RouterNIC1IPv4Addr = tcpip.ProtocolAddress{
   141  		Protocol: ipv4.ProtocolNumber,
   142  		AddressWithPrefix: tcpip.AddressWithPrefix{
   143  			Address:   testutil.MustParse4("192.168.0.1"),
   144  			PrefixLen: 24,
   145  		},
   146  	}
   147  	RouterNIC2IPv4Addr = tcpip.ProtocolAddress{
   148  		Protocol: ipv4.ProtocolNumber,
   149  		AddressWithPrefix: tcpip.AddressWithPrefix{
   150  			Address:   testutil.MustParse4("10.0.0.3"),
   151  			PrefixLen: 8,
   152  		},
   153  	}
   154  	Host2IPv4Addr = tcpip.ProtocolAddress{
   155  		Protocol: ipv4.ProtocolNumber,
   156  		AddressWithPrefix: tcpip.AddressWithPrefix{
   157  			Address:   testutil.MustParse4("10.0.0.2"),
   158  			PrefixLen: 8,
   159  		},
   160  	}
   161  	Host1IPv6Addr = tcpip.ProtocolAddress{
   162  		Protocol: ipv6.ProtocolNumber,
   163  		AddressWithPrefix: tcpip.AddressWithPrefix{
   164  			Address:   testutil.MustParse6("a::2"),
   165  			PrefixLen: 64,
   166  		},
   167  	}
   168  	RouterNIC1IPv6Addr = tcpip.ProtocolAddress{
   169  		Protocol: ipv6.ProtocolNumber,
   170  		AddressWithPrefix: tcpip.AddressWithPrefix{
   171  			Address:   testutil.MustParse6("a::1"),
   172  			PrefixLen: 64,
   173  		},
   174  	}
   175  	RouterNIC2IPv6Addr = tcpip.ProtocolAddress{
   176  		Protocol: ipv6.ProtocolNumber,
   177  		AddressWithPrefix: tcpip.AddressWithPrefix{
   178  			Address:   testutil.MustParse6("b::1"),
   179  			PrefixLen: 64,
   180  		},
   181  	}
   182  	Host2IPv6Addr = tcpip.ProtocolAddress{
   183  		Protocol: ipv6.ProtocolNumber,
   184  		AddressWithPrefix: tcpip.AddressWithPrefix{
   185  			Address:   testutil.MustParse6("b::2"),
   186  			PrefixLen: 64,
   187  		},
   188  	}
   189  )
   190  
   191  // NewEthernetEndpoint returns an ethernet link endpoint that wraps an inner
   192  // link endpoint and checks the destination link address before delivering
   193  // network packets to the network dispatcher.
   194  //
   195  // See ethernet.Endpoint for more details.
   196  func NewEthernetEndpoint(ep stack.LinkEndpoint) *EndpointWithDestinationCheck {
   197  	var e EndpointWithDestinationCheck
   198  	e.Endpoint.Init(ethernet.New(ep), &e)
   199  	return &e
   200  }
   201  
   202  // EndpointWithDestinationCheck is a link endpoint that checks the destination
   203  // link address before delivering network packets to the network dispatcher.
   204  type EndpointWithDestinationCheck struct {
   205  	nested.Endpoint
   206  }
   207  
   208  var _ stack.NetworkDispatcher = (*EndpointWithDestinationCheck)(nil)
   209  var _ stack.LinkEndpoint = (*EndpointWithDestinationCheck)(nil)
   210  
   211  // DeliverNetworkPacket implements stack.NetworkDispatcher.
   212  func (e *EndpointWithDestinationCheck) DeliverNetworkPacket(proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
   213  	if dst := header.Ethernet(pkt.LinkHeader().Slice()).DestinationAddress(); dst == e.Endpoint.LinkAddress() || dst == header.EthernetBroadcastAddress || header.IsMulticastEthernetAddress(dst) {
   214  		e.Endpoint.DeliverNetworkPacket(proto, pkt)
   215  	}
   216  }
   217  
   218  // SetupRouterStack creates the NICs, sets forwarding, adds addresses and sets
   219  // the route table for a stack that should operate as a router.
   220  func SetupRouterStack(t *testing.T, s *stack.Stack, ep1, ep2 stack.LinkEndpoint) {
   221  
   222  	if err := s.SetForwardingDefaultAndAllNICs(ipv4.ProtocolNumber, true); err != nil {
   223  		t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d): %s", ipv4.ProtocolNumber, err)
   224  	}
   225  	if err := s.SetForwardingDefaultAndAllNICs(ipv6.ProtocolNumber, true); err != nil {
   226  		t.Fatalf("s.SetForwardingDefaultAndAllNICs(%d): %s", ipv6.ProtocolNumber, err)
   227  	}
   228  
   229  	for _, setup := range []struct {
   230  		nicID   tcpip.NICID
   231  		nicName string
   232  		ep      stack.LinkEndpoint
   233  
   234  		addresses [2]tcpip.ProtocolAddress
   235  	}{
   236  		{
   237  			nicID:     RouterNICID1,
   238  			nicName:   RouterNIC1Name,
   239  			ep:        ep1,
   240  			addresses: [2]tcpip.ProtocolAddress{RouterNIC1IPv4Addr, RouterNIC1IPv6Addr},
   241  		},
   242  		{
   243  			nicID:     RouterNICID2,
   244  			nicName:   RouterNIC2Name,
   245  			ep:        ep2,
   246  			addresses: [2]tcpip.ProtocolAddress{RouterNIC2IPv4Addr, RouterNIC2IPv6Addr},
   247  		},
   248  	} {
   249  		opts := stack.NICOptions{Name: setup.nicName}
   250  		if err := s.CreateNICWithOptions(setup.nicID, setup.ep, opts); err != nil {
   251  			t.Fatalf("s.CreateNICWithOptions(%d, _, %#v): %s", setup.nicID, opts, err)
   252  		}
   253  
   254  		for _, addr := range setup.addresses {
   255  			if err := s.AddProtocolAddress(setup.nicID, addr, stack.AddressProperties{}); err != nil {
   256  				t.Fatalf("s.AddProtocolAddress(%d, %#v, {}): %s", setup.nicID, addr, err)
   257  			}
   258  		}
   259  	}
   260  
   261  	s.SetRouteTable([]tcpip.Route{
   262  		{
   263  			Destination: RouterNIC1IPv4Addr.AddressWithPrefix.Subnet(),
   264  			NIC:         RouterNICID1,
   265  		},
   266  		{
   267  			Destination: RouterNIC1IPv6Addr.AddressWithPrefix.Subnet(),
   268  			NIC:         RouterNICID1,
   269  		},
   270  		{
   271  			Destination: RouterNIC2IPv4Addr.AddressWithPrefix.Subnet(),
   272  			NIC:         RouterNICID2,
   273  		},
   274  		{
   275  			Destination: RouterNIC2IPv6Addr.AddressWithPrefix.Subnet(),
   276  			NIC:         RouterNICID2,
   277  		},
   278  	})
   279  }
   280  
   281  // SetupRoutedStacks creates the NICs, sets forwarding, adds addresses and sets
   282  // the route tables for the passed stacks.
   283  func SetupRoutedStacks(t *testing.T, host1Stack, routerStack, host2Stack *stack.Stack) {
   284  	const maxFrameSize = header.IPv6MinimumMTU + header.EthernetMinimumSize
   285  	host1NIC, routerNIC1 := pipe.New(LinkAddr1, LinkAddr2, maxFrameSize)
   286  	routerNIC2, host2NIC := pipe.New(LinkAddr3, LinkAddr4, maxFrameSize)
   287  
   288  	SetupRouterStack(t, routerStack, NewEthernetEndpoint(routerNIC1), NewEthernetEndpoint(routerNIC2))
   289  
   290  	{
   291  		opts := stack.NICOptions{Name: Host1NICName}
   292  		if err := host1Stack.CreateNICWithOptions(Host1NICID, NewEthernetEndpoint(host1NIC), opts); err != nil {
   293  			t.Fatalf("host1Stack.CreateNICWithOptions(%d, _, %#v): %s", Host1NICID, opts, err)
   294  		}
   295  	}
   296  	{
   297  		opts := stack.NICOptions{Name: Host2NICName}
   298  		if err := host2Stack.CreateNICWithOptions(Host2NICID, NewEthernetEndpoint(host2NIC), opts); err != nil {
   299  			t.Fatalf("host2Stack.CreateNICWithOptions(%d, _, %#v): %s", Host2NICID, opts, err)
   300  		}
   301  	}
   302  
   303  	if err := host1Stack.AddProtocolAddress(Host1NICID, Host1IPv4Addr, stack.AddressProperties{}); err != nil {
   304  		t.Fatalf("host1Stack.AddProtocolAddress(%d, %+v, {}): %s", Host1NICID, Host1IPv4Addr, err)
   305  	}
   306  	if err := host2Stack.AddProtocolAddress(Host2NICID, Host2IPv4Addr, stack.AddressProperties{}); err != nil {
   307  		t.Fatalf("host2Stack.AddProtocolAddress(%d, %+v, {}): %s", Host2NICID, Host2IPv4Addr, err)
   308  	}
   309  	if err := host1Stack.AddProtocolAddress(Host1NICID, Host1IPv6Addr, stack.AddressProperties{}); err != nil {
   310  		t.Fatalf("host1Stack.AddProtocolAddress(%d, %+v, {}): %s", Host1NICID, Host1IPv6Addr, err)
   311  	}
   312  	if err := host2Stack.AddProtocolAddress(Host2NICID, Host2IPv6Addr, stack.AddressProperties{}); err != nil {
   313  		t.Fatalf("host2Stack.AddProtocolAddress(%d, %+v, {}): %s", Host2NICID, Host2IPv6Addr, err)
   314  	}
   315  
   316  	host1Stack.SetRouteTable([]tcpip.Route{
   317  		{
   318  			Destination: Host1IPv4Addr.AddressWithPrefix.Subnet(),
   319  			NIC:         Host1NICID,
   320  		},
   321  		{
   322  			Destination: Host1IPv6Addr.AddressWithPrefix.Subnet(),
   323  			NIC:         Host1NICID,
   324  		},
   325  		{
   326  			Destination: Host2IPv4Addr.AddressWithPrefix.Subnet(),
   327  			Gateway:     RouterNIC1IPv4Addr.AddressWithPrefix.Address,
   328  			NIC:         Host1NICID,
   329  		},
   330  		{
   331  			Destination: Host2IPv6Addr.AddressWithPrefix.Subnet(),
   332  			Gateway:     RouterNIC1IPv6Addr.AddressWithPrefix.Address,
   333  			NIC:         Host1NICID,
   334  		},
   335  	})
   336  	host2Stack.SetRouteTable([]tcpip.Route{
   337  		{
   338  			Destination: Host2IPv4Addr.AddressWithPrefix.Subnet(),
   339  			NIC:         Host2NICID,
   340  		},
   341  		{
   342  			Destination: Host2IPv6Addr.AddressWithPrefix.Subnet(),
   343  			NIC:         Host2NICID,
   344  		},
   345  		{
   346  			Destination: Host1IPv4Addr.AddressWithPrefix.Subnet(),
   347  			Gateway:     RouterNIC2IPv4Addr.AddressWithPrefix.Address,
   348  			NIC:         Host2NICID,
   349  		},
   350  		{
   351  			Destination: Host1IPv6Addr.AddressWithPrefix.Subnet(),
   352  			Gateway:     RouterNIC2IPv6Addr.AddressWithPrefix.Address,
   353  			NIC:         Host2NICID,
   354  		},
   355  	})
   356  }
   357  
   358  // ICMPv4Echo returns an ICMPv4 echo packet.
   359  func ICMPv4Echo(src, dst tcpip.Address, ttl uint8, ty header.ICMPv4Type) []byte {
   360  	totalLen := header.IPv4MinimumSize + header.ICMPv4MinimumSize
   361  	hdr := prependable.New(totalLen)
   362  	pkt := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize))
   363  	pkt.SetType(ty)
   364  	pkt.SetCode(header.ICMPv4UnusedCode)
   365  	pkt.SetChecksum(0)
   366  	pkt.SetChecksum(^checksum.Checksum(pkt, 0))
   367  	ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
   368  	ip.Encode(&header.IPv4Fields{
   369  		TotalLength: uint16(totalLen),
   370  		Protocol:    uint8(icmp.ProtocolNumber4),
   371  		TTL:         ttl,
   372  		SrcAddr:     src,
   373  		DstAddr:     dst,
   374  	})
   375  	ip.SetChecksum(^ip.CalculateChecksum())
   376  	return hdr.View()
   377  }
   378  
   379  // RxICMPv4EchoRequest constructs and injects an ICMPv4 echo request packet on
   380  // the provided endpoint.
   381  func RxICMPv4EchoRequest(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
   382  	newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   383  		Payload: buffer.MakeWithData(ICMPv4Echo(src, dst, ttl, header.ICMPv4Echo)),
   384  	})
   385  	defer newPkt.DecRef()
   386  	e.InjectInbound(header.IPv4ProtocolNumber, newPkt)
   387  }
   388  
   389  // RxICMPv4EchoReply constructs and injects an ICMPv4 echo reply packet on
   390  // the provided endpoint.
   391  func RxICMPv4EchoReply(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
   392  	newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   393  		Payload: buffer.MakeWithData(ICMPv4Echo(src, dst, ttl, header.ICMPv4EchoReply)),
   394  	})
   395  	defer newPkt.DecRef()
   396  	e.InjectInbound(header.IPv4ProtocolNumber, newPkt)
   397  }
   398  
   399  // ICMPv6Echo returns an ICMPv6 echo packet.
   400  func ICMPv6Echo(src, dst tcpip.Address, ttl uint8, ty header.ICMPv6Type) []byte {
   401  	totalLen := header.IPv6MinimumSize + header.ICMPv6MinimumSize
   402  	hdr := prependable.New(totalLen)
   403  	pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize))
   404  	pkt.SetType(ty)
   405  	pkt.SetCode(header.ICMPv6UnusedCode)
   406  	pkt.SetChecksum(0)
   407  	pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
   408  		Header: pkt,
   409  		Src:    src,
   410  		Dst:    dst,
   411  	}))
   412  	ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
   413  	ip.Encode(&header.IPv6Fields{
   414  		PayloadLength:     header.ICMPv6MinimumSize,
   415  		TransportProtocol: icmp.ProtocolNumber6,
   416  		HopLimit:          ttl,
   417  		SrcAddr:           src,
   418  		DstAddr:           dst,
   419  	})
   420  	return hdr.View()
   421  }
   422  
   423  // RxICMPv6EchoRequest constructs and injects an ICMPv6 echo request packet on
   424  // the provided endpoint.
   425  func RxICMPv6EchoRequest(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
   426  	newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   427  		Payload: buffer.MakeWithData(ICMPv6Echo(src, dst, ttl, header.ICMPv6EchoRequest)),
   428  	})
   429  	defer newPkt.DecRef()
   430  	e.InjectInbound(header.IPv6ProtocolNumber, newPkt)
   431  }
   432  
   433  // RxICMPv6EchoReply constructs and injects an ICMPv6 echo reply packet on
   434  // the provided endpoint.
   435  func RxICMPv6EchoReply(e *channel.Endpoint, src, dst tcpip.Address, ttl uint8) {
   436  	newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   437  		Payload: buffer.MakeWithData(ICMPv6Echo(src, dst, ttl, header.ICMPv6EchoReply)),
   438  	})
   439  	defer newPkt.DecRef()
   440  	e.InjectInbound(header.IPv6ProtocolNumber, newPkt)
   441  }