]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Add an ability to disable link-local capability per peer
authorDonatas Abraitis <donatas@opensourcerouting.org>
Tue, 11 Feb 2025 13:24:12 +0000 (15:24 +0200)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Tue, 11 Feb 2025 15:01:56 +0000 (17:01 +0200)
Even if we have unnumbered peering, let's respect `no neighbor X capability link-local`
and disable it per-neighbor on demand.

Fixes: db853cc97eafee8742cd391aaa2b5bc58a6751ae ("bgpd: Implement Link-Local Next Hop capability")
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_attr.c
bgpd/bgp_nht.c
bgpd/bgp_route.c
bgpd/bgp_updgrp_packet.c
bgpd/bgpd.h

index 1a7d0e75689c60bdfba7fb139777f3a074761567..f280add12aa41733f1b8d38c0256c51ad95d9e4e 100644 (file)
@@ -2450,8 +2450,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                        if (!peer->nexthop.ifp) {
                                zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
                                          peer->host);
-                               if (CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                                   CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV))
+                               if (PEER_HAS_LINK_LOCAL_CAPABILITY(peer))
                                        bgp_notify_send(peer->connection, BGP_NOTIFY_UPDATE_ERR,
                                                        BGP_NOTIFY_UPDATE_UNREACH_NEXT_HOP);
                                return BGP_ATTR_PARSE_WITHDRAW;
@@ -4215,8 +4214,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                                           IPV6_MAX_BYTELEN);
                        } else {
                                stream_putc(s, IPV6_MAX_BYTELEN);
-                               if (CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                                   CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV))
+                               if (PEER_HAS_LINK_LOCAL_CAPABILITY(peer))
                                        stream_put(s, &attr->mp_nexthop_local, IPV6_MAX_BYTELEN);
                                else
                                        stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
index c8e15372b60b87c8a737a9961479f7c1cab86834..3be6ee48b881c1a687aa9dc7afeb8d7a17e3f7ef 100644 (file)
@@ -1102,8 +1102,7 @@ static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
                                /* If we receive MP_REACH with GUA as LL, we should
                                 * check if we have Link-Local Next Hop capability also.
                                 */
-                               if (!(CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                                     CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV))) {
+                               if (!PEER_HAS_LINK_LOCAL_CAPABILITY(peer)) {
                                        zlog_warn("%s: received IPv6 global next-hop as Link-Local, but no capability exchanged",
                                                  __func__);
                                        p->u.prefix6 = attr->mp_nexthop_global;
index c54d28b0919dbb77c9042eaf1a351e77c336209e..3b8469d5eeac72cec043fc4b6938a71e70340c61 100644 (file)
@@ -2512,8 +2512,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                         * length of the Next Hop field to 16 and include only the IPv6 link-local
                         * address in the Next Hop field.
                         */
-                       if (!(CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                             CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV)))
+                       if (!PEER_HAS_LINK_LOCAL_CAPABILITY(peer))
                                global_and_ll = true;
                }
 
@@ -9728,8 +9727,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                bgp_nexthop_hostname(path->peer, path->nexthop);
        char esi_buf[ESI_STR_LEN];
        bool ll_nexthop_only = attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL &&
-                              !!CHECK_FLAG(path->peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                              !!CHECK_FLAG(path->peer->cap, PEER_CAP_LINK_LOCAL_RCV);
+                              PEER_HAS_LINK_LOCAL_CAPABILITY(path->peer);
 
        if (json_paths)
                json_path = json_object_new_object();
@@ -10842,8 +10840,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
                bgp_get_imported_bpi_ultimate(path);
        struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr);
        bool ll_nexthop_only = attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL &&
-                              !!CHECK_FLAG(path->peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                              !!CHECK_FLAG(path->peer->cap, PEER_CAP_LINK_LOCAL_RCV);
+                              PEER_HAS_LINK_LOCAL_CAPABILITY(path->peer);
 
        if (json_paths) {
                json_path = json_object_new_object();
index 4b25aeb727665b96263e849b8295686bba31ac96..23f2340bb350bafc2052c10e10996d12ee5eb34c 100644 (file)
@@ -447,8 +447,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
                int gnh_modified, lnh_modified;
                size_t offset_nhglobal = vec->offset + 1;
                size_t offset_nhlocal = vec->offset + 1;
-               bool ll_nexthop_only = !!CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
-                                      !!CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV);
+               bool ll_nexthop_only = PEER_HAS_LINK_LOCAL_CAPABILITY(peer);
 
                gnh_modified = lnh_modified = 0;
                mod_v6nhg = &v6nhglobal;
@@ -538,8 +537,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
                }
 
                if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL ||
-                   nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ||
-                   (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL && ll_nexthop_only)) {
+                   nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL || ll_nexthop_only) {
                        stream_get_from(&v6nhlocal, s, offset_nhlocal,
                                        IPV6_MAX_BYTELEN);
                        if (IN6_IS_ADDR_UNSPECIFIED(&v6nhlocal)) {
@@ -559,8 +557,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
 
                if (bgp_debug_update(peer, NULL, NULL, 0)) {
                        if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL ||
-                           nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ||
-                           (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL && ll_nexthop_only))
+                           nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL || ll_nexthop_only)
                                zlog_debug(
                                        "u%" PRIu64 ":s%" PRIu64
                                        " %s send UPDATE w/ mp_nexthops %pI6, %pI6%s",
index d02c1c924deb56fd0bdea0079e7379d3a7da3647..d331adff886f2bfd33aaac07277ad2e237d76700 100644 (file)
@@ -2921,4 +2921,9 @@ extern void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode);
         !(_afi == AFI_IP && _safi == SAFI_MPLS_VPN) &&                        \
         !(_afi == AFI_IP6 && _safi == SAFI_MPLS_VPN))
 
+#define PEER_HAS_LINK_LOCAL_CAPABILITY(_peer)                                                      \
+       (CHECK_FLAG(_peer->flags, PEER_FLAG_CAPABILITY_LINK_LOCAL) &&                              \
+        CHECK_FLAG(_peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&                                        \
+        CHECK_FLAG(_peer->cap, PEER_CAP_LINK_LOCAL_RCV))
+
 #endif /* _QUAGGA_BGPD_H */