github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/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 "fmt" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 "github.com/google/go-cmp/cmp/cmpopts" 23 "github.com/SagerNet/gvisor/pkg/tcpip" 24 "github.com/SagerNet/gvisor/pkg/tcpip/buffer" 25 "github.com/SagerNet/gvisor/pkg/tcpip/faketime" 26 "github.com/SagerNet/gvisor/pkg/tcpip/header" 27 "github.com/SagerNet/gvisor/pkg/tcpip/link/channel" 28 "github.com/SagerNet/gvisor/pkg/tcpip/link/sniffer" 29 "github.com/SagerNet/gvisor/pkg/tcpip/network/arp" 30 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4" 31 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 32 "github.com/SagerNet/gvisor/pkg/tcpip/testutil" 33 ) 34 35 const ( 36 nicID = 1 37 38 stackLinkAddr = tcpip.LinkAddress("\x0a\x0a\x0b\x0b\x0c\x0c") 39 remoteLinkAddr = tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06") 40 ) 41 42 var ( 43 stackAddr = testutil.MustParse4("10.0.0.1") 44 remoteAddr = testutil.MustParse4("10.0.0.2") 45 unknownAddr = testutil.MustParse4("10.0.0.3") 46 ) 47 48 type eventType uint8 49 50 const ( 51 entryAdded eventType = iota 52 entryChanged 53 entryRemoved 54 ) 55 56 func (t eventType) String() string { 57 switch t { 58 case entryAdded: 59 return "add" 60 case entryChanged: 61 return "change" 62 case entryRemoved: 63 return "remove" 64 default: 65 return fmt.Sprintf("unknown (%d)", t) 66 } 67 } 68 69 type eventInfo struct { 70 eventType eventType 71 nicID tcpip.NICID 72 entry stack.NeighborEntry 73 } 74 75 func (e eventInfo) String() string { 76 return fmt.Sprintf("%s event for NIC #%d, %#v", e.eventType, e.nicID, e.entry) 77 } 78 79 // arpDispatcher implements NUDDispatcher to validate the dispatching of 80 // events upon certain NUD state machine events. 81 type arpDispatcher struct { 82 // C is where events are queued 83 C chan eventInfo 84 } 85 86 var _ stack.NUDDispatcher = (*arpDispatcher)(nil) 87 88 func (d *arpDispatcher) OnNeighborAdded(nicID tcpip.NICID, entry stack.NeighborEntry) { 89 e := eventInfo{ 90 eventType: entryAdded, 91 nicID: nicID, 92 entry: entry, 93 } 94 d.C <- e 95 } 96 97 func (d *arpDispatcher) OnNeighborChanged(nicID tcpip.NICID, entry stack.NeighborEntry) { 98 e := eventInfo{ 99 eventType: entryChanged, 100 nicID: nicID, 101 entry: entry, 102 } 103 d.C <- e 104 } 105 106 func (d *arpDispatcher) OnNeighborRemoved(nicID tcpip.NICID, entry stack.NeighborEntry) { 107 e := eventInfo{ 108 eventType: entryRemoved, 109 nicID: nicID, 110 entry: entry, 111 } 112 d.C <- e 113 } 114 115 func (d *arpDispatcher) nextEvent() (eventInfo, bool) { 116 select { 117 case event := <-d.C: 118 return event, true 119 default: 120 return eventInfo{}, false 121 } 122 } 123 124 type testContext struct { 125 s *stack.Stack 126 linkEP *channel.Endpoint 127 nudDisp arpDispatcher 128 } 129 130 func makeTestContext(t *testing.T, eventDepth int, packetDepth int) testContext { 131 t.Helper() 132 133 tc := testContext{ 134 nudDisp: arpDispatcher{ 135 C: make(chan eventInfo, eventDepth), 136 }, 137 } 138 139 tc.s = stack.New(stack.Options{ 140 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, arp.NewProtocol}, 141 NUDDisp: &tc.nudDisp, 142 Clock: &faketime.NullClock{}, 143 }) 144 145 tc.linkEP = channel.New(packetDepth, header.IPv4MinimumMTU, stackLinkAddr) 146 tc.linkEP.LinkEPCapabilities |= stack.CapabilityResolutionRequired 147 148 wep := stack.LinkEndpoint(tc.linkEP) 149 if testing.Verbose() { 150 wep = sniffer.New(wep) 151 } 152 if err := tc.s.CreateNIC(nicID, wep); err != nil { 153 t.Fatalf("CreateNIC failed: %s", err) 154 } 155 156 if err := tc.s.AddAddress(nicID, ipv4.ProtocolNumber, stackAddr); err != nil { 157 t.Fatalf("AddAddress for ipv4 failed: %s", err) 158 } 159 160 tc.s.SetRouteTable([]tcpip.Route{{ 161 Destination: header.IPv4EmptySubnet, 162 NIC: nicID, 163 }}) 164 165 return tc 166 } 167 168 func (c *testContext) cleanup() { 169 c.linkEP.Close() 170 } 171 172 func TestMalformedPacket(t *testing.T) { 173 c := makeTestContext(t, 0, 0) 174 defer c.cleanup() 175 176 v := make(buffer.View, header.ARPSize) 177 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 178 Data: v.ToVectorisedView(), 179 }) 180 181 c.linkEP.InjectInbound(arp.ProtocolNumber, pkt) 182 183 if got := c.s.Stats().ARP.PacketsReceived.Value(); got != 1 { 184 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = 1", got) 185 } 186 if got := c.s.Stats().ARP.MalformedPacketsReceived.Value(); got != 1 { 187 t.Errorf("got c.s.Stats().ARP.MalformedPacketsReceived.Value() = %d, want = 1", got) 188 } 189 } 190 191 func TestDisabledEndpoint(t *testing.T) { 192 c := makeTestContext(t, 0, 0) 193 defer c.cleanup() 194 195 ep, err := c.s.GetNetworkEndpoint(nicID, header.ARPProtocolNumber) 196 if err != nil { 197 t.Fatalf("GetNetworkEndpoint(%d, header.ARPProtocolNumber) failed: %s", nicID, err) 198 } 199 ep.Disable() 200 201 v := make(buffer.View, header.ARPSize) 202 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 203 Data: v.ToVectorisedView(), 204 }) 205 206 c.linkEP.InjectInbound(arp.ProtocolNumber, pkt) 207 208 if got := c.s.Stats().ARP.PacketsReceived.Value(); got != 1 { 209 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = 1", got) 210 } 211 if got := c.s.Stats().ARP.DisabledPacketsReceived.Value(); got != 1 { 212 t.Errorf("got c.s.Stats().ARP.DisabledPacketsReceived.Value() = %d, want = 1", got) 213 } 214 } 215 216 func TestDirectReply(t *testing.T) { 217 c := makeTestContext(t, 0, 0) 218 defer c.cleanup() 219 220 const senderMAC = "\x01\x02\x03\x04\x05\x06" 221 const senderIPv4 = "\x0a\x00\x00\x02" 222 223 v := make(buffer.View, header.ARPSize) 224 h := header.ARP(v) 225 h.SetIPv4OverEthernet() 226 h.SetOp(header.ARPReply) 227 228 copy(h.HardwareAddressSender(), senderMAC) 229 copy(h.ProtocolAddressSender(), senderIPv4) 230 copy(h.HardwareAddressTarget(), stackLinkAddr) 231 copy(h.ProtocolAddressTarget(), stackAddr) 232 233 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 234 Data: v.ToVectorisedView(), 235 }) 236 237 c.linkEP.InjectInbound(arp.ProtocolNumber, pkt) 238 239 if got := c.s.Stats().ARP.PacketsReceived.Value(); got != 1 { 240 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = 1", got) 241 } 242 if got := c.s.Stats().ARP.RepliesReceived.Value(); got != 1 { 243 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = 1", got) 244 } 245 } 246 247 func TestDirectRequest(t *testing.T) { 248 c := makeTestContext(t, 1, 1) 249 defer c.cleanup() 250 251 tests := []struct { 252 name string 253 senderAddr tcpip.Address 254 senderLinkAddr tcpip.LinkAddress 255 targetAddr tcpip.Address 256 isValid bool 257 }{ 258 { 259 name: "Loopback", 260 senderAddr: stackAddr, 261 senderLinkAddr: stackLinkAddr, 262 targetAddr: stackAddr, 263 isValid: true, 264 }, 265 { 266 name: "Remote", 267 senderAddr: remoteAddr, 268 senderLinkAddr: remoteLinkAddr, 269 targetAddr: stackAddr, 270 isValid: true, 271 }, 272 { 273 name: "RemoteInvalidTarget", 274 senderAddr: remoteAddr, 275 senderLinkAddr: remoteLinkAddr, 276 targetAddr: unknownAddr, 277 isValid: false, 278 }, 279 } 280 281 for _, test := range tests { 282 t.Run(test.name, func(t *testing.T) { 283 packetsRecv := c.s.Stats().ARP.PacketsReceived.Value() 284 requestsRecv := c.s.Stats().ARP.RequestsReceived.Value() 285 requestsRecvUnknownAddr := c.s.Stats().ARP.RequestsReceivedUnknownTargetAddress.Value() 286 outgoingReplies := c.s.Stats().ARP.OutgoingRepliesSent.Value() 287 288 // Inject an incoming ARP request. 289 v := make(buffer.View, header.ARPSize) 290 h := header.ARP(v) 291 h.SetIPv4OverEthernet() 292 h.SetOp(header.ARPRequest) 293 copy(h.HardwareAddressSender(), test.senderLinkAddr) 294 copy(h.ProtocolAddressSender(), test.senderAddr) 295 copy(h.ProtocolAddressTarget(), test.targetAddr) 296 c.linkEP.InjectInbound(arp.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{ 297 Data: v.ToVectorisedView(), 298 })) 299 300 if got, want := c.s.Stats().ARP.PacketsReceived.Value(), packetsRecv+1; got != want { 301 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = %d", got, want) 302 } 303 if got, want := c.s.Stats().ARP.RequestsReceived.Value(), requestsRecv+1; got != want { 304 t.Errorf("got c.s.Stats().ARP.PacketsReceived.Value() = %d, want = %d", got, want) 305 } 306 307 if !test.isValid { 308 // No packets should be sent after receiving an invalid ARP request. 309 // There is no need to perform a blocking read here, since packets are 310 // sent in the same function that handles ARP requests. 311 if pkt, ok := c.linkEP.Read(); ok { 312 t.Errorf("unexpected packet sent with network protocol number %d", pkt.Proto) 313 } 314 if got, want := c.s.Stats().ARP.RequestsReceivedUnknownTargetAddress.Value(), requestsRecvUnknownAddr+1; got != want { 315 t.Errorf("got c.s.Stats().ARP.RequestsReceivedUnknownTargetAddress.Value() = %d, want = %d", got, want) 316 } 317 if got, want := c.s.Stats().ARP.OutgoingRepliesSent.Value(), outgoingReplies; got != want { 318 t.Errorf("got c.s.Stats().ARP.OutgoingRepliesSent.Value() = %d, want = %d", got, want) 319 } 320 321 return 322 } 323 324 if got, want := c.s.Stats().ARP.OutgoingRepliesSent.Value(), outgoingReplies+1; got != want { 325 t.Errorf("got c.s.Stats().ARP.OutgoingRepliesSent.Value() = %d, want = %d", got, want) 326 } 327 328 // Verify an ARP response was sent. 329 pi, ok := c.linkEP.Read() 330 if !ok { 331 t.Fatal("expected ARP response to be sent, got none") 332 } 333 334 if pi.Proto != arp.ProtocolNumber { 335 t.Fatalf("expected ARP response, got network protocol number %d", pi.Proto) 336 } 337 rep := header.ARP(pi.Pkt.NetworkHeader().View()) 338 if !rep.IsValid() { 339 t.Fatalf("invalid ARP response: len = %d; response = %x", len(rep), rep) 340 } 341 if got, want := tcpip.LinkAddress(rep.HardwareAddressSender()), stackLinkAddr; got != want { 342 t.Errorf("got HardwareAddressSender() = %s, want = %s", got, want) 343 } 344 if got, want := tcpip.Address(rep.ProtocolAddressSender()), tcpip.Address(h.ProtocolAddressTarget()); got != want { 345 t.Errorf("got ProtocolAddressSender() = %s, want = %s", got, want) 346 } 347 if got, want := tcpip.LinkAddress(rep.HardwareAddressTarget()), tcpip.LinkAddress(h.HardwareAddressSender()); got != want { 348 t.Errorf("got HardwareAddressTarget() = %s, want = %s", got, want) 349 } 350 if got, want := tcpip.Address(rep.ProtocolAddressTarget()), tcpip.Address(h.ProtocolAddressSender()); got != want { 351 t.Errorf("got ProtocolAddressTarget() = %s, want = %s", got, want) 352 } 353 354 // Verify the sender was saved in the neighbor cache. 355 if got, ok := c.nudDisp.nextEvent(); ok { 356 want := eventInfo{ 357 eventType: entryAdded, 358 nicID: nicID, 359 entry: stack.NeighborEntry{ 360 Addr: test.senderAddr, 361 LinkAddr: test.senderLinkAddr, 362 State: stack.Stale, 363 }, 364 } 365 if diff := cmp.Diff(want, got, cmp.AllowUnexported(eventInfo{}), cmpopts.IgnoreFields(stack.NeighborEntry{}, "UpdatedAt")); diff != "" { 366 t.Errorf("got invalid event (-want +got):\n%s", diff) 367 } 368 } else { 369 t.Fatal("event didn't arrive") 370 } 371 372 neighbors, err := c.s.Neighbors(nicID, ipv4.ProtocolNumber) 373 if err != nil { 374 t.Fatalf("c.s.Neighbors(%d, %d): %s", nicID, ipv4.ProtocolNumber, err) 375 } 376 377 neighborByAddr := make(map[tcpip.Address]stack.NeighborEntry) 378 for _, n := range neighbors { 379 if existing, ok := neighborByAddr[n.Addr]; ok { 380 if diff := cmp.Diff(existing, n); diff != "" { 381 t.Fatalf("duplicate neighbor entry found (-existing +got):\n%s", diff) 382 } 383 t.Fatalf("exact neighbor entry duplicate found for addr=%s", n.Addr) 384 } 385 neighborByAddr[n.Addr] = n 386 } 387 388 neigh, ok := neighborByAddr[test.senderAddr] 389 if !ok { 390 t.Fatalf("expected neighbor entry with Addr = %s", test.senderAddr) 391 } 392 if got, want := neigh.LinkAddr, test.senderLinkAddr; got != want { 393 t.Errorf("got neighbor LinkAddr = %s, want = %s", got, want) 394 } 395 if got, want := neigh.State, stack.Stale; got != want { 396 t.Errorf("got neighbor State = %s, want = %s", got, want) 397 } 398 399 // No more events should be dispatched 400 for { 401 event, ok := c.nudDisp.nextEvent() 402 if !ok { 403 break 404 } 405 t.Errorf("unexpected %s", event) 406 } 407 }) 408 } 409 } 410 411 var _ stack.LinkEndpoint = (*testLinkEndpoint)(nil) 412 413 type testLinkEndpoint struct { 414 stack.LinkEndpoint 415 416 writeErr tcpip.Error 417 } 418 419 func (t *testLinkEndpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error { 420 if t.writeErr != nil { 421 return t.writeErr 422 } 423 424 return t.LinkEndpoint.WritePacket(r, protocol, pkt) 425 } 426 427 func TestLinkAddressRequest(t *testing.T) { 428 const nicID = 1 429 430 testAddr := tcpip.Address([]byte{1, 2, 3, 4}) 431 432 tests := []struct { 433 name string 434 nicAddr tcpip.Address 435 localAddr tcpip.Address 436 remoteLinkAddr tcpip.LinkAddress 437 linkErr tcpip.Error 438 expectedErr tcpip.Error 439 expectedLocalAddr tcpip.Address 440 expectedRemoteLinkAddr tcpip.LinkAddress 441 expectedRequestsSent uint64 442 expectedRequestBadLocalAddressErrors uint64 443 expectedRequestInterfaceHasNoLocalAddressErrors uint64 444 expectedRequestDroppedErrors uint64 445 }{ 446 { 447 name: "Unicast", 448 nicAddr: stackAddr, 449 localAddr: stackAddr, 450 remoteLinkAddr: remoteLinkAddr, 451 expectedLocalAddr: stackAddr, 452 expectedRemoteLinkAddr: remoteLinkAddr, 453 expectedRequestsSent: 1, 454 expectedRequestBadLocalAddressErrors: 0, 455 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 456 expectedRequestDroppedErrors: 0, 457 }, 458 { 459 name: "Multicast", 460 nicAddr: stackAddr, 461 localAddr: stackAddr, 462 remoteLinkAddr: "", 463 expectedLocalAddr: stackAddr, 464 expectedRemoteLinkAddr: header.EthernetBroadcastAddress, 465 expectedRequestsSent: 1, 466 expectedRequestBadLocalAddressErrors: 0, 467 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 468 expectedRequestDroppedErrors: 0, 469 }, 470 { 471 name: "Unicast with unspecified source", 472 nicAddr: stackAddr, 473 localAddr: "", 474 remoteLinkAddr: remoteLinkAddr, 475 expectedLocalAddr: stackAddr, 476 expectedRemoteLinkAddr: remoteLinkAddr, 477 expectedRequestsSent: 1, 478 expectedRequestBadLocalAddressErrors: 0, 479 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 480 expectedRequestDroppedErrors: 0, 481 }, 482 { 483 name: "Multicast with unspecified source", 484 nicAddr: stackAddr, 485 localAddr: "", 486 remoteLinkAddr: "", 487 expectedLocalAddr: stackAddr, 488 expectedRemoteLinkAddr: header.EthernetBroadcastAddress, 489 expectedRequestsSent: 1, 490 expectedRequestBadLocalAddressErrors: 0, 491 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 492 expectedRequestDroppedErrors: 0, 493 }, 494 { 495 name: "Unicast with unassigned address", 496 nicAddr: stackAddr, 497 localAddr: testAddr, 498 remoteLinkAddr: remoteLinkAddr, 499 expectedErr: &tcpip.ErrBadLocalAddress{}, 500 expectedRequestsSent: 0, 501 expectedRequestBadLocalAddressErrors: 1, 502 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 503 expectedRequestDroppedErrors: 0, 504 }, 505 { 506 name: "Multicast with unassigned address", 507 nicAddr: stackAddr, 508 localAddr: testAddr, 509 remoteLinkAddr: "", 510 expectedErr: &tcpip.ErrBadLocalAddress{}, 511 expectedRequestsSent: 0, 512 expectedRequestBadLocalAddressErrors: 1, 513 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 514 expectedRequestDroppedErrors: 0, 515 }, 516 { 517 name: "Unicast with no local address available", 518 nicAddr: "", 519 localAddr: "", 520 remoteLinkAddr: remoteLinkAddr, 521 expectedErr: &tcpip.ErrNetworkUnreachable{}, 522 expectedRequestsSent: 0, 523 expectedRequestBadLocalAddressErrors: 0, 524 expectedRequestInterfaceHasNoLocalAddressErrors: 1, 525 expectedRequestDroppedErrors: 0, 526 }, 527 { 528 name: "Multicast with no local address available", 529 nicAddr: "", 530 localAddr: "", 531 remoteLinkAddr: "", 532 expectedErr: &tcpip.ErrNetworkUnreachable{}, 533 expectedRequestsSent: 0, 534 expectedRequestBadLocalAddressErrors: 0, 535 expectedRequestInterfaceHasNoLocalAddressErrors: 1, 536 expectedRequestDroppedErrors: 0, 537 }, 538 { 539 name: "Link error", 540 nicAddr: stackAddr, 541 localAddr: stackAddr, 542 remoteLinkAddr: remoteLinkAddr, 543 linkErr: &tcpip.ErrInvalidEndpointState{}, 544 expectedErr: &tcpip.ErrInvalidEndpointState{}, 545 expectedRequestsSent: 0, 546 expectedRequestBadLocalAddressErrors: 0, 547 expectedRequestInterfaceHasNoLocalAddressErrors: 0, 548 expectedRequestDroppedErrors: 1, 549 }, 550 } 551 552 for _, test := range tests { 553 t.Run(test.name, func(t *testing.T) { 554 s := stack.New(stack.Options{ 555 NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocol, ipv4.NewProtocol}, 556 }) 557 linkEP := channel.New(1, header.IPv4MinimumMTU, stackLinkAddr) 558 if err := s.CreateNIC(nicID, &testLinkEndpoint{LinkEndpoint: linkEP, writeErr: test.linkErr}); err != nil { 559 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 560 } 561 562 ep, err := s.GetNetworkEndpoint(nicID, arp.ProtocolNumber) 563 if err != nil { 564 t.Fatalf("s.GetNetworkEndpoint(%d, %d): %s", nicID, arp.ProtocolNumber, err) 565 } 566 linkRes, ok := ep.(stack.LinkAddressResolver) 567 if !ok { 568 t.Fatalf("expected %T to implement stack.LinkAddressResolver", ep) 569 } 570 571 if len(test.nicAddr) != 0 { 572 if err := s.AddAddress(nicID, ipv4.ProtocolNumber, test.nicAddr); err != nil { 573 t.Fatalf("s.AddAddress(%d, %d, %s): %s", nicID, ipv4.ProtocolNumber, test.nicAddr, err) 574 } 575 } 576 577 { 578 err := linkRes.LinkAddressRequest(remoteAddr, test.localAddr, test.remoteLinkAddr) 579 if diff := cmp.Diff(test.expectedErr, err); diff != "" { 580 t.Fatalf("unexpected error from p.LinkAddressRequest(%s, %s, %s, _), (-want, +got):\n%s", remoteAddr, test.localAddr, test.remoteLinkAddr, diff) 581 } 582 } 583 584 if got := s.Stats().ARP.OutgoingRequestsSent.Value(); got != test.expectedRequestsSent { 585 t.Errorf("got s.Stats().ARP.OutgoingRequestsSent.Value() = %d, want = %d", got, test.expectedRequestsSent) 586 } 587 if got := s.Stats().ARP.OutgoingRequestInterfaceHasNoLocalAddressErrors.Value(); got != test.expectedRequestInterfaceHasNoLocalAddressErrors { 588 t.Errorf("got s.Stats().ARP.OutgoingRequestInterfaceHasNoLocalAddressErrors.Value() = %d, want = %d", got, test.expectedRequestInterfaceHasNoLocalAddressErrors) 589 } 590 if got := s.Stats().ARP.OutgoingRequestBadLocalAddressErrors.Value(); got != test.expectedRequestBadLocalAddressErrors { 591 t.Errorf("got s.Stats().ARP.OutgoingRequestBadLocalAddressErrors.Value() = %d, want = %d", got, test.expectedRequestBadLocalAddressErrors) 592 } 593 if got := s.Stats().ARP.OutgoingRequestsDropped.Value(); got != test.expectedRequestDroppedErrors { 594 t.Errorf("got s.Stats().ARP.OutgoingRequestsDropped.Value() = %d, want = %d", got, test.expectedRequestDroppedErrors) 595 } 596 597 if test.expectedErr != nil { 598 return 599 } 600 601 pkt, ok := linkEP.Read() 602 if !ok { 603 t.Fatal("expected to send a link address request") 604 } 605 606 if pkt.Route.RemoteLinkAddress != test.expectedRemoteLinkAddr { 607 t.Errorf("got pkt.Route.RemoteLinkAddress = %s, want = %s", pkt.Route.RemoteLinkAddress, test.expectedRemoteLinkAddr) 608 } 609 610 rep := header.ARP(stack.PayloadSince(pkt.Pkt.NetworkHeader())) 611 if got := rep.Op(); got != header.ARPRequest { 612 t.Errorf("got Op = %d, want = %d", got, header.ARPRequest) 613 } 614 if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr { 615 t.Errorf("got HardwareAddressSender = %s, want = %s", got, stackLinkAddr) 616 } 617 if got := tcpip.Address(rep.ProtocolAddressSender()); got != test.expectedLocalAddr { 618 t.Errorf("got ProtocolAddressSender = %s, want = %s", got, test.expectedLocalAddr) 619 } 620 if got, want := tcpip.LinkAddress(rep.HardwareAddressTarget()), tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00"); got != want { 621 t.Errorf("got HardwareAddressTarget = %s, want = %s", got, want) 622 } 623 if got := tcpip.Address(rep.ProtocolAddressTarget()); got != remoteAddr { 624 t.Errorf("got ProtocolAddressTarget = %s, want = %s", got, remoteAddr) 625 } 626 }) 627 } 628 } 629 630 func TestDADARPRequestPacket(t *testing.T) { 631 clock := faketime.NewManualClock() 632 s := stack.New(stack.Options{ 633 NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocolWithOptions(arp.Options{ 634 DADConfigs: stack.DADConfigurations{ 635 DupAddrDetectTransmits: 1, 636 }, 637 }), ipv4.NewProtocol}, 638 Clock: clock, 639 }) 640 e := channel.New(1, header.IPv4MinimumMTU, stackLinkAddr) 641 if err := s.CreateNIC(nicID, e); err != nil { 642 t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err) 643 } 644 645 if res, err := s.CheckDuplicateAddress(nicID, header.IPv4ProtocolNumber, remoteAddr, func(stack.DADResult) {}); err != nil { 646 t.Fatalf("s.CheckDuplicateAddress(%d, %d, %s, _): %s", nicID, header.IPv4ProtocolNumber, remoteAddr, err) 647 } else if res != stack.DADStarting { 648 t.Fatalf("got s.CheckDuplicateAddress(%d, %d, %s, _) = %d, want = %d", nicID, header.IPv4ProtocolNumber, remoteAddr, res, stack.DADStarting) 649 } 650 651 clock.RunImmediatelyScheduledJobs() 652 pkt, ok := e.Read() 653 if !ok { 654 t.Fatal("expected to send an ARP request") 655 } 656 657 if pkt.Route.RemoteLinkAddress != header.EthernetBroadcastAddress { 658 t.Errorf("got pkt.Route.RemoteLinkAddress = %s, want = %s", pkt.Route.RemoteLinkAddress, header.EthernetBroadcastAddress) 659 } 660 661 req := header.ARP(stack.PayloadSince(pkt.Pkt.NetworkHeader())) 662 if !req.IsValid() { 663 t.Errorf("got req.IsValid() = false, want = true") 664 } 665 if got := req.Op(); got != header.ARPRequest { 666 t.Errorf("got req.Op() = %d, want = %d", got, header.ARPRequest) 667 } 668 if got := tcpip.LinkAddress(req.HardwareAddressSender()); got != stackLinkAddr { 669 t.Errorf("got req.HardwareAddressSender() = %s, want = %s", got, stackLinkAddr) 670 } 671 if got := tcpip.Address(req.ProtocolAddressSender()); got != header.IPv4Any { 672 t.Errorf("got req.ProtocolAddressSender() = %s, want = %s", got, header.IPv4Any) 673 } 674 if got, want := tcpip.LinkAddress(req.HardwareAddressTarget()), tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00"); got != want { 675 t.Errorf("got req.HardwareAddressTarget() = %s, want = %s", got, want) 676 } 677 if got := tcpip.Address(req.ProtocolAddressTarget()); got != remoteAddr { 678 t.Errorf("got req.ProtocolAddressTarget() = %s, want = %s", got, remoteAddr) 679 } 680 }