From: Donatas Abraitis Date: Tue, 11 Feb 2025 13:24:12 +0000 (+0200) Subject: bgpd: Add an ability to disable link-local capability per peer X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=ca24f56a5c0e1cede41ff6d66bbb1326707f571f;p=mirror%2Ffrr.git bgpd: Add an ability to disable link-local capability per peer 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 --- diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 1a7d0e7568..f280add12a 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -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); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index c8e15372b6..3be6ee48b8 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -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; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c54d28b091..3b8469d5ee 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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(); diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 4b25aeb727..23f2340bb3 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -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", diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index d02c1c924d..d331adff88 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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 */