]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: stop removing and replacing private asn if it matches the peer 4750/head
authorDon Slice <dslice@cumulusnetworks.com>
Thu, 25 Jul 2019 15:35:06 +0000 (11:35 -0400)
committerDon Slice <dslice@cumulusnetworks.com>
Mon, 29 Jul 2019 19:27:03 +0000 (12:27 -0700)
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>
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_route.c

index 05577cb8bdb0779847fd7f04d321dc5398d9bbad..cf0d28887e52f2c8e3a6b9c4d88c2593e408e655 100644 (file)
@@ -1232,7 +1232,8 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
 }
 
 /* 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 assegment *seg;
@@ -1244,7 +1245,9 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
                int 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 = seg->next;
@@ -1255,7 +1258,7 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn)
 }
 
 /* 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 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
-               else if (public == seg->length) {
+               if (public == seg->length)
                        new_seg = assegment_dup(seg);
-               }
 
                // The segment is a mix of public and private ASNs. Copy as many
                // spots as
@@ -1301,8 +1297,9 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath)
                        new_seg = assegment_new(seg->type, public);
                        j = 0;
                        for (i = 0; i < seg->length; i++) {
-                               // ASN is public
-                               if (!BGP_AS_IS_PRIVATE(seg->as[i])) {
+                               // keep ASN if public or matches peer's ASN
+                               if (!BGP_AS_IS_PRIVATE(seg->as[i])
+                                   || (seg->as[i] == peer_asn)) {
                                        new_seg->as[j] = seg->as[i];
                                        j++;
                                }
index 6f3d94cdb3f948c68f826626085a88faea2eca32..f84b3740c96d3a850de6b4221f0e0060de363620 100644 (file)
@@ -112,8 +112,9 @@ extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
                                                  as_t target_asn,
                                                  as_t our_asn);
 extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
-                                                 as_t asn);
-extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
+                                                 as_t asn, as_t peer_asn);
+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_confed_check(struct aspath *);
 extern int aspath_left_confed_check(struct aspath *);
index aa02cc3c63cae7fad3a7f7f65506d3f54efae48a..51c50f710e1d652e139daae24bbdb880304690ff 100644 (file)
@@ -1366,7 +1366,7 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
                                    peer, afi, safi,
                                    PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
                                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
                        // 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
                        else
                                attr->aspath = aspath_remove_private_asns(
-                                       attr->aspath);
+                                       attr->aspath, peer->as);
                }
 
                // '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_FLAG_REMOVE_PRIVATE_AS_REPLACE))
                                attr->aspath = aspath_replace_private_asns(
-                                       attr->aspath, bgp->as);
+                                       attr->aspath, bgp->as, peer->as);
                        else
                                attr->aspath = aspath_empty_get();
                }