]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: fix do not use srv6 SID for NHT when SID is ours
authorPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 14 Mar 2025 20:09:29 +0000 (21:09 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 24 Mar 2025 08:17:01 +0000 (09:17 +0100)
The resulting VPN prefix of a BGP route from a L3VPN in an srv6 setup
is not advertised to remote devices.

> r1# show bgp ipv6 vpn
> BGP table version is 2, local router ID is 1.1.1.1, vrf id 0
> Default local pref 100, local AS 65500
> Status codes:  s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
>                i internal, r RIB-failure, S Stale, R Removed
> Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
> Origin codes:  i - IGP, e - EGP, ? - incomplete
> RPKI validation codes: V valid, I invalid, N Not found
>
>      Network          Next Hop            Metric LocPrf Weight Path
> Route Distinguisher: 1:10
>      2011:1::/64      2001:1::2@6<             0    100      0 i
>     UN=2001:1::2 EC{99:99} label=4096 sid=2001:db8:1:1:: sid_structure=[40,24,8,0] type=bgp, subtype=5

What happens is that the SID of this BGP update is used as nexthop.
Consequently, the prefix is not valid because of nexthop unreachable.
obviously the locator prefix is not reachable in that L3VRF, and the
real nexthop 2001:1::2 should be used.

> r1# show bgp vrf vrf10 nexthop  detail
> Current BGP nexthop cache:
>  2001:db8:1:1:100:: invalid, #paths 1
>   Last update: Fri Mar 14 21:18:59 2025
>   Paths:
>     2/3 2011:1::/64 RD 1:10 VRF default flags 0x4000

Fix this by considering the SID of a given BGP update, only if the SID
is not ours.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_nht.c

index 268d8046995ed6c9cea87b466da82b5df48163a1..76ac6a5e9683b1023ff456c764cb0904bcc2fd26 100644 (file)
@@ -38,7 +38,8 @@ extern struct zclient *zclient;
 
 static void register_zebra_rnh(struct bgp_nexthop_cache *bnc);
 static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc);
-static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
+static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p,
+                       struct bgp *bgp_nexthop);
 static void bgp_nht_ifp_initial(struct event *thread);
 
 DEFINE_HOOK(bgp_nht_path_update, (struct bgp *bgp, struct bgp_path_info *pi, bool valid),
@@ -330,7 +331,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
 
                /* This will return true if the global IPv6 NH is a link local
                 * addr */
-               if (!make_prefix(afi, pi, &p))
+               if (!make_prefix(afi, pi, &p, bgp_nexthop))
                        return 1;
 
                /*
@@ -988,7 +989,7 @@ void bgp_cleanup_nexthops(struct bgp *bgp)
  * make_prefix - make a prefix structure from the path (essentially
  * path's node.
  */
-static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
+static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p, struct bgp *bgp_nexthop)
 {
 
        int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP)
@@ -1000,6 +1001,9 @@ static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
        struct in_addr ipv4;
        struct peer *peer = pi->peer;
        struct attr *attr = pi->attr;
+       bool local_sid = false;
+       struct bgp *bgp = bgp_get_default();
+       struct prefix_ipv6 tmp_prefix;
 
        if (p_orig->family == AF_FLOWSPEC) {
                if (!peer)
@@ -1029,7 +1033,20 @@ static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
                break;
        case AFI_IP6:
                p->family = AF_INET6;
-               if (attr->srv6_l3vpn) {
+               if (bgp && bgp->srv6_locator && bgp->srv6_enabled && attr->srv6_l3vpn) {
+                       tmp_prefix.family = AF_INET6;
+                       tmp_prefix.prefixlen = IPV6_MAX_BITLEN;
+                       tmp_prefix.prefix = attr->srv6_l3vpn->sid;
+                       if (bgp_nexthop->vpn_policy[afi].tovpn_sid_locator &&
+                           bgp_nexthop->vpn_policy[afi].tovpn_sid)
+                               local_sid = prefix_match(&bgp_nexthop->vpn_policy[afi]
+                                                                 .tovpn_sid_locator->prefix,
+                                                        &tmp_prefix);
+                       else if (bgp_nexthop->tovpn_sid_locator && bgp_nexthop->tovpn_sid)
+                               local_sid = prefix_match(&bgp_nexthop->tovpn_sid_locator->prefix,
+                                                        &tmp_prefix);
+               }
+               if (local_sid == false && attr->srv6_l3vpn) {
                        p->prefixlen = IPV6_MAX_BITLEN;
                        if (attr->srv6_l3vpn->transposition_len != 0 &&
                            BGP_PATH_INFO_NUM_LABELS(pi)) {