bgpd: Send LL only if LL Next Hop capability is negotiated

If we have LL Next Hop capability exchanged, we should send LL-only as 16-bytes
NH instead of a GUA (global unicast).

Fixes: db853cc97e ("bgpd: Implement Link-Local Next Hop capability")

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
Donatas Abraitis 2025-02-11 10:19:20 +02:00
parent c91c5e8463
commit 0050f82b8d
2 changed files with 20 additions and 9 deletions

View File

@ -4215,8 +4215,11 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
IPV6_MAX_BYTELEN); IPV6_MAX_BYTELEN);
} else { } else {
stream_putc(s, IPV6_MAX_BYTELEN); stream_putc(s, IPV6_MAX_BYTELEN);
stream_put(s, &attr->mp_nexthop_global, if (CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_ADV) &&
IPV6_MAX_BYTELEN); CHECK_FLAG(peer->cap, PEER_CAP_LINK_LOCAL_RCV))
stream_put(s, &attr->mp_nexthop_local, IPV6_MAX_BYTELEN);
else
stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
} }
} break; } break;
case SAFI_MPLS_VPN: { case SAFI_MPLS_VPN: {

View File

@ -447,6 +447,8 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
int gnh_modified, lnh_modified; int gnh_modified, lnh_modified;
size_t offset_nhglobal = vec->offset + 1; size_t offset_nhglobal = vec->offset + 1;
size_t offset_nhlocal = 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);
gnh_modified = lnh_modified = 0; gnh_modified = lnh_modified = 0;
mod_v6nhg = &v6nhglobal; mod_v6nhg = &v6nhglobal;
@ -535,8 +537,9 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
gnh_modified = 1; gnh_modified = 1;
} }
if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL ||
|| nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) { nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ||
(nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL && ll_nexthop_only)) {
stream_get_from(&v6nhlocal, s, offset_nhlocal, stream_get_from(&v6nhlocal, s, offset_nhlocal,
IPV6_MAX_BYTELEN); IPV6_MAX_BYTELEN);
if (IN6_IS_ADDR_UNSPECIFIED(&v6nhlocal)) { if (IN6_IS_ADDR_UNSPECIFIED(&v6nhlocal)) {
@ -545,14 +548,19 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
} }
} }
if (lnh_modified && ll_nexthop_only) {
stream_put_in6_addr_at(s, offset_nhlocal, mod_v6nhl);
} else {
if (gnh_modified) if (gnh_modified)
stream_put_in6_addr_at(s, offset_nhglobal, mod_v6nhg); stream_put_in6_addr_at(s, offset_nhglobal, mod_v6nhg);
if (lnh_modified) if (lnh_modified)
stream_put_in6_addr_at(s, offset_nhlocal, mod_v6nhl); stream_put_in6_addr_at(s, offset_nhlocal, mod_v6nhl);
}
if (bgp_debug_update(peer, NULL, NULL, 0)) { if (bgp_debug_update(peer, NULL, NULL, 0)) {
if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL ||
|| nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ||
(nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL && ll_nexthop_only))
zlog_debug( zlog_debug(
"u%" PRIu64 ":s%" PRIu64 "u%" PRIu64 ":s%" PRIu64
" %s send UPDATE w/ mp_nexthops %pI6, %pI6%s", " %s send UPDATE w/ mp_nexthops %pI6, %pI6%s",