github.com/polevpn/netstack@v1.10.9/tcpip/network/arp/arp_test.go (about)

     1  // Copyright 2018 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 arp_test
    16  
    17  import (
    18  	"strconv"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/polevpn/netstack/tcpip"
    23  	"github.com/polevpn/netstack/tcpip/buffer"
    24  	"github.com/polevpn/netstack/tcpip/header"
    25  	"github.com/polevpn/netstack/tcpip/link/channel"
    26  	"github.com/polevpn/netstack/tcpip/link/sniffer"
    27  	"github.com/polevpn/netstack/tcpip/network/arp"
    28  	"github.com/polevpn/netstack/tcpip/network/ipv4"
    29  	"github.com/polevpn/netstack/tcpip/stack"
    30  	"github.com/polevpn/netstack/tcpip/transport/icmp"
    31  )
    32  
    33  const (
    34  	stackLinkAddr = tcpip.LinkAddress("\x0a\x0a\x0b\x0b\x0c\x0c")
    35  	stackAddr1    = tcpip.Address("\x0a\x00\x00\x01")
    36  	stackAddr2    = tcpip.Address("\x0a\x00\x00\x02")
    37  	stackAddrBad  = tcpip.Address("\x0a\x00\x00\x03")
    38  )
    39  
    40  type testContext struct {
    41  	t      *testing.T
    42  	linkEP *channel.Endpoint
    43  	s      *stack.Stack
    44  }
    45  
    46  func newTestContext(t *testing.T) *testContext {
    47  	s := stack.New(stack.Options{
    48  		NetworkProtocols:   []stack.NetworkProtocol{ipv4.NewProtocol(), arp.NewProtocol()},
    49  		TransportProtocols: []stack.TransportProtocol{icmp.NewProtocol4()},
    50  	})
    51  
    52  	const defaultMTU = 65536
    53  	ep := channel.New(256, defaultMTU, stackLinkAddr)
    54  	wep := stack.LinkEndpoint(ep)
    55  
    56  	if testing.Verbose() {
    57  		wep = sniffer.New(ep)
    58  	}
    59  	if err := s.CreateNIC(1, wep); err != nil {
    60  		t.Fatalf("CreateNIC failed: %v", err)
    61  	}
    62  
    63  	if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr1); err != nil {
    64  		t.Fatalf("AddAddress for ipv4 failed: %v", err)
    65  	}
    66  	if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr2); err != nil {
    67  		t.Fatalf("AddAddress for ipv4 failed: %v", err)
    68  	}
    69  	if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
    70  		t.Fatalf("AddAddress for arp failed: %v", err)
    71  	}
    72  
    73  	s.SetRouteTable([]tcpip.Route{{
    74  		Destination: header.IPv4EmptySubnet,
    75  		NIC:         1,
    76  	}})
    77  
    78  	return &testContext{
    79  		t:      t,
    80  		s:      s,
    81  		linkEP: ep,
    82  	}
    83  }
    84  
    85  func (c *testContext) cleanup() {
    86  	close(c.linkEP.C)
    87  }
    88  
    89  func TestDirectRequest(t *testing.T) {
    90  	c := newTestContext(t)
    91  	defer c.cleanup()
    92  
    93  	const senderMAC = "\x01\x02\x03\x04\x05\x06"
    94  	const senderIPv4 = "\x0a\x00\x00\x02"
    95  
    96  	v := make(buffer.View, header.ARPSize)
    97  	h := header.ARP(v)
    98  	h.SetIPv4OverEthernet()
    99  	h.SetOp(header.ARPRequest)
   100  	copy(h.HardwareAddressSender(), senderMAC)
   101  	copy(h.ProtocolAddressSender(), senderIPv4)
   102  
   103  	inject := func(addr tcpip.Address) {
   104  		copy(h.ProtocolAddressTarget(), addr)
   105  		c.linkEP.InjectInbound(arp.ProtocolNumber, tcpip.PacketBuffer{
   106  			Data: v.ToVectorisedView(),
   107  		})
   108  	}
   109  
   110  	for i, address := range []tcpip.Address{stackAddr1, stackAddr2} {
   111  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   112  			inject(address)
   113  			pi := <-c.linkEP.C
   114  			if pi.Proto != arp.ProtocolNumber {
   115  				t.Fatalf("expected ARP response, got network protocol number %d", pi.Proto)
   116  			}
   117  			rep := header.ARP(pi.Pkt.Header.View())
   118  			if !rep.IsValid() {
   119  				t.Fatalf("invalid ARP response pi.Pkt.Header.UsedLength()=%d", pi.Pkt.Header.UsedLength())
   120  			}
   121  			if got, want := tcpip.LinkAddress(rep.HardwareAddressSender()), stackLinkAddr; got != want {
   122  				t.Errorf("got HardwareAddressSender = %s, want = %s", got, want)
   123  			}
   124  			if got, want := tcpip.Address(rep.ProtocolAddressSender()), tcpip.Address(h.ProtocolAddressTarget()); got != want {
   125  				t.Errorf("got ProtocolAddressSender = %s, want = %s", got, want)
   126  			}
   127  			if got, want := tcpip.LinkAddress(rep.HardwareAddressTarget()), tcpip.LinkAddress(h.HardwareAddressSender()); got != want {
   128  				t.Errorf("got HardwareAddressTarget = %s, want = %s", got, want)
   129  			}
   130  			if got, want := tcpip.Address(rep.ProtocolAddressTarget()), tcpip.Address(h.ProtocolAddressSender()); got != want {
   131  				t.Errorf("got ProtocolAddressTarget = %s, want = %s", got, want)
   132  			}
   133  		})
   134  	}
   135  
   136  	inject(stackAddrBad)
   137  	select {
   138  	case pkt := <-c.linkEP.C:
   139  		t.Errorf("stackAddrBad: unexpected packet sent, Proto=%v", pkt.Proto)
   140  	case <-time.After(100 * time.Millisecond):
   141  		// Sleep tests are gross, but this will only potentially flake
   142  		// if there's a bug. If there is no bug this will reliably
   143  		// succeed.
   144  	}
   145  }