From 4c62dacd66a8e81c5d149d85f6eb0eedd1ab3017 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Wed, 29 Oct 2025 10:36:39 +0100 Subject: [PATCH] fix(#3214): tablemanager use link-local nexthop if global is unspecified --- internal/pkg/table/table_manager.go | 4 ++++ internal/pkg/table/table_manager_test.go | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/internal/pkg/table/table_manager.go b/internal/pkg/table/table_manager.go index ea91125bd..8d14bdf48 100644 --- a/internal/pkg/table/table_manager.go +++ b/internal/pkg/table/table_manager.go @@ -90,6 +90,10 @@ func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time, nexthop := reach.Nexthop family := bgp.NewFamily(reach.AFI, reach.SAFI) + if nexthop.IsUnspecified() && reach.LinkLocalNexthop.IsValid() && !reach.LinkLocalNexthop.IsUnspecified() { + nexthop = reach.LinkLocalNexthop + } + for _, nlri := range reach.Value { // when build path from reach // reachAttrs might not contain next_hop if `attrs` does not have one diff --git a/internal/pkg/table/table_manager_test.go b/internal/pkg/table/table_manager_test.go index bd1725701..b323d9f9c 100644 --- a/internal/pkg/table/table_manager_test.go +++ b/internal/pkg/table/table_manager_test.go @@ -1476,6 +1476,29 @@ func TestProcessBGPUpdate_8_mpunreach_path_ipv6(t *testing.T) { assert.Equal(t, expectedNexthop, path.GetNexthop().String()) } +func TestProcessBGPUpdate_select_linklocal_nexthop_over_unspecified_global(t *testing.T) { + tm := NewTableManager(logger, []bgp.Family{bgp.RF_IPv6_UC}) + + origin1 := bgp.NewPathAttributeOrigin(0) + aspath1 := createAsPathAttribute([]uint32{65000}) + nlri1, _ := bgp.NewIPAddrPrefix(netip.MustParsePrefix("2001:123:123:1::/64")) + mpReach1, _ := bgp.NewPathAttributeMpReachNLRI(bgp.RF_IPv6_UC, []bgp.PathNLRI{{NLRI: nlri1}}, netip.MustParseAddr("::"), netip.MustParseAddr("fe80::ade0")) + med1 := bgp.NewPathAttributeMultiExitDisc(200) + localpref1 := bgp.NewPathAttributeLocalPref(100) + + pathAttributes1 := []bgp.PathAttributeInterface{ + mpReach1, origin1, aspath1, med1, localpref1, + } + + bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil) + + peer1 := peerR1() + pList, err := tm.ProcessUpdate(peer1, bgpMessage1) + assert.Equal(t, 1, len(pList)) + assert.Equal(t, pList[0].GetNexthop(), netip.MustParseAddr("fe80::ade0")) + assert.NoError(t, err) +} + // handle bestpath lost func TestProcessBGPUpdate_bestpath_lost_ipv4(t *testing.T) { tm := NewTableManager(logger, []bgp.Family{bgp.RF_IPv4_UC})