mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 10:04:18 +00:00
bgpd: Rework extended community transitiviness
Extended communities can be transitive or non-transitive. Like other attributes (e.g., MED) non-transitive extended communities SHOULD be sent to the direct peer, but not forward them to eBGP peers next. Before this patch, we never send non-transitive extended attributes to the direct peers at all. Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
This commit is contained in:
parent
5ca4656ad7
commit
b4e72bc198
@ -4482,66 +4482,22 @@ static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
|
||||
}
|
||||
|
||||
static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer,
|
||||
struct ecommunity *ecomm,
|
||||
bool transparent, int attribute)
|
||||
struct ecommunity *ecomm, int attribute)
|
||||
{
|
||||
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
|
||||
peer->sub_sort == BGP_PEER_EBGP_OAD || transparent) {
|
||||
if (ecomm->size * ecomm->unit_size > 255) {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||
BGP_ATTR_FLAG_TRANS |
|
||||
BGP_ATTR_FLAG_EXTLEN);
|
||||
stream_putc(s, attribute);
|
||||
stream_putw(s, ecomm->size * ecomm->unit_size);
|
||||
} else {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||
BGP_ATTR_FLAG_TRANS);
|
||||
stream_putc(s, attribute);
|
||||
stream_putc(s, ecomm->size * ecomm->unit_size);
|
||||
}
|
||||
stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size);
|
||||
if (!ecomm || !ecomm->size)
|
||||
return;
|
||||
|
||||
if (ecomm->size * ecomm->unit_size > 255) {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
|
||||
stream_putc(s, attribute);
|
||||
stream_putw(s, ecomm->size * ecomm->unit_size);
|
||||
} else {
|
||||
uint8_t *pnt;
|
||||
int tbit;
|
||||
int ecom_tr_size = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < ecomm->size; i++) {
|
||||
pnt = ecomm->val + (i * ecomm->unit_size);
|
||||
tbit = *pnt;
|
||||
|
||||
if (CHECK_FLAG(tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
||||
continue;
|
||||
|
||||
ecom_tr_size++;
|
||||
}
|
||||
|
||||
if (ecom_tr_size) {
|
||||
if (ecom_tr_size * ecomm->unit_size > 255) {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||
BGP_ATTR_FLAG_TRANS |
|
||||
BGP_ATTR_FLAG_EXTLEN);
|
||||
stream_putc(s, attribute);
|
||||
stream_putw(s, ecom_tr_size * ecomm->unit_size);
|
||||
} else {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
|
||||
BGP_ATTR_FLAG_TRANS);
|
||||
stream_putc(s, attribute);
|
||||
stream_putc(s, ecom_tr_size * ecomm->unit_size);
|
||||
}
|
||||
|
||||
for (i = 0; i < ecomm->size; i++) {
|
||||
pnt = ecomm->val + (i * ecomm->unit_size);
|
||||
tbit = *pnt;
|
||||
|
||||
if (CHECK_FLAG(tbit,
|
||||
ECOMMUNITY_FLAG_NON_TRANSITIVE))
|
||||
continue;
|
||||
|
||||
stream_put(s, pnt, ecomm->unit_size);
|
||||
}
|
||||
}
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
|
||||
stream_putc(s, attribute);
|
||||
stream_putc(s, ecomm->size * ecomm->unit_size);
|
||||
}
|
||||
|
||||
stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size);
|
||||
}
|
||||
|
||||
/* Make attribute packet. */
|
||||
@ -4848,19 +4804,11 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct strea
|
||||
|
||||
/* Extended IPv6/Communities attributes. */
|
||||
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) {
|
||||
bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
|
||||
PEER_FLAG_RSERVER_CLIENT) &&
|
||||
from &&
|
||||
CHECK_FLAG(from->af_flags[afi][safi],
|
||||
PEER_FLAG_RSERVER_CLIENT);
|
||||
|
||||
if (CHECK_FLAG(attr->flag,
|
||||
ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
|
||||
struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
|
||||
|
||||
bgp_packet_ecommunity_attribute(s, peer, ecomm,
|
||||
transparent,
|
||||
BGP_ATTR_EXT_COMMUNITIES);
|
||||
bgp_packet_ecommunity_attribute(s, peer, ecomm, BGP_ATTR_EXT_COMMUNITIES);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(attr->flag,
|
||||
@ -4869,7 +4817,6 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct strea
|
||||
bgp_attr_get_ipv6_ecommunity(attr);
|
||||
|
||||
bgp_packet_ecommunity_attribute(s, peer, ecomm,
|
||||
transparent,
|
||||
BGP_ATTR_IPV6_EXT_COMMUNITIES);
|
||||
}
|
||||
}
|
||||
|
@ -2836,6 +2836,50 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
|
||||
}
|
||||
}
|
||||
|
||||
/* Extended communities can be transitive and non-transitive.
|
||||
* If the extended community is non-transitive, strip it off,
|
||||
* unless it's a locally originated route (static, aggregate,
|
||||
* redistributed, etc.).
|
||||
*/
|
||||
if (from->sort == BGP_PEER_EBGP && peer->sort == BGP_PEER_EBGP &&
|
||||
pi->sub_type == BGP_ROUTE_NORMAL) {
|
||||
struct ecommunity *new_ecomm;
|
||||
struct ecommunity *old_ecomm;
|
||||
|
||||
old_ecomm = bgp_attr_get_ecommunity(attr);
|
||||
if (old_ecomm) {
|
||||
new_ecomm = ecommunity_dup(old_ecomm);
|
||||
if (ecommunity_strip_non_transitive(new_ecomm)) {
|
||||
bgp_attr_set_ecommunity(attr, new_ecomm);
|
||||
if (!old_ecomm->refcnt)
|
||||
ecommunity_free(&old_ecomm);
|
||||
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
|
||||
zlog_debug("%pBP: %pFX stripped non-transitive extended communities",
|
||||
peer, p);
|
||||
} else {
|
||||
ecommunity_free(&new_ecomm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extended link-bandwidth communities are encoded as IPv6
|
||||
* address-specific extended communities.
|
||||
*/
|
||||
old_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
|
||||
if (old_ecomm) {
|
||||
new_ecomm = ecommunity_dup(old_ecomm);
|
||||
if (ecommunity_strip_non_transitive(new_ecomm)) {
|
||||
bgp_attr_set_ipv6_ecommunity(attr, new_ecomm);
|
||||
if (!old_ecomm->refcnt)
|
||||
ecommunity_free(&old_ecomm);
|
||||
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
|
||||
zlog_debug("%pBP: %pFX stripped non-transitive ipv6 extended communities",
|
||||
peer, p);
|
||||
} else {
|
||||
ecommunity_free(&new_ecomm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user