mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +00:00
bgpd: stop removing and replacing private asn if it matches the peer
Problems reported that if multiple peers have "remove-private-AS replace-AS" with each other and all are using private asns, the as-path gets hosed and continues to grow when a prefix is removed. This fix disallows removing and replacing the private asn if it matches the peer's ASN so that normal as-path loop prevention will operate correctly. Ticket: CM-25489 Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
parent
a041a8fff2
commit
bf26b80eba
@ -1232,7 +1232,8 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Replace all private ASNs with our own ASN */
|
/* Replace all private ASNs with our own ASN */
|
||||||
struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
|
struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn,
|
||||||
|
as_t peer_asn)
|
||||||
{
|
{
|
||||||
struct aspath *new;
|
struct aspath *new;
|
||||||
struct assegment *seg;
|
struct assegment *seg;
|
||||||
@ -1244,7 +1245,9 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < seg->length; i++) {
|
for (i = 0; i < seg->length; i++) {
|
||||||
if (BGP_AS_IS_PRIVATE(seg->as[i]))
|
/* Don't replace if public ASN or peer's ASN */
|
||||||
|
if (BGP_AS_IS_PRIVATE(seg->as[i])
|
||||||
|
&& (seg->as[i] != peer_asn))
|
||||||
seg->as[i] = asn;
|
seg->as[i] = asn;
|
||||||
}
|
}
|
||||||
seg = seg->next;
|
seg = seg->next;
|
||||||
@ -1255,7 +1258,7 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all private ASNs */
|
/* Remove all private ASNs */
|
||||||
struct aspath *aspath_remove_private_asns(struct aspath *aspath)
|
struct aspath *aspath_remove_private_asns(struct aspath *aspath, as_t peer_asn)
|
||||||
{
|
{
|
||||||
struct aspath *new;
|
struct aspath *new;
|
||||||
struct assegment *seg;
|
struct assegment *seg;
|
||||||
@ -1282,16 +1285,9 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The entire segment is private so skip it
|
|
||||||
if (!public) {
|
|
||||||
seg = seg->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The entire segment is public so copy it
|
// The entire segment is public so copy it
|
||||||
else if (public == seg->length) {
|
if (public == seg->length)
|
||||||
new_seg = assegment_dup(seg);
|
new_seg = assegment_dup(seg);
|
||||||
}
|
|
||||||
|
|
||||||
// The segment is a mix of public and private ASNs. Copy as many
|
// The segment is a mix of public and private ASNs. Copy as many
|
||||||
// spots as
|
// spots as
|
||||||
@ -1301,8 +1297,9 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath)
|
|||||||
new_seg = assegment_new(seg->type, public);
|
new_seg = assegment_new(seg->type, public);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i = 0; i < seg->length; i++) {
|
for (i = 0; i < seg->length; i++) {
|
||||||
// ASN is public
|
// keep ASN if public or matches peer's ASN
|
||||||
if (!BGP_AS_IS_PRIVATE(seg->as[i])) {
|
if (!BGP_AS_IS_PRIVATE(seg->as[i])
|
||||||
|
|| (seg->as[i] == peer_asn)) {
|
||||||
new_seg->as[j] = seg->as[i];
|
new_seg->as[j] = seg->as[i];
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
@ -112,8 +112,9 @@ extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
|
|||||||
as_t target_asn,
|
as_t target_asn,
|
||||||
as_t our_asn);
|
as_t our_asn);
|
||||||
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
|
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
|
||||||
as_t asn);
|
as_t asn, as_t peer_asn);
|
||||||
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
|
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath,
|
||||||
|
as_t peer_asn);
|
||||||
extern int aspath_firstas_check(struct aspath *, as_t);
|
extern int aspath_firstas_check(struct aspath *, as_t);
|
||||||
extern int aspath_confed_check(struct aspath *);
|
extern int aspath_confed_check(struct aspath *);
|
||||||
extern int aspath_left_confed_check(struct aspath *);
|
extern int aspath_left_confed_check(struct aspath *);
|
||||||
|
@ -1366,7 +1366,7 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
peer, afi, safi,
|
peer, afi, safi,
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
|
||||||
attr->aspath = aspath_replace_private_asns(
|
attr->aspath = aspath_replace_private_asns(
|
||||||
attr->aspath, bgp->as);
|
attr->aspath, bgp->as, peer->as);
|
||||||
|
|
||||||
// The entire aspath consists of private ASNs so create
|
// The entire aspath consists of private ASNs so create
|
||||||
// an empty aspath
|
// an empty aspath
|
||||||
@ -1377,7 +1377,7 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
// the private ASNs
|
// the private ASNs
|
||||||
else
|
else
|
||||||
attr->aspath = aspath_remove_private_asns(
|
attr->aspath = aspath_remove_private_asns(
|
||||||
attr->aspath);
|
attr->aspath, peer->as);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'all' was not specified so the entire aspath must be private
|
// 'all' was not specified so the entire aspath must be private
|
||||||
@ -1388,7 +1388,7 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
peer, afi, safi,
|
peer, afi, safi,
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
|
||||||
attr->aspath = aspath_replace_private_asns(
|
attr->aspath = aspath_replace_private_asns(
|
||||||
attr->aspath, bgp->as);
|
attr->aspath, bgp->as, peer->as);
|
||||||
else
|
else
|
||||||
attr->aspath = aspath_empty_get();
|
attr->aspath = aspath_empty_get();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user