]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Implement EBGP-OAD peering type 14537/head
authorDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 6 Oct 2023 11:51:18 +0000 (14:51 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 6 Oct 2023 18:53:43 +0000 (21:53 +0300)
At each EBGP boundary, BGP path attributes are modified as per [RFC4271], which includes stripping any IBGP-only attributes.

Some networks span more than one autonomous system and require more flexibility in the propagation of path attributes. It is worth noting that these multi-AS networks have a common or single administrative entity. These networks are said to belong to One Administrative Domain (OAD). It is desirable to carry IBGP-only attributes across EBGP peerings when the peers belong to an OAD.

This document defines a new EBGP peering type known as EBGP-OAD, which is used between two EBGP peers that belong to an OAD. This document also defines rules for route announcement and processing for EBGP-OAD peers.

https://datatracker.ietf.org/doc/html/draft-uttaro-idr-bgp-oad

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_attr.c
bgpd/bgp_route.c
bgpd/bgp_updgrp.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 808b98e41998f80315b684221f65a1c122a4e74d..21736dfb833b64e617abf32b6a0dcbda9f7c9c92 100644 (file)
@@ -1952,7 +1952,9 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
         * UPDATE message SHALL be handled using the approach of "treat-as-
         * withdraw".
         */
-       if (peer->sort == BGP_PEER_IBGP && length != 4) {
+       if ((peer->sort == BGP_PEER_IBGP ||
+            peer->sub_sort == BGP_PEER_EBGP_OAD) &&
+           length != 4) {
                flog_err(EC_BGP_ATTR_LEN,
                         "LOCAL_PREF attribute length isn't 4 [%u]", length);
                return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
@@ -1962,7 +1964,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
        /* If it is contained in an UPDATE message that is received from an
           external peer, then this attribute MUST be ignored by the
           receiving speaker. */
-       if (peer->sort == BGP_PEER_EBGP) {
+       if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD) {
                STREAM_FORWARD_GETP(peer->curr, length);
                return BGP_ATTR_PARSE_PROCEED;
        }
@@ -3380,7 +3382,8 @@ static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
         * the default value of AIGP_SESSION SHOULD be "enabled".
         */
        if (peer->sort == BGP_PEER_EBGP &&
-           !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
+           (!CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
+            peer->sub_sort != BGP_PEER_EBGP_OAD)) {
                zlog_warn(
                        "%pBP received AIGP attribute, but eBGP peer do not support it",
                        peer);
@@ -4639,7 +4642,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
        }
 
        /* Local preference. */
-       if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
+       if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
+           peer->sub_sort == BGP_PEER_EBGP_OAD) {
                stream_putc(s, BGP_ATTR_FLAG_TRANS);
                stream_putc(s, BGP_ATTR_LOCAL_PREF);
                stream_putc(s, 4);
@@ -5013,6 +5017,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
        /* AIGP */
        if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
            (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
+            peer->sub_sort == BGP_PEER_EBGP_OAD ||
             peer->sort != BGP_PEER_EBGP)) {
                /* At the moment only AIGP Metric TLV exists for AIGP
                 * attribute. If more comes in, do not forget to update
index 71b43c67568d2d83ba3310613b4df156db8ec57a..6cc27b98d48575eb53b955d958b2aed500213d6d 100644 (file)
@@ -2300,8 +2300,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
 
        /* Remove MED if its an EBGP peer - will get overwritten by route-maps
         */
-       if (peer->sort == BGP_PEER_EBGP
-           && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+       if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD &&
+           attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
                if (from != bgp->peer_self && !transparent
                    && !CHECK_FLAG(peer->af_flags[afi][safi],
                                   PEER_FLAG_MED_UNCHANGED))
@@ -2515,8 +2515,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
                return false;
 
        if (bgp_in_graceful_shutdown(bgp)) {
-               if (peer->sort == BGP_PEER_IBGP
-                   || peer->sort == BGP_PEER_CONFED) {
+               if (peer->sort == BGP_PEER_IBGP ||
+                   peer->sort == BGP_PEER_CONFED ||
+                   peer->sub_sort == BGP_PEER_EBGP_OAD) {
                        attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
                        attr->local_pref = BGP_GSHUT_LOCAL_PREF;
                } else {
index a2006c3508d4d0041114b4abe0727e2527e5feda..9eb4433c55178f3972c0efde7d06141355f3a2fc 100644 (file)
@@ -128,6 +128,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
 
        dst->bgp = src->bgp;
        dst->sort = src->sort;
+       dst->sub_sort = src->sub_sort;
        dst->as = src->as;
        dst->v_routeadv = src->v_routeadv;
        dst->flags = src->flags;
index 9b4d8936828a719e8278d55d980b9934e189200f..6bb42c8917c6d1a9b475286cd703b3d9abc7d004 100644 (file)
@@ -6985,6 +6985,28 @@ DEFPY(no_neighbor_role,
        return ret;
 }
 
+DEFPY (neighbor_oad,
+       neighbor_oad_cmd,
+       "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor oad",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set peering session type to EBGP-OAD\n")
+{
+       struct peer *peer;
+
+       peer = peer_and_group_lookup_vty(vty, neighbor);
+       if (!peer)
+               return CMD_WARNING_CONFIG_FAILED;
+
+       if (no)
+               peer->sub_sort = 0;
+       else if (peer->sort == BGP_PEER_EBGP)
+               peer->sub_sort = BGP_PEER_EBGP_OAD;
+
+       return CMD_SUCCESS;
+}
+
 /* disable-connected-check */
 DEFUN (neighbor_disable_connected_check,
        neighbor_disable_connected_check_cmd,
@@ -17971,6 +17993,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
                                ? " strict-mode"
                                : "");
 
+       if (peer->sub_sort == BGP_PEER_EBGP_OAD)
+               vty_out(vty, " neighbor %s oad\n", addr);
+
        /* ttl-security hops */
        if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED) {
                if (!peer_group_active(peer)
@@ -19557,6 +19582,9 @@ void bgp_vty_init(void)
        install_element(BGP_NODE, &neighbor_role_strict_cmd);
        install_element(BGP_NODE, &no_neighbor_role_cmd);
 
+       /* "neighbor oad" commands. */
+       install_element(BGP_NODE, &neighbor_oad_cmd);
+
        /* "neighbor aigp" commands. */
        install_element(BGP_NODE, &neighbor_aigp_cmd);
 
index e760d41587687417edea4e31dd07b5083b73258d..894ebaa84f0fcff41ac4c527e70038d8b36a0166 100644 (file)
@@ -3153,6 +3153,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
                        peer->as_type = group->conf->as_type;
                        peer->as = group->conf->as;
                        peer->sort = group->conf->sort;
+                       peer->sub_sort = group->conf->sub_sort;
                }
 
                ptype = peer_sort(peer);
index 8f78e33f6517bb8917e493b59b52e0459d4d3ce8..d324381080ba2512426fb98e89bb24fec44f07a0 100644 (file)
@@ -973,6 +973,14 @@ enum bgp_peer_sort {
        BGP_PEER_CONFED,
 };
 
+/* BGP peering sub-types
+ * E.g.:
+ * EBGP-OAD - https://datatracker.ietf.org/doc/html/draft-uttaro-idr-bgp-oad
+ */
+enum bgp_peer_sub_sort {
+       BGP_PEER_EBGP_OAD = 1,
+};
+
 /* BGP message header and packet size.  */
 #define BGP_MARKER_SIZE                                16
 #define BGP_HEADER_SIZE                                19
@@ -1199,6 +1207,7 @@ struct peer {
        as_t local_as;
 
        enum bgp_peer_sort sort;
+       enum bgp_peer_sub_sort sub_sort;
 
        /* Peer's Change local AS number. */
        as_t change_local_as;