(t *testing.T)
| 643 | } |
| 644 | |
| 645 | func TestRouter_BackupRouteOverridesHeldRoute(t *testing.T) { |
| 646 | tunables := ConfigureConstants() |
| 647 | // Topology: |
| 648 | // A --(1)-- C |
| 649 | // A --(1)-- B --(10)-- C |
| 650 | // Initially A prefers A-C path. |
| 651 | // When A-C fails, A should be starved, request a seqno, and then switch to A-B-C. |
| 652 | |
| 653 | h := &RouterHarness{} |
| 654 | cPrefix := nodeToPrefix("C") |
| 655 | rs := &state.RouterState{ |
| 656 | RouterTunables: tunables, |
| 657 | Id: "A", |
| 658 | SelfSeqno: make(map[netip.Prefix]uint16), |
| 659 | Routes: make(map[netip.Prefix]state.SelRoute), |
| 660 | Sources: make(map[state.Source]state.FD), |
| 661 | Neighbours: MakeNeighbours("B", "C"), |
| 662 | Advertised: map[netip.Prefix]state.Advertisement{nodeToPrefix("A"): {NodeId: state.NodeId("A"), Expiry: maxTime}}, |
| 663 | } |
| 664 | |
| 665 | AC := AddLink(rs, NewMockEndpoint("C", 1)) |
| 666 | _ = AddLink(rs, NewMockEndpoint("B", 1)) |
| 667 | |
| 668 | // C's advertisement via direct link |
| 669 | h.NeighUpdate(rs, "C", "C", cPrefix, 0, 0) |
| 670 | // B's advertisement of C (cost 10). This is initially UNFEASIBLE because 10 > 1 (current FD). |
| 671 | h.NeighUpdate(rs, "B", "C", cPrefix, 0, 10) |
| 672 | |
| 673 | ComputeRoutes(rs, h) |
| 674 | |
| 675 | // Initially A prefers C via direct link |
| 676 | assert.Equal(t, "C", string(rs.Routes[cPrefix].Nh)) |
| 677 | assert.Equal(t, uint32(1), rs.Routes[cPrefix].Metric) |
| 678 | |
| 679 | // Now AC link goes down |
| 680 | RemoveLink(rs, AC) |
| 681 | ComputeRoutes(rs, h) |
| 682 | |
| 683 | // A-C route should be retracted and held as INF |
| 684 | assert.Equal(t, state.INF, rs.Routes[cPrefix].Metric) |
| 685 | |
| 686 | // A should realize it's starved and request a higher seqno |
| 687 | SolveStarvation(rs, h) |
| 688 | h.GetActions().AssertContains(t, BroadcastRequestSeqno(state.Source{NodeId: "C", Prefix: cPrefix}, uint16(1), uint8(64))) |
| 689 | |
| 690 | // Now B advertises C with the higher seqno (1). This is now FEASIBLE. |
| 691 | h.NeighUpdate(rs, "B", "C", cPrefix, 1, 10) |
| 692 | ComputeRoutes(rs, h) |
| 693 | |
| 694 | // A should now successfully switch to B |
| 695 | assert.Equal(t, "B", string(rs.Routes[cPrefix].Nh)) |
| 696 | assert.Equal(t, uint32(11), rs.Routes[cPrefix].Metric) |
| 697 | } |
| 698 | |
| 699 | func TestRouter_RetractedByClearedWhenHeldRouteRecovers(t *testing.T) { |
| 700 | tunables := ConfigureConstants() |
nothing calls this directly
no test coverage detected