github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/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/FlowerWrong/netstack/tcpip" 23 "github.com/FlowerWrong/netstack/tcpip/buffer" 24 "github.com/FlowerWrong/netstack/tcpip/header" 25 "github.com/FlowerWrong/netstack/tcpip/link/channel" 26 "github.com/FlowerWrong/netstack/tcpip/link/sniffer" 27 "github.com/FlowerWrong/netstack/tcpip/network/arp" 28 "github.com/FlowerWrong/netstack/tcpip/network/ipv4" 29 "github.com/FlowerWrong/netstack/tcpip/stack" 30 "github.com/FlowerWrong/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.Inject(arp.ProtocolNumber, v.ToVectorisedView()) 106 } 107 108 for i, address := range []tcpip.Address{stackAddr1, stackAddr2} { 109 t.Run(strconv.Itoa(i), func(t *testing.T) { 110 inject(address) 111 pkt := <-c.linkEP.C 112 if pkt.Proto != arp.ProtocolNumber { 113 t.Fatalf("expected ARP response, got network protocol number %d", pkt.Proto) 114 } 115 rep := header.ARP(pkt.Header) 116 if !rep.IsValid() { 117 t.Fatalf("invalid ARP response len(pkt.Header)=%d", len(pkt.Header)) 118 } 119 if got, want := tcpip.LinkAddress(rep.HardwareAddressSender()), stackLinkAddr; got != want { 120 t.Errorf("got HardwareAddressSender = %s, want = %s", got, want) 121 } 122 if got, want := tcpip.Address(rep.ProtocolAddressSender()), tcpip.Address(h.ProtocolAddressTarget()); got != want { 123 t.Errorf("got ProtocolAddressSender = %s, want = %s", got, want) 124 } 125 if got, want := tcpip.LinkAddress(rep.HardwareAddressTarget()), tcpip.LinkAddress(h.HardwareAddressSender()); got != want { 126 t.Errorf("got HardwareAddressTarget = %s, want = %s", got, want) 127 } 128 if got, want := tcpip.Address(rep.ProtocolAddressTarget()), tcpip.Address(h.ProtocolAddressSender()); got != want { 129 t.Errorf("got ProtocolAddressTarget = %s, want = %s", got, want) 130 } 131 }) 132 } 133 134 inject(stackAddrBad) 135 select { 136 case pkt := <-c.linkEP.C: 137 t.Errorf("stackAddrBad: unexpected packet sent, Proto=%v", pkt.Proto) 138 case <-time.After(100 * time.Millisecond): 139 // Sleep tests are gross, but this will only potentially flake 140 // if there's a bug. If there is no bug this will reliably 141 // succeed. 142 } 143 }