github.com/lightlus/netstack@v1.2.0/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/lightlus/netstack/tcpip" 23 "github.com/lightlus/netstack/tcpip/buffer" 24 "github.com/lightlus/netstack/tcpip/header" 25 "github.com/lightlus/netstack/tcpip/link/channel" 26 "github.com/lightlus/netstack/tcpip/link/sniffer" 27 "github.com/lightlus/netstack/tcpip/network/arp" 28 "github.com/lightlus/netstack/tcpip/network/ipv4" 29 "github.com/lightlus/netstack/tcpip/stack" 30 "github.com/lightlus/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 }