]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Pass global ASN for confederation peers if not AS_SPECIFIED
authorDonatas Abraitis <donatas@opensourcerouting.org>
Tue, 21 Feb 2023 21:10:45 +0000 (23:10 +0200)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Wed, 22 Feb 2023 17:25:35 +0000 (17:25 +0000)
When we specify remote-as as external/internal, we need to set local_as to
bgp->as, instead of bgp->confed_id. Before this patch, (bgp->as != *as) is
always valid for such a case because *as is always 0.

Also, append peer->local_as as CONFED_SEQ to avoid other side withdrawing
the routes due to confederation own AS received and/or malformed as-path.

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
(cherry picked from commit db5a5ee6e4665b5f951ed2a37398820da4b762f1)

bgpd/bgp_attr.c
bgpd/bgpd.c

index 59ccf30a84ef6184ae6e1322b7ca53a834dbf6bf..00a194f5c6e9ac08c7d4ee96f64a68453acac3fb 100644 (file)
@@ -1655,6 +1655,14 @@ static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
         */
        struct aspath *aspath;
 
+       /* Refresh peer's type. If we set e.g.: AS_EXTERNAL/AS_INTERNAL,
+        * then peer->sort remains BGP_PEER_EBGP/IBGP, hence we need to
+        * have an actual type before checking.
+        * This is especially a case for BGP confederation peers, to avoid
+        * receiving and treating AS_PATH as malformed.
+        */
+       (void)peer_sort(peer);
+
        /* Confederation sanity check. */
        if ((peer->sort == BGP_PEER_CONFED
             && !aspath_left_confed_check(attr->aspath))
@@ -4347,8 +4355,22 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
                aspath = aspath_delete_confed_seq(aspath);
 
                if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
-                       /* Stuff our path CONFED_ID on the front */
-                       aspath = aspath_add_seq(aspath, bgp->confed_id);
+                       /* A confed member, so we need to do the
+                        * AS_CONFED_SEQUENCE thing if it's outside a common
+                        * administration.
+                        * Configured confederation peers MUST be validated
+                        * under BGP_PEER_CONFED, but if we have configured
+                        * remote-as as AS_EXTERNAL, we need to check again
+                        * if the peer belongs to us.
+                        */
+                       if (bgp_confederation_peers_check(bgp, peer->as)) {
+                               aspath = aspath_dup(attr->aspath);
+                               aspath = aspath_add_confed_seq(aspath,
+                                                              peer->local_as);
+                       } else {
+                               /* Stuff our path CONFED_ID on the front */
+                               aspath = aspath_add_seq(aspath, bgp->confed_id);
+                       }
                } else {
                        if (peer->change_local_as) {
                                /* If replace-as is specified, we only use the
index 39010e76f9d1bd164336aa29564af93b72fe9221..a24c75d0a5caf4dd477eb99c24e797b3820707a8 100644 (file)
@@ -2027,9 +2027,9 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
 
                /* If the peer is not part of our confederation, and its not an
                   iBGP peer then spoof the source AS */
-               if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)
-                   && !bgp_confederation_peers_check(bgp, *as)
-                   && bgp->as != *as)
+               if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION) &&
+                   !bgp_confederation_peers_check(bgp, *as) && *as &&
+                   bgp->as != *as)
                        local_as = bgp->confed_id;
                else
                        local_as = bgp->as;