github.com/vpnishe/netstack@v1.10.6/tcpip/stack/ndp_test.go (about) 1 // Copyright 2019 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 stack_test 16 17 import ( 18 "encoding/binary" 19 "fmt" 20 "testing" 21 "time" 22 23 "github.com/google/go-cmp/cmp" 24 "github.com/vpnishe/netstack/tcpip" 25 "github.com/vpnishe/netstack/tcpip/buffer" 26 "github.com/vpnishe/netstack/tcpip/checker" 27 "github.com/vpnishe/netstack/tcpip/header" 28 "github.com/vpnishe/netstack/tcpip/link/channel" 29 "github.com/vpnishe/netstack/tcpip/network/ipv6" 30 "github.com/vpnishe/netstack/tcpip/stack" 31 "github.com/vpnishe/netstack/tcpip/transport/icmp" 32 ) 33 34 const ( 35 addr1 = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" 36 addr2 = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02" 37 addr3 = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03" 38 linkAddr1 = "\x02\x02\x03\x04\x05\x06" 39 linkAddr2 = "\x02\x02\x03\x04\x05\x07" 40 linkAddr3 = "\x02\x02\x03\x04\x05\x08" 41 defaultTimeout = 250 * time.Millisecond 42 ) 43 44 var ( 45 llAddr1 = header.LinkLocalAddr(linkAddr1) 46 llAddr2 = header.LinkLocalAddr(linkAddr2) 47 llAddr3 = header.LinkLocalAddr(linkAddr3) 48 ) 49 50 // TestDADDisabled tests that an address successfully resolves immediately 51 // when DAD is not enabled (the default for an empty stack.Options). 52 func TestDADDisabled(t *testing.T) { 53 opts := stack.Options{ 54 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 55 } 56 57 e := channel.New(10, 1280, linkAddr1) 58 s := stack.New(opts) 59 if err := s.CreateNIC(1, e); err != nil { 60 t.Fatalf("CreateNIC(_) = %s", err) 61 } 62 63 if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { 64 t.Fatalf("AddAddress(_, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) 65 } 66 67 // Should get the address immediately since we should not have performed 68 // DAD on it. 69 addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 70 if err != nil { 71 t.Fatalf("stack.GetMainNICAddress(_, _) err = %s", err) 72 } 73 if addr.Address != addr1 { 74 t.Fatalf("got stack.GetMainNICAddress(_, _) = %s, want = %s", addr, addr1) 75 } 76 77 // We should not have sent any NDP NS messages. 78 if got := s.Stats().ICMP.V6PacketsSent.NeighborSolicit.Value(); got != 0 { 79 t.Fatalf("got NeighborSolicit = %d, want = 0", got) 80 } 81 } 82 83 // ndpDADEvent is a set of parameters that was passed to 84 // ndpDispatcher.OnDuplicateAddressDetectionStatus. 85 type ndpDADEvent struct { 86 nicID tcpip.NICID 87 addr tcpip.Address 88 resolved bool 89 err *tcpip.Error 90 } 91 92 type ndpRouterEvent struct { 93 nicID tcpip.NICID 94 addr tcpip.Address 95 // true if router was discovered, false if invalidated. 96 discovered bool 97 } 98 99 type ndpPrefixEvent struct { 100 nicID tcpip.NICID 101 prefix tcpip.Subnet 102 // true if prefix was discovered, false if invalidated. 103 discovered bool 104 } 105 106 var _ stack.NDPDispatcher = (*ndpDispatcher)(nil) 107 108 // ndpDispatcher implements NDPDispatcher so tests can know when various NDP 109 // related events happen for test purposes. 110 type ndpDispatcher struct { 111 dadC chan ndpDADEvent 112 routerC chan ndpRouterEvent 113 rememberRouter bool 114 prefixC chan ndpPrefixEvent 115 rememberPrefix bool 116 routeTable []tcpip.Route 117 } 118 119 // Implements stack.NDPDispatcher.OnDuplicateAddressDetectionStatus. 120 func (n *ndpDispatcher) OnDuplicateAddressDetectionStatus(nicID tcpip.NICID, addr tcpip.Address, resolved bool, err *tcpip.Error) { 121 if n.dadC != nil { 122 n.dadC <- ndpDADEvent{ 123 nicID, 124 addr, 125 resolved, 126 err, 127 } 128 } 129 } 130 131 // Implements stack.NDPDispatcher.OnDefaultRouterDiscovered. 132 func (n *ndpDispatcher) OnDefaultRouterDiscovered(nicID tcpip.NICID, addr tcpip.Address) (bool, []tcpip.Route) { 133 if n.routerC != nil { 134 n.routerC <- ndpRouterEvent{ 135 nicID, 136 addr, 137 true, 138 } 139 } 140 141 if !n.rememberRouter { 142 return false, nil 143 } 144 145 rt := append([]tcpip.Route(nil), n.routeTable...) 146 rt = append(rt, tcpip.Route{ 147 Destination: header.IPv6EmptySubnet, 148 Gateway: addr, 149 NIC: nicID, 150 }) 151 n.routeTable = rt 152 return true, rt 153 } 154 155 // Implements stack.NDPDispatcher.OnDefaultRouterInvalidated. 156 func (n *ndpDispatcher) OnDefaultRouterInvalidated(nicID tcpip.NICID, addr tcpip.Address) []tcpip.Route { 157 if n.routerC != nil { 158 n.routerC <- ndpRouterEvent{ 159 nicID, 160 addr, 161 false, 162 } 163 } 164 165 var rt []tcpip.Route 166 exclude := tcpip.Route{ 167 Destination: header.IPv6EmptySubnet, 168 Gateway: addr, 169 NIC: nicID, 170 } 171 172 for _, r := range n.routeTable { 173 if r != exclude { 174 rt = append(rt, r) 175 } 176 } 177 n.routeTable = rt 178 return rt 179 } 180 181 // Implements stack.NDPDispatcher.OnOnLinkPrefixDiscovered. 182 func (n *ndpDispatcher) OnOnLinkPrefixDiscovered(nicID tcpip.NICID, prefix tcpip.Subnet) (bool, []tcpip.Route) { 183 if n.prefixC != nil { 184 n.prefixC <- ndpPrefixEvent{ 185 nicID, 186 prefix, 187 true, 188 } 189 } 190 191 if !n.rememberPrefix { 192 return false, nil 193 } 194 195 rt := append([]tcpip.Route(nil), n.routeTable...) 196 rt = append(rt, tcpip.Route{ 197 Destination: prefix, 198 NIC: nicID, 199 }) 200 n.routeTable = rt 201 return true, rt 202 } 203 204 // Implements stack.NDPDispatcher.OnOnLinkPrefixInvalidated. 205 func (n *ndpDispatcher) OnOnLinkPrefixInvalidated(nicID tcpip.NICID, prefix tcpip.Subnet) []tcpip.Route { 206 if n.prefixC != nil { 207 n.prefixC <- ndpPrefixEvent{ 208 nicID, 209 prefix, 210 false, 211 } 212 } 213 214 rt := make([]tcpip.Route, 0) 215 exclude := tcpip.Route{ 216 Destination: prefix, 217 NIC: nicID, 218 } 219 220 for _, r := range n.routeTable { 221 if r != exclude { 222 rt = append(rt, r) 223 } 224 } 225 n.routeTable = rt 226 return rt 227 } 228 229 // TestDADResolve tests that an address successfully resolves after performing 230 // DAD for various values of DupAddrDetectTransmits and RetransmitTimer. 231 // Included in the subtests is a test to make sure that an invalid 232 // RetransmitTimer (<1ms) values get fixed to the default RetransmitTimer of 1s. 233 func TestDADResolve(t *testing.T) { 234 tests := []struct { 235 name string 236 dupAddrDetectTransmits uint8 237 retransTimer time.Duration 238 expectedRetransmitTimer time.Duration 239 }{ 240 {"1:1s:1s", 1, time.Second, time.Second}, 241 {"2:1s:1s", 2, time.Second, time.Second}, 242 {"1:2s:2s", 1, 2 * time.Second, 2 * time.Second}, 243 // 0s is an invalid RetransmitTimer timer and will be fixed to 244 // the default RetransmitTimer value of 1s. 245 {"1:0s:1s", 1, 0, time.Second}, 246 } 247 248 for _, test := range tests { 249 t.Run(test.name, func(t *testing.T) { 250 ndpDisp := ndpDispatcher{ 251 dadC: make(chan ndpDADEvent), 252 } 253 opts := stack.Options{ 254 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 255 NDPDisp: &ndpDisp, 256 } 257 opts.NDPConfigs.RetransmitTimer = test.retransTimer 258 opts.NDPConfigs.DupAddrDetectTransmits = test.dupAddrDetectTransmits 259 260 e := channel.New(10, 1280, linkAddr1) 261 s := stack.New(opts) 262 if err := s.CreateNIC(1, e); err != nil { 263 t.Fatalf("CreateNIC(_) = %s", err) 264 } 265 266 if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { 267 t.Fatalf("AddAddress(_, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) 268 } 269 270 stat := s.Stats().ICMP.V6PacketsSent.NeighborSolicit 271 272 // Should have sent an NDP NS immediately. 273 if got := stat.Value(); got != 1 { 274 t.Fatalf("got NeighborSolicit = %d, want = 1", got) 275 276 } 277 278 // Address should not be considered bound to the NIC yet 279 // (DAD ongoing). 280 addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 281 if err != nil { 282 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 283 } 284 if want := (tcpip.AddressWithPrefix{}); addr != want { 285 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 286 } 287 288 // Wait for the remaining time - some delta (500ms), to 289 // make sure the address is still not resolved. 290 const delta = 500 * time.Millisecond 291 time.Sleep(test.expectedRetransmitTimer*time.Duration(test.dupAddrDetectTransmits) - delta) 292 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 293 if err != nil { 294 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 295 } 296 if want := (tcpip.AddressWithPrefix{}); addr != want { 297 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 298 } 299 300 // Wait for DAD to resolve. 301 select { 302 case <-time.After(2 * delta): 303 // We should get a resolution event after 500ms 304 // (delta) since we wait for 500ms less than the 305 // expected resolution time above to make sure 306 // that the address did not yet resolve. Waiting 307 // for 1s (2x delta) without a resolution event 308 // means something is wrong. 309 t.Fatal("timed out waiting for DAD resolution") 310 case e := <-ndpDisp.dadC: 311 if e.err != nil { 312 t.Fatal("got DAD error: ", e.err) 313 } 314 if e.nicID != 1 { 315 t.Fatalf("got DAD event w/ nicID = %d, want = 1", e.nicID) 316 } 317 if e.addr != addr1 { 318 t.Fatalf("got DAD event w/ addr = %s, want = %s", addr, addr1) 319 } 320 if !e.resolved { 321 t.Fatal("got DAD event w/ resolved = false, want = true") 322 } 323 } 324 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 325 if err != nil { 326 t.Fatalf("stack.GetMainNICAddress(_, _) err = %s", err) 327 } 328 if addr.Address != addr1 { 329 t.Fatalf("got stack.GetMainNICAddress(_, _) = %s, want = %s", addr, addr1) 330 } 331 332 // Should not have sent any more NS messages. 333 if got := stat.Value(); got != uint64(test.dupAddrDetectTransmits) { 334 t.Fatalf("got NeighborSolicit = %d, want = %d", got, test.dupAddrDetectTransmits) 335 } 336 337 // Validate the sent Neighbor Solicitation messages. 338 for i := uint8(0); i < test.dupAddrDetectTransmits; i++ { 339 p := <-e.C 340 341 // Make sure its an IPv6 packet. 342 if p.Proto != header.IPv6ProtocolNumber { 343 t.Fatalf("got Proto = %d, want = %d", p.Proto, header.IPv6ProtocolNumber) 344 } 345 346 // Check NDP packet. 347 checker.IPv6(t, p.Pkt.Header.View().ToVectorisedView().First(), 348 checker.TTL(header.NDPHopLimit), 349 checker.NDPNS( 350 checker.NDPNSTargetAddress(addr1))) 351 } 352 }) 353 } 354 355 } 356 357 // TestDADFail tests to make sure that the DAD process fails if another node is 358 // detected to be performing DAD on the same address (receive an NS message from 359 // a node doing DAD for the same address), or if another node is detected to own 360 // the address already (receive an NA message for the tentative address). 361 func TestDADFail(t *testing.T) { 362 tests := []struct { 363 name string 364 makeBuf func(tgt tcpip.Address) buffer.Prependable 365 getStat func(s tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter 366 }{ 367 { 368 "RxSolicit", 369 func(tgt tcpip.Address) buffer.Prependable { 370 hdr := buffer.NewPrependable(header.IPv6MinimumSize + header.ICMPv6NeighborSolicitMinimumSize) 371 pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborSolicitMinimumSize)) 372 pkt.SetType(header.ICMPv6NeighborSolicit) 373 ns := header.NDPNeighborSolicit(pkt.NDPPayload()) 374 ns.SetTargetAddress(tgt) 375 snmc := header.SolicitedNodeAddr(tgt) 376 pkt.SetChecksum(header.ICMPv6Checksum(pkt, header.IPv6Any, snmc, buffer.VectorisedView{})) 377 payloadLength := hdr.UsedLength() 378 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 379 ip.Encode(&header.IPv6Fields{ 380 PayloadLength: uint16(payloadLength), 381 NextHeader: uint8(icmp.ProtocolNumber6), 382 HopLimit: 255, 383 SrcAddr: header.IPv6Any, 384 DstAddr: snmc, 385 }) 386 387 return hdr 388 389 }, 390 func(s tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter { 391 return s.NeighborSolicit 392 }, 393 }, 394 { 395 "RxAdvert", 396 func(tgt tcpip.Address) buffer.Prependable { 397 hdr := buffer.NewPrependable(header.IPv6MinimumSize + header.ICMPv6NeighborAdvertSize) 398 pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertSize)) 399 pkt.SetType(header.ICMPv6NeighborAdvert) 400 na := header.NDPNeighborAdvert(pkt.NDPPayload()) 401 na.SetSolicitedFlag(true) 402 na.SetOverrideFlag(true) 403 na.SetTargetAddress(tgt) 404 pkt.SetChecksum(header.ICMPv6Checksum(pkt, tgt, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{})) 405 payloadLength := hdr.UsedLength() 406 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 407 ip.Encode(&header.IPv6Fields{ 408 PayloadLength: uint16(payloadLength), 409 NextHeader: uint8(icmp.ProtocolNumber6), 410 HopLimit: 255, 411 SrcAddr: tgt, 412 DstAddr: header.IPv6AllNodesMulticastAddress, 413 }) 414 415 return hdr 416 417 }, 418 func(s tcpip.ICMPv6ReceivedPacketStats) *tcpip.StatCounter { 419 return s.NeighborAdvert 420 }, 421 }, 422 } 423 424 for _, test := range tests { 425 t.Run(test.name, func(t *testing.T) { 426 ndpDisp := ndpDispatcher{ 427 dadC: make(chan ndpDADEvent), 428 } 429 ndpConfigs := stack.DefaultNDPConfigurations() 430 opts := stack.Options{ 431 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 432 NDPConfigs: ndpConfigs, 433 NDPDisp: &ndpDisp, 434 } 435 opts.NDPConfigs.RetransmitTimer = time.Second * 2 436 437 e := channel.New(10, 1280, linkAddr1) 438 s := stack.New(opts) 439 if err := s.CreateNIC(1, e); err != nil { 440 t.Fatalf("CreateNIC(_) = %s", err) 441 } 442 443 if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { 444 t.Fatalf("AddAddress(_, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) 445 } 446 447 // Address should not be considered bound to the NIC yet 448 // (DAD ongoing). 449 addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 450 if err != nil { 451 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 452 } 453 if want := (tcpip.AddressWithPrefix{}); addr != want { 454 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 455 } 456 457 // Receive a packet to simulate multiple nodes owning or 458 // attempting to own the same address. 459 hdr := test.makeBuf(addr1) 460 e.InjectInbound(header.IPv6ProtocolNumber, tcpip.PacketBuffer{ 461 Data: hdr.View().ToVectorisedView(), 462 }) 463 464 stat := test.getStat(s.Stats().ICMP.V6PacketsReceived) 465 if got := stat.Value(); got != 1 { 466 t.Fatalf("got stat = %d, want = 1", got) 467 } 468 469 // Wait for DAD to fail and make sure the address did 470 // not get resolved. 471 select { 472 case <-time.After(time.Duration(ndpConfigs.DupAddrDetectTransmits)*ndpConfigs.RetransmitTimer + time.Second): 473 // If we don't get a failure event after the 474 // expected resolution time + extra 1s buffer, 475 // something is wrong. 476 t.Fatal("timed out waiting for DAD failure") 477 case e := <-ndpDisp.dadC: 478 if e.err != nil { 479 t.Fatal("got DAD error: ", e.err) 480 } 481 if e.nicID != 1 { 482 t.Fatalf("got DAD event w/ nicID = %d, want = 1", e.nicID) 483 } 484 if e.addr != addr1 { 485 t.Fatalf("got DAD event w/ addr = %s, want = %s", addr, addr1) 486 } 487 if e.resolved { 488 t.Fatal("got DAD event w/ resolved = true, want = false") 489 } 490 } 491 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 492 if err != nil { 493 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 494 } 495 if want := (tcpip.AddressWithPrefix{}); addr != want { 496 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 497 } 498 }) 499 } 500 } 501 502 // TestDADStop tests to make sure that the DAD process stops when an address is 503 // removed. 504 func TestDADStop(t *testing.T) { 505 ndpDisp := ndpDispatcher{ 506 dadC: make(chan ndpDADEvent), 507 } 508 ndpConfigs := stack.NDPConfigurations{ 509 RetransmitTimer: time.Second, 510 DupAddrDetectTransmits: 2, 511 } 512 opts := stack.Options{ 513 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 514 NDPDisp: &ndpDisp, 515 NDPConfigs: ndpConfigs, 516 } 517 518 e := channel.New(10, 1280, linkAddr1) 519 s := stack.New(opts) 520 if err := s.CreateNIC(1, e); err != nil { 521 t.Fatalf("CreateNIC(_) = %s", err) 522 } 523 524 if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { 525 t.Fatalf("AddAddress(_, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) 526 } 527 528 // Address should not be considered bound to the NIC yet (DAD ongoing). 529 addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 530 if err != nil { 531 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 532 } 533 if want := (tcpip.AddressWithPrefix{}); addr != want { 534 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 535 } 536 537 // Remove the address. This should stop DAD. 538 if err := s.RemoveAddress(1, addr1); err != nil { 539 t.Fatalf("RemoveAddress(_, %s) = %s", addr1, err) 540 } 541 542 // Wait for DAD to fail (since the address was removed during DAD). 543 select { 544 case <-time.After(time.Duration(ndpConfigs.DupAddrDetectTransmits)*ndpConfigs.RetransmitTimer + time.Second): 545 // If we don't get a failure event after the expected resolution 546 // time + extra 1s buffer, something is wrong. 547 t.Fatal("timed out waiting for DAD failure") 548 case e := <-ndpDisp.dadC: 549 if e.err != nil { 550 t.Fatal("got DAD error: ", e.err) 551 } 552 if e.nicID != 1 { 553 t.Fatalf("got DAD event w/ nicID = %d, want = 1", e.nicID) 554 } 555 if e.addr != addr1 { 556 t.Fatalf("got DAD event w/ addr = %s, want = %s", addr, addr1) 557 } 558 if e.resolved { 559 t.Fatal("got DAD event w/ resolved = true, want = false") 560 } 561 562 } 563 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 564 if err != nil { 565 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 566 } 567 if want := (tcpip.AddressWithPrefix{}); addr != want { 568 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 569 } 570 571 // Should not have sent more than 1 NS message. 572 if got := s.Stats().ICMP.V6PacketsSent.NeighborSolicit.Value(); got > 1 { 573 t.Fatalf("got NeighborSolicit = %d, want <= 1", got) 574 } 575 } 576 577 // TestSetNDPConfigurationFailsForBadNICID tests to make sure we get an error if 578 // we attempt to update NDP configurations using an invalid NICID. 579 func TestSetNDPConfigurationFailsForBadNICID(t *testing.T) { 580 s := stack.New(stack.Options{ 581 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 582 }) 583 584 // No NIC with ID 1 yet. 585 if got := s.SetNDPConfigurations(1, stack.NDPConfigurations{}); got != tcpip.ErrUnknownNICID { 586 t.Fatalf("got s.SetNDPConfigurations = %v, want = %s", got, tcpip.ErrUnknownNICID) 587 } 588 } 589 590 // TestSetNDPConfigurations tests that we can update and use per-interface NDP 591 // configurations without affecting the default NDP configurations or other 592 // interfaces' configurations. 593 func TestSetNDPConfigurations(t *testing.T) { 594 tests := []struct { 595 name string 596 dupAddrDetectTransmits uint8 597 retransmitTimer time.Duration 598 expectedRetransmitTimer time.Duration 599 }{ 600 { 601 "OK", 602 1, 603 time.Second, 604 time.Second, 605 }, 606 { 607 "Invalid Retransmit Timer", 608 1, 609 0, 610 time.Second, 611 }, 612 } 613 614 for _, test := range tests { 615 t.Run(test.name, func(t *testing.T) { 616 ndpDisp := ndpDispatcher{ 617 dadC: make(chan ndpDADEvent), 618 } 619 e := channel.New(10, 1280, linkAddr1) 620 s := stack.New(stack.Options{ 621 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 622 NDPDisp: &ndpDisp, 623 }) 624 625 // This NIC(1)'s NDP configurations will be updated to 626 // be different from the default. 627 if err := s.CreateNIC(1, e); err != nil { 628 t.Fatalf("CreateNIC(1) = %s", err) 629 } 630 631 // Created before updating NIC(1)'s NDP configurations 632 // but updating NIC(1)'s NDP configurations should not 633 // affect other existing NICs. 634 if err := s.CreateNIC(2, e); err != nil { 635 t.Fatalf("CreateNIC(2) = %s", err) 636 } 637 638 // Update the NDP configurations on NIC(1) to use DAD. 639 configs := stack.NDPConfigurations{ 640 DupAddrDetectTransmits: test.dupAddrDetectTransmits, 641 RetransmitTimer: test.retransmitTimer, 642 } 643 if err := s.SetNDPConfigurations(1, configs); err != nil { 644 t.Fatalf("got SetNDPConfigurations(1, _) = %s", err) 645 } 646 647 // Created after updating NIC(1)'s NDP configurations 648 // but the stack's default NDP configurations should not 649 // have been updated. 650 if err := s.CreateNIC(3, e); err != nil { 651 t.Fatalf("CreateNIC(3) = %s", err) 652 } 653 654 // Add addresses for each NIC. 655 if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { 656 t.Fatalf("AddAddress(1, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) 657 } 658 if err := s.AddAddress(2, header.IPv6ProtocolNumber, addr2); err != nil { 659 t.Fatalf("AddAddress(2, %d, %s) = %s", header.IPv6ProtocolNumber, addr2, err) 660 } 661 if err := s.AddAddress(3, header.IPv6ProtocolNumber, addr3); err != nil { 662 t.Fatalf("AddAddress(3, %d, %s) = %s", header.IPv6ProtocolNumber, addr3, err) 663 } 664 665 // Address should not be considered bound to NIC(1) yet 666 // (DAD ongoing). 667 addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 668 if err != nil { 669 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 670 } 671 if want := (tcpip.AddressWithPrefix{}); addr != want { 672 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 673 } 674 675 // Should get the address on NIC(2) and NIC(3) 676 // immediately since we should not have performed DAD on 677 // it as the stack was configured to not do DAD by 678 // default and we only updated the NDP configurations on 679 // NIC(1). 680 addr, err = s.GetMainNICAddress(2, header.IPv6ProtocolNumber) 681 if err != nil { 682 t.Fatalf("stack.GetMainNICAddress(2, _) err = %s", err) 683 } 684 if addr.Address != addr2 { 685 t.Fatalf("got stack.GetMainNICAddress(2, _) = %s, want = %s", addr, addr2) 686 } 687 addr, err = s.GetMainNICAddress(3, header.IPv6ProtocolNumber) 688 if err != nil { 689 t.Fatalf("stack.GetMainNICAddress(3, _) err = %s", err) 690 } 691 if addr.Address != addr3 { 692 t.Fatalf("got stack.GetMainNICAddress(3, _) = %s, want = %s", addr, addr3) 693 } 694 695 // Sleep until right (500ms before) before resolution to 696 // make sure the address didn't resolve on NIC(1) yet. 697 const delta = 500 * time.Millisecond 698 time.Sleep(time.Duration(test.dupAddrDetectTransmits)*test.expectedRetransmitTimer - delta) 699 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 700 if err != nil { 701 t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) 702 } 703 if want := (tcpip.AddressWithPrefix{}); addr != want { 704 t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) 705 } 706 707 // Wait for DAD to resolve. 708 select { 709 case <-time.After(2 * delta): 710 // We should get a resolution event after 500ms 711 // (delta) since we wait for 500ms less than the 712 // expected resolution time above to make sure 713 // that the address did not yet resolve. Waiting 714 // for 1s (2x delta) without a resolution event 715 // means something is wrong. 716 t.Fatal("timed out waiting for DAD resolution") 717 case e := <-ndpDisp.dadC: 718 if e.err != nil { 719 t.Fatal("got DAD error: ", e.err) 720 } 721 if e.nicID != 1 { 722 t.Fatalf("got DAD event w/ nicID = %d, want = 1", e.nicID) 723 } 724 if e.addr != addr1 { 725 t.Fatalf("got DAD event w/ addr = %s, want = %s", addr, addr1) 726 } 727 if !e.resolved { 728 t.Fatal("got DAD event w/ resolved = false, want = true") 729 } 730 } 731 addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) 732 if err != nil { 733 t.Fatalf("stack.GetMainNICAddress(1, _) err = %s", err) 734 } 735 if addr.Address != addr1 { 736 t.Fatalf("got stack.GetMainNICAddress(1, _) = %s, want = %s", addr, addr1) 737 } 738 }) 739 } 740 } 741 742 // raBufWithOpts returns a valid NDP Router Advertisement with options. 743 // 744 // Note, raBufWithOpts does not populate any of the RA fields other than the 745 // Router Lifetime. 746 func raBufWithOpts(ip tcpip.Address, rl uint16, optSer header.NDPOptionsSerializer) tcpip.PacketBuffer { 747 icmpSize := header.ICMPv6HeaderSize + header.NDPRAMinimumSize + int(optSer.Length()) 748 hdr := buffer.NewPrependable(header.IPv6MinimumSize + icmpSize) 749 pkt := header.ICMPv6(hdr.Prepend(icmpSize)) 750 pkt.SetType(header.ICMPv6RouterAdvert) 751 pkt.SetCode(0) 752 ra := header.NDPRouterAdvert(pkt.NDPPayload()) 753 opts := ra.Options() 754 opts.Serialize(optSer) 755 // Populate the Router Lifetime. 756 binary.BigEndian.PutUint16(pkt.NDPPayload()[2:], rl) 757 pkt.SetChecksum(header.ICMPv6Checksum(pkt, ip, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{})) 758 payloadLength := hdr.UsedLength() 759 iph := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 760 iph.Encode(&header.IPv6Fields{ 761 PayloadLength: uint16(payloadLength), 762 NextHeader: uint8(icmp.ProtocolNumber6), 763 HopLimit: header.NDPHopLimit, 764 SrcAddr: ip, 765 DstAddr: header.IPv6AllNodesMulticastAddress, 766 }) 767 768 return tcpip.PacketBuffer{Data: hdr.View().ToVectorisedView()} 769 } 770 771 // raBuf returns a valid NDP Router Advertisement. 772 // 773 // Note, raBuf does not populate any of the RA fields other than the 774 // Router Lifetime. 775 func raBuf(ip tcpip.Address, rl uint16) tcpip.PacketBuffer { 776 return raBufWithOpts(ip, rl, header.NDPOptionsSerializer{}) 777 } 778 779 // raBufWithPI returns a valid NDP Router Advertisement with a single Prefix 780 // Information option. 781 // 782 // Note, raBufWithPI does not populate any of the RA fields other than the 783 // Router Lifetime. 784 func raBufWithPI(ip tcpip.Address, rl uint16, prefix tcpip.AddressWithPrefix, onLink bool, vl uint32) tcpip.PacketBuffer { 785 flags := uint8(0) 786 if onLink { 787 flags |= 128 788 } 789 790 buf := [30]byte{} 791 buf[0] = uint8(prefix.PrefixLen) 792 buf[1] = flags 793 binary.BigEndian.PutUint32(buf[2:], vl) 794 copy(buf[14:], prefix.Address) 795 return raBufWithOpts(ip, rl, header.NDPOptionsSerializer{ 796 header.NDPPrefixInformation(buf[:]), 797 }) 798 } 799 800 // TestNoRouterDiscovery tests that router discovery will not be performed if 801 // configured not to. 802 func TestNoRouterDiscovery(t *testing.T) { 803 // Being configured to discover routers means handle and 804 // discover are set to true and forwarding is set to false. 805 // This tests all possible combinations of the configurations, 806 // except for the configuration where handle = true, discover = 807 // true and forwarding = false (the required configuration to do 808 // router discovery) - that will done in other tests. 809 for i := 0; i < 7; i++ { 810 handle := i&1 != 0 811 discover := i&2 != 0 812 forwarding := i&4 == 0 813 814 t.Run(fmt.Sprintf("HandleRAs(%t), DiscoverDefaultRouters(%t), Forwarding(%t)", handle, discover, forwarding), func(t *testing.T) { 815 ndpDisp := ndpDispatcher{ 816 routerC: make(chan ndpRouterEvent, 10), 817 } 818 e := channel.New(10, 1280, linkAddr1) 819 s := stack.New(stack.Options{ 820 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 821 NDPConfigs: stack.NDPConfigurations{ 822 HandleRAs: handle, 823 DiscoverDefaultRouters: discover, 824 }, 825 NDPDisp: &ndpDisp, 826 }) 827 s.SetForwarding(forwarding) 828 829 if err := s.CreateNIC(1, e); err != nil { 830 t.Fatalf("CreateNIC(1) = %s", err) 831 } 832 833 // Rx an RA with non-zero lifetime. 834 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, 1000)) 835 select { 836 case <-ndpDisp.routerC: 837 t.Fatal("unexpectedly discovered a router when configured not to") 838 case <-time.After(defaultTimeout): 839 } 840 }) 841 } 842 } 843 844 // TestRouterDiscoveryDispatcherNoRemember tests that the stack does not 845 // remember a discovered router when the dispatcher asks it not to. 846 func TestRouterDiscoveryDispatcherNoRemember(t *testing.T) { 847 ndpDisp := ndpDispatcher{ 848 routerC: make(chan ndpRouterEvent, 10), 849 } 850 e := channel.New(10, 1280, linkAddr1) 851 s := stack.New(stack.Options{ 852 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 853 NDPConfigs: stack.NDPConfigurations{ 854 HandleRAs: true, 855 DiscoverDefaultRouters: true, 856 }, 857 NDPDisp: &ndpDisp, 858 }) 859 860 if err := s.CreateNIC(1, e); err != nil { 861 t.Fatalf("CreateNIC(1) = %s", err) 862 } 863 864 routeTable := []tcpip.Route{ 865 { 866 header.IPv6EmptySubnet, 867 llAddr3, 868 1, 869 }, 870 } 871 s.SetRouteTable(routeTable) 872 873 // Rx an RA with short lifetime. 874 lifetime := time.Duration(1) 875 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, uint16(lifetime))) 876 select { 877 case r := <-ndpDisp.routerC: 878 if r.nicID != 1 { 879 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 880 } 881 if r.addr != llAddr2 { 882 t.Fatalf("got r.addr = %s, want = %s", r.addr, llAddr2) 883 } 884 if !r.discovered { 885 t.Fatal("got r.discovered = false, want = true") 886 } 887 case <-time.After(defaultTimeout): 888 t.Fatal("timeout waiting for router discovery event") 889 } 890 891 // Original route table should not have been modified. 892 if got := s.GetRouteTable(); !cmp.Equal(got, routeTable) { 893 t.Fatalf("got GetRouteTable = %v, want = %v", got, routeTable) 894 } 895 896 // Wait for the normal invalidation time plus an extra second to 897 // make sure we do not actually receive any invalidation events as 898 // we should not have remembered the router in the first place. 899 select { 900 case <-ndpDisp.routerC: 901 t.Fatal("should not have received any router events") 902 case <-time.After(lifetime*time.Second + defaultTimeout): 903 } 904 905 // Original route table should not have been modified. 906 if got := s.GetRouteTable(); !cmp.Equal(got, routeTable) { 907 t.Fatalf("got GetRouteTable = %v, want = %v", got, routeTable) 908 } 909 } 910 911 func TestRouterDiscovery(t *testing.T) { 912 ndpDisp := ndpDispatcher{ 913 routerC: make(chan ndpRouterEvent, 10), 914 rememberRouter: true, 915 } 916 e := channel.New(10, 1280, linkAddr1) 917 s := stack.New(stack.Options{ 918 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 919 NDPConfigs: stack.NDPConfigurations{ 920 HandleRAs: true, 921 DiscoverDefaultRouters: true, 922 }, 923 NDPDisp: &ndpDisp, 924 }) 925 926 waitForEvent := func(addr tcpip.Address, discovered bool, timeout time.Duration) { 927 t.Helper() 928 929 select { 930 case r := <-ndpDisp.routerC: 931 if r.nicID != 1 { 932 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 933 } 934 if r.addr != addr { 935 t.Fatalf("got r.addr = %s, want = %s", r.addr, addr) 936 } 937 if r.discovered != discovered { 938 t.Fatalf("got r.discovered = %t, want = %t", r.discovered, discovered) 939 } 940 case <-time.After(timeout): 941 t.Fatal("timeout waiting for router discovery event") 942 } 943 } 944 945 if err := s.CreateNIC(1, e); err != nil { 946 t.Fatalf("CreateNIC(1) = %s", err) 947 } 948 949 // Rx an RA from lladdr2 with zero lifetime. It should not be 950 // remembered. 951 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, 0)) 952 select { 953 case <-ndpDisp.routerC: 954 t.Fatal("unexpectedly discovered a router with 0 lifetime") 955 case <-time.After(defaultTimeout): 956 } 957 958 // Rx an RA from lladdr2 with a huge lifetime. 959 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, 1000)) 960 waitForEvent(llAddr2, true, defaultTimeout) 961 962 // Should have a default route through the discovered router. 963 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr2, 1}}; !cmp.Equal(got, want) { 964 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 965 } 966 967 // Rx an RA from another router (lladdr3) with non-zero lifetime. 968 l3Lifetime := time.Duration(6) 969 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr3, uint16(l3Lifetime))) 970 waitForEvent(llAddr3, true, defaultTimeout) 971 972 // Should have default routes through the discovered routers. 973 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr2, 1}, {header.IPv6EmptySubnet, llAddr3, 1}}; !cmp.Equal(got, want) { 974 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 975 } 976 977 // Rx an RA from lladdr2 with lesser lifetime. 978 l2Lifetime := time.Duration(2) 979 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, uint16(l2Lifetime))) 980 select { 981 case <-ndpDisp.routerC: 982 t.Fatal("Should not receive a router event when updating lifetimes for known routers") 983 case <-time.After(defaultTimeout): 984 } 985 986 // Should still have a default route through the discovered routers. 987 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr2, 1}, {header.IPv6EmptySubnet, llAddr3, 1}}; !cmp.Equal(got, want) { 988 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 989 } 990 991 // Wait for lladdr2's router invalidation timer to fire. The lifetime 992 // of the router should have been updated to the most recent (smaller) 993 // lifetime. 994 // 995 // Wait for the normal lifetime plus an extra bit for the 996 // router to get invalidated. If we don't get an invalidation 997 // event after this time, then something is wrong. 998 waitForEvent(llAddr2, false, l2Lifetime*time.Second+defaultTimeout) 999 1000 // Should no longer have the default route through lladdr2. 1001 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr3, 1}}; !cmp.Equal(got, want) { 1002 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1003 } 1004 1005 // Rx an RA from lladdr2 with huge lifetime. 1006 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, 1000)) 1007 waitForEvent(llAddr2, true, defaultTimeout) 1008 1009 // Should have a default route through the discovered routers. 1010 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr3, 1}, {header.IPv6EmptySubnet, llAddr2, 1}}; !cmp.Equal(got, want) { 1011 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1012 } 1013 1014 // Rx an RA from lladdr2 with zero lifetime. It should be invalidated. 1015 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr2, 0)) 1016 waitForEvent(llAddr2, false, defaultTimeout) 1017 1018 // Should have deleted the default route through the router that just 1019 // got invalidated. 1020 if got, want := s.GetRouteTable(), []tcpip.Route{{header.IPv6EmptySubnet, llAddr3, 1}}; !cmp.Equal(got, want) { 1021 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1022 } 1023 1024 // Wait for lladdr3's router invalidation timer to fire. The lifetime 1025 // of the router should have been updated to the most recent (smaller) 1026 // lifetime. 1027 // 1028 // Wait for the normal lifetime plus an extra bit for the 1029 // router to get invalidated. If we don't get an invalidation 1030 // event after this time, then something is wrong. 1031 waitForEvent(llAddr3, false, l3Lifetime*time.Second+defaultTimeout) 1032 1033 // Should not have any routes now that all discovered routers have been 1034 // invalidated. 1035 if got := len(s.GetRouteTable()); got != 0 { 1036 t.Fatalf("got len(s.GetRouteTable()) = %d, want = 0", got) 1037 } 1038 } 1039 1040 // TestRouterDiscoveryMaxRouters tests that only 1041 // stack.MaxDiscoveredDefaultRouters discovered routers are remembered. 1042 func TestRouterDiscoveryMaxRouters(t *testing.T) { 1043 ndpDisp := ndpDispatcher{ 1044 routerC: make(chan ndpRouterEvent, 10), 1045 rememberRouter: true, 1046 } 1047 e := channel.New(10, 1280, linkAddr1) 1048 s := stack.New(stack.Options{ 1049 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1050 NDPConfigs: stack.NDPConfigurations{ 1051 HandleRAs: true, 1052 DiscoverDefaultRouters: true, 1053 }, 1054 NDPDisp: &ndpDisp, 1055 }) 1056 1057 if err := s.CreateNIC(1, e); err != nil { 1058 t.Fatalf("CreateNIC(1) = %s", err) 1059 } 1060 1061 expectedRt := [stack.MaxDiscoveredDefaultRouters]tcpip.Route{} 1062 1063 // Receive an RA from 2 more than the max number of discovered routers. 1064 for i := 1; i <= stack.MaxDiscoveredDefaultRouters+2; i++ { 1065 linkAddr := []byte{2, 2, 3, 4, 5, 0} 1066 linkAddr[5] = byte(i) 1067 llAddr := header.LinkLocalAddr(tcpip.LinkAddress(linkAddr)) 1068 1069 e.InjectInbound(header.IPv6ProtocolNumber, raBuf(llAddr, 5)) 1070 1071 if i <= stack.MaxDiscoveredDefaultRouters { 1072 expectedRt[i-1] = tcpip.Route{header.IPv6EmptySubnet, llAddr, 1} 1073 select { 1074 case r := <-ndpDisp.routerC: 1075 if r.nicID != 1 { 1076 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 1077 } 1078 if r.addr != llAddr { 1079 t.Fatalf("got r.addr = %s, want = %s", r.addr, llAddr) 1080 } 1081 if !r.discovered { 1082 t.Fatal("got r.discovered = false, want = true") 1083 } 1084 case <-time.After(defaultTimeout): 1085 t.Fatal("timeout waiting for router discovery event") 1086 } 1087 1088 } else { 1089 select { 1090 case <-ndpDisp.routerC: 1091 t.Fatal("should not have discovered a new router after we already discovered the max number of routers") 1092 case <-time.After(defaultTimeout): 1093 } 1094 } 1095 } 1096 1097 // Should only have default routes for the first 1098 // stack.MaxDiscoveredDefaultRouters discovered routers. 1099 if got := s.GetRouteTable(); !cmp.Equal(got, expectedRt[:]) { 1100 t.Fatalf("got GetRouteTable = %v, want = %v", got, expectedRt) 1101 } 1102 } 1103 1104 // TestNoPrefixDiscovery tests that prefix discovery will not be performed if 1105 // configured not to. 1106 func TestNoPrefixDiscovery(t *testing.T) { 1107 prefix := tcpip.AddressWithPrefix{ 1108 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00"), 1109 PrefixLen: 64, 1110 } 1111 1112 // Being configured to discover prefixes means handle and 1113 // discover are set to true and forwarding is set to false. 1114 // This tests all possible combinations of the configurations, 1115 // except for the configuration where handle = true, discover = 1116 // true and forwarding = false (the required configuration to do 1117 // prefix discovery) - that will done in other tests. 1118 for i := 0; i < 7; i++ { 1119 handle := i&1 != 0 1120 discover := i&2 != 0 1121 forwarding := i&4 == 0 1122 1123 t.Run(fmt.Sprintf("HandleRAs(%t), DiscoverOnLinkPrefixes(%t), Forwarding(%t)", handle, discover, forwarding), func(t *testing.T) { 1124 ndpDisp := ndpDispatcher{ 1125 prefixC: make(chan ndpPrefixEvent, 10), 1126 } 1127 e := channel.New(10, 1280, linkAddr1) 1128 s := stack.New(stack.Options{ 1129 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1130 NDPConfigs: stack.NDPConfigurations{ 1131 HandleRAs: handle, 1132 DiscoverOnLinkPrefixes: discover, 1133 }, 1134 NDPDisp: &ndpDisp, 1135 }) 1136 s.SetForwarding(forwarding) 1137 1138 if err := s.CreateNIC(1, e); err != nil { 1139 t.Fatalf("CreateNIC(1) = %s", err) 1140 } 1141 1142 // Rx an RA with prefix with non-zero lifetime. 1143 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, 10)) 1144 1145 select { 1146 case <-ndpDisp.prefixC: 1147 t.Fatal("unexpectedly discovered a prefix when configured not to") 1148 case <-time.After(defaultTimeout): 1149 } 1150 }) 1151 } 1152 } 1153 1154 // TestPrefixDiscoveryDispatcherNoRemember tests that the stack does not 1155 // remember a discovered on-link prefix when the dispatcher asks it not to. 1156 func TestPrefixDiscoveryDispatcherNoRemember(t *testing.T) { 1157 prefix := tcpip.AddressWithPrefix{ 1158 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00"), 1159 PrefixLen: 64, 1160 } 1161 subnet := prefix.Subnet() 1162 1163 ndpDisp := ndpDispatcher{ 1164 prefixC: make(chan ndpPrefixEvent, 10), 1165 } 1166 e := channel.New(10, 1280, linkAddr1) 1167 s := stack.New(stack.Options{ 1168 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1169 NDPConfigs: stack.NDPConfigurations{ 1170 HandleRAs: true, 1171 DiscoverDefaultRouters: false, 1172 DiscoverOnLinkPrefixes: true, 1173 }, 1174 NDPDisp: &ndpDisp, 1175 }) 1176 1177 if err := s.CreateNIC(1, e); err != nil { 1178 t.Fatalf("CreateNIC(1) = %s", err) 1179 } 1180 1181 routeTable := []tcpip.Route{ 1182 { 1183 header.IPv6EmptySubnet, 1184 llAddr3, 1185 1, 1186 }, 1187 } 1188 s.SetRouteTable(routeTable) 1189 1190 // Rx an RA with prefix with a short lifetime. 1191 const lifetime = 1 1192 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, lifetime)) 1193 select { 1194 case r := <-ndpDisp.prefixC: 1195 if r.nicID != 1 { 1196 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 1197 } 1198 if r.prefix != subnet { 1199 t.Fatalf("got r.prefix = %s, want = %s", r.prefix, subnet) 1200 } 1201 if !r.discovered { 1202 t.Fatal("got r.discovered = false, want = true") 1203 } 1204 case <-time.After(defaultTimeout): 1205 t.Fatal("timeout waiting for prefix discovery event") 1206 } 1207 1208 // Original route table should not have been modified. 1209 if got := s.GetRouteTable(); !cmp.Equal(got, routeTable) { 1210 t.Fatalf("got GetRouteTable = %v, want = %v", got, routeTable) 1211 } 1212 1213 // Wait for the normal invalidation time plus some buffer to 1214 // make sure we do not actually receive any invalidation events as 1215 // we should not have remembered the prefix in the first place. 1216 select { 1217 case <-ndpDisp.prefixC: 1218 t.Fatal("should not have received any prefix events") 1219 case <-time.After(lifetime*time.Second + defaultTimeout): 1220 } 1221 1222 // Original route table should not have been modified. 1223 if got := s.GetRouteTable(); !cmp.Equal(got, routeTable) { 1224 t.Fatalf("got GetRouteTable = %v, want = %v", got, routeTable) 1225 } 1226 } 1227 1228 func TestPrefixDiscovery(t *testing.T) { 1229 prefix1 := tcpip.AddressWithPrefix{ 1230 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00"), 1231 PrefixLen: 64, 1232 } 1233 prefix2 := tcpip.AddressWithPrefix{ 1234 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x09\x00\x00\x00\x00\x00\x00\x00\x00"), 1235 PrefixLen: 64, 1236 } 1237 prefix3 := tcpip.AddressWithPrefix{ 1238 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x09\x0a\x00\x00\x00\x00\x00\x00\x00"), 1239 PrefixLen: 72, 1240 } 1241 subnet1 := prefix1.Subnet() 1242 subnet2 := prefix2.Subnet() 1243 subnet3 := prefix3.Subnet() 1244 1245 ndpDisp := ndpDispatcher{ 1246 prefixC: make(chan ndpPrefixEvent, 10), 1247 rememberPrefix: true, 1248 } 1249 e := channel.New(10, 1280, linkAddr1) 1250 s := stack.New(stack.Options{ 1251 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1252 NDPConfigs: stack.NDPConfigurations{ 1253 HandleRAs: true, 1254 DiscoverOnLinkPrefixes: true, 1255 }, 1256 NDPDisp: &ndpDisp, 1257 }) 1258 1259 waitForEvent := func(subnet tcpip.Subnet, discovered bool, timeout time.Duration) { 1260 t.Helper() 1261 1262 select { 1263 case r := <-ndpDisp.prefixC: 1264 if r.nicID != 1 { 1265 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 1266 } 1267 if r.prefix != subnet { 1268 t.Fatalf("got r.prefix = %s, want = %s", r.prefix, subnet) 1269 } 1270 if r.discovered != discovered { 1271 t.Fatalf("got r.discovered = %t, want = %t", r.discovered, discovered) 1272 } 1273 case <-time.After(timeout): 1274 t.Fatal("timeout waiting for prefix discovery event") 1275 } 1276 } 1277 1278 if err := s.CreateNIC(1, e); err != nil { 1279 t.Fatalf("CreateNIC(1) = %s", err) 1280 } 1281 1282 // Receive an RA with prefix1 in an NDP Prefix Information option (PI) 1283 // with zero valid lifetime. 1284 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix1, true, 0)) 1285 select { 1286 case <-ndpDisp.prefixC: 1287 t.Fatal("unexpectedly discovered a prefix with 0 lifetime") 1288 case <-time.After(defaultTimeout): 1289 } 1290 1291 // Receive an RA with prefix1 in an NDP Prefix Information option (PI) 1292 // with non-zero lifetime. 1293 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix1, true, 100)) 1294 waitForEvent(subnet1, true, defaultTimeout) 1295 1296 // Should have added a device route for subnet1 through the nic. 1297 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet1, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1298 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1299 } 1300 1301 // Receive an RA with prefix2 in a PI. 1302 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix2, true, 100)) 1303 waitForEvent(subnet2, true, defaultTimeout) 1304 1305 // Should have added a device route for subnet2 through the nic. 1306 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet1, tcpip.Address([]byte(nil)), 1}, {subnet2, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1307 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1308 } 1309 1310 // Receive an RA with prefix3 in a PI. 1311 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix3, true, 100)) 1312 waitForEvent(subnet3, true, defaultTimeout) 1313 1314 // Should have added a device route for subnet3 through the nic. 1315 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet1, tcpip.Address([]byte(nil)), 1}, {subnet2, tcpip.Address([]byte(nil)), 1}, {subnet3, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1316 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1317 } 1318 1319 // Receive an RA with prefix1 in a PI with lifetime = 0. 1320 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix1, true, 0)) 1321 waitForEvent(subnet1, false, defaultTimeout) 1322 1323 // Should have removed the device route for subnet1 through the nic. 1324 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet2, tcpip.Address([]byte(nil)), 1}, {subnet3, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1325 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1326 } 1327 1328 // Receive an RA with prefix2 in a PI with lesser lifetime. 1329 lifetime := uint32(2) 1330 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix2, true, lifetime)) 1331 select { 1332 case <-ndpDisp.prefixC: 1333 t.Fatal("unexpectedly received prefix event when updating lifetime") 1334 case <-time.After(defaultTimeout): 1335 } 1336 1337 // Should not have updated route table. 1338 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet2, tcpip.Address([]byte(nil)), 1}, {subnet3, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1339 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1340 } 1341 1342 // Wait for prefix2's most recent invalidation timer plus some buffer to 1343 // expire. 1344 waitForEvent(subnet2, false, time.Duration(lifetime)*time.Second+defaultTimeout) 1345 1346 // Should have removed the device route for subnet2 through the nic. 1347 if got, want := s.GetRouteTable(), []tcpip.Route{{subnet3, tcpip.Address([]byte(nil)), 1}}; !cmp.Equal(got, want) { 1348 t.Fatalf("got GetRouteTable = %v, want = %v", got, want) 1349 } 1350 1351 // Receive RA to invalidate prefix3. 1352 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix3, true, 0)) 1353 waitForEvent(subnet3, false, defaultTimeout) 1354 1355 // Should not have any routes. 1356 if got := len(s.GetRouteTable()); got != 0 { 1357 t.Fatalf("got len(s.GetRouteTable()) = %d, want = 0", got) 1358 } 1359 } 1360 1361 func TestPrefixDiscoveryWithInfiniteLifetime(t *testing.T) { 1362 // Update the infinite lifetime value to a smaller value so we can test 1363 // that when we receive a PI with such a lifetime value, we do not 1364 // invalidate the prefix. 1365 const testInfiniteLifetimeSeconds = 2 1366 const testInfiniteLifetime = testInfiniteLifetimeSeconds * time.Second 1367 saved := header.NDPPrefixInformationInfiniteLifetime 1368 header.NDPPrefixInformationInfiniteLifetime = testInfiniteLifetime 1369 defer func() { 1370 header.NDPPrefixInformationInfiniteLifetime = saved 1371 }() 1372 1373 prefix := tcpip.AddressWithPrefix{ 1374 Address: tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00"), 1375 PrefixLen: 64, 1376 } 1377 subnet := prefix.Subnet() 1378 1379 ndpDisp := ndpDispatcher{ 1380 prefixC: make(chan ndpPrefixEvent, 10), 1381 rememberPrefix: true, 1382 } 1383 e := channel.New(10, 1280, linkAddr1) 1384 s := stack.New(stack.Options{ 1385 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1386 NDPConfigs: stack.NDPConfigurations{ 1387 HandleRAs: true, 1388 DiscoverOnLinkPrefixes: true, 1389 }, 1390 NDPDisp: &ndpDisp, 1391 }) 1392 1393 waitForEvent := func(discovered bool, timeout time.Duration) { 1394 t.Helper() 1395 1396 select { 1397 case r := <-ndpDisp.prefixC: 1398 if r.nicID != 1 { 1399 t.Errorf("got r.nicID = %d, want = 1", r.nicID) 1400 } 1401 if r.prefix != subnet { 1402 t.Errorf("got r.prefix = %s, want = %s", r.prefix, subnet) 1403 } 1404 if r.discovered != discovered { 1405 t.Errorf("got r.discovered = %t, want = %t", r.discovered, discovered) 1406 } 1407 case <-time.After(timeout): 1408 t.Fatal("timeout waiting for prefix discovery event") 1409 } 1410 } 1411 1412 if err := s.CreateNIC(1, e); err != nil { 1413 t.Fatalf("CreateNIC(1) = %s", err) 1414 } 1415 1416 // Receive an RA with prefix in an NDP Prefix Information option (PI) 1417 // with infinite valid lifetime which should not get invalidated. 1418 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, testInfiniteLifetimeSeconds)) 1419 waitForEvent(true, defaultTimeout) 1420 select { 1421 case <-ndpDisp.prefixC: 1422 t.Fatal("unexpectedly invalidated a prefix with infinite lifetime") 1423 case <-time.After(testInfiniteLifetime + defaultTimeout): 1424 } 1425 1426 // Receive an RA with finite lifetime. 1427 // The prefix should get invalidated after 1s. 1428 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, testInfiniteLifetimeSeconds-1)) 1429 waitForEvent(false, testInfiniteLifetime) 1430 1431 // Receive an RA with finite lifetime. 1432 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, testInfiniteLifetimeSeconds-1)) 1433 waitForEvent(true, defaultTimeout) 1434 1435 // Receive an RA with prefix with an infinite lifetime. 1436 // The prefix should not be invalidated. 1437 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, testInfiniteLifetimeSeconds)) 1438 select { 1439 case <-ndpDisp.prefixC: 1440 t.Fatal("unexpectedly invalidated a prefix with infinite lifetime") 1441 case <-time.After(testInfiniteLifetime + defaultTimeout): 1442 } 1443 1444 // Receive an RA with a prefix with a lifetime value greater than the 1445 // set infinite lifetime value. 1446 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, testInfiniteLifetimeSeconds+1)) 1447 select { 1448 case <-ndpDisp.prefixC: 1449 t.Fatal("unexpectedly invalidated a prefix with infinite lifetime") 1450 case <-time.After((testInfiniteLifetimeSeconds+1)*time.Second + defaultTimeout): 1451 } 1452 1453 // Receive an RA with 0 lifetime. 1454 // The prefix should get invalidated. 1455 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithPI(llAddr2, 0, prefix, true, 0)) 1456 waitForEvent(false, defaultTimeout) 1457 } 1458 1459 // TestPrefixDiscoveryMaxRouters tests that only 1460 // stack.MaxDiscoveredOnLinkPrefixes discovered on-link prefixes are remembered. 1461 func TestPrefixDiscoveryMaxOnLinkPrefixes(t *testing.T) { 1462 ndpDisp := ndpDispatcher{ 1463 prefixC: make(chan ndpPrefixEvent, stack.MaxDiscoveredOnLinkPrefixes+3), 1464 rememberPrefix: true, 1465 } 1466 e := channel.New(10, 1280, linkAddr1) 1467 s := stack.New(stack.Options{ 1468 NetworkProtocols: []stack.NetworkProtocol{ipv6.NewProtocol()}, 1469 NDPConfigs: stack.NDPConfigurations{ 1470 HandleRAs: true, 1471 DiscoverDefaultRouters: false, 1472 DiscoverOnLinkPrefixes: true, 1473 }, 1474 NDPDisp: &ndpDisp, 1475 }) 1476 1477 if err := s.CreateNIC(1, e); err != nil { 1478 t.Fatalf("CreateNIC(1) = %s", err) 1479 } 1480 1481 optSer := make(header.NDPOptionsSerializer, stack.MaxDiscoveredOnLinkPrefixes+2) 1482 expectedRt := [stack.MaxDiscoveredOnLinkPrefixes]tcpip.Route{} 1483 prefixes := [stack.MaxDiscoveredOnLinkPrefixes + 2]tcpip.Subnet{} 1484 1485 // Receive an RA with 2 more than the max number of discovered on-link 1486 // prefixes. 1487 for i := 0; i < stack.MaxDiscoveredOnLinkPrefixes+2; i++ { 1488 prefixAddr := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0} 1489 prefixAddr[7] = byte(i) 1490 prefix := tcpip.AddressWithPrefix{ 1491 Address: tcpip.Address(prefixAddr[:]), 1492 PrefixLen: 64, 1493 } 1494 prefixes[i] = prefix.Subnet() 1495 buf := [30]byte{} 1496 buf[0] = uint8(prefix.PrefixLen) 1497 buf[1] = 128 1498 binary.BigEndian.PutUint32(buf[2:], 10) 1499 copy(buf[14:], prefix.Address) 1500 1501 optSer[i] = header.NDPPrefixInformation(buf[:]) 1502 1503 if i < stack.MaxDiscoveredOnLinkPrefixes { 1504 expectedRt[i] = tcpip.Route{prefixes[i], tcpip.Address([]byte(nil)), 1} 1505 } 1506 } 1507 1508 e.InjectInbound(header.IPv6ProtocolNumber, raBufWithOpts(llAddr1, 0, optSer)) 1509 for i := 0; i < stack.MaxDiscoveredOnLinkPrefixes+2; i++ { 1510 if i < stack.MaxDiscoveredOnLinkPrefixes { 1511 select { 1512 case r := <-ndpDisp.prefixC: 1513 if r.nicID != 1 { 1514 t.Fatalf("got r.nicID = %d, want = 1", r.nicID) 1515 } 1516 if r.prefix != prefixes[i] { 1517 t.Fatalf("got r.prefix = %s, want = %s", r.prefix, prefixes[i]) 1518 } 1519 if !r.discovered { 1520 t.Fatal("got r.discovered = false, want = true") 1521 } 1522 case <-time.After(defaultTimeout): 1523 t.Fatal("timeout waiting for prefix discovery event") 1524 } 1525 } else { 1526 select { 1527 case <-ndpDisp.prefixC: 1528 t.Fatal("should not have discovered a new prefix after we already discovered the max number of prefixes") 1529 case <-time.After(defaultTimeout): 1530 } 1531 } 1532 } 1533 1534 // Should only have device routes for the first 1535 // stack.MaxDiscoveredOnLinkPrefixes discovered on-link prefixes. 1536 if got := s.GetRouteTable(); !cmp.Equal(got, expectedRt[:]) { 1537 t.Fatalf("got GetRouteTable = %v, want = %v", got, expectedRt) 1538 } 1539 }