]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Announce cumulative link bandwidth to EBGP peers
authorvivek <vivek@cumulusnetworks.com>
Tue, 24 Mar 2020 21:25:56 +0000 (14:25 -0700)
committervivek <vivek@cumulusnetworks.com>
Tue, 31 Mar 2020 03:12:31 +0000 (20:12 -0700)
When announcing ourselves as the next hop (e.g., to EBGP peers), if the
best path has the link bandwidth extended community and it is transitive,
change the value of the link bandwidth to the cumulative downstream
bandwidth (sum of the link bandwidths of all our multipaths) as this
makes the most sense. It is also implied by
https://tools.ietf.org/html/draft-mohanty-bess-ebgp-dmz. Of course, do
not override the link bandwidth if it has been specified by policy.

Note: Transitive extended communities will be automatically passed along
to EBGP peers; this commit is updating the value that is announced to
something that is the most appropriate.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
bgpd/bgp_attr.h
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h
bgpd/bgp_route.c
bgpd/bgp_routemap.c

index 5fec4be29c467b5e19b101181902ce01bfe03961..a6964c465320c8223500072b123036d20e6f5927 100644 (file)
@@ -263,6 +263,7 @@ struct attr {
 #define BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED (1 << 4)
 #define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5)
 #define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
+#define BATTR_RMAP_LINK_BW_SET (1 << 7)
 
 /* Router Reflector related structure. */
 struct cluster_list {
index 0fbbc885b964d9029679e34da7c99e6cdbec26d7..1ab59e62cbe9ac390675327396dc971beaa1d5fb 100644 (file)
@@ -1268,3 +1268,44 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
 
        return NULL;
 }
+
+
+struct ecommunity *ecommunity_replace_linkbw(as_t as,
+                                            struct ecommunity *ecom,
+                                            uint64_t cum_bw)
+{
+       struct ecommunity *new;
+       struct ecommunity_val lb_eval;
+       const uint8_t *eval;
+       uint8_t type;
+       uint32_t cur_bw;
+
+       /* Nothing to replace if link-bandwidth doesn't exist or
+        * is non-transitive - just return existing extcommunity.
+        */
+       new = ecom;
+       if (!ecom || !ecom->size)
+               return new;
+
+       eval = ecommunity_linkbw_present(ecom, &cur_bw);
+       if (!eval)
+               return new;
+
+       type = *eval;
+       if (type & ECOMMUNITY_FLAG_NON_TRANSITIVE)
+               return new;
+
+       /* Transitive link-bandwidth exists, replace with the passed
+        * (cumulative) bandwidth value. We need to create a new
+        * extcommunity for this - refer to AS-Path replace function
+        * for reference.
+        */
+       if (cum_bw > 0xFFFFFFFF)
+               cum_bw = 0xFFFFFFFF;
+       encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw,
+                         false, &lb_eval);
+       new = ecommunity_dup(ecom);
+       ecommunity_add_val(new, &lb_eval, true, true);
+
+       return new;
+}
index 094c677ff98231d3c4540c556f32a4559af7dbd8..7deae8e746f2e2dfdd343066a3cb3ceb8cae2f1d 100644 (file)
@@ -238,6 +238,8 @@ extern void bgp_remove_ecomm_from_aggregate_hash(
 extern void bgp_aggr_ecommunity_remove(void *arg);
 extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
                                                uint32_t *bw);
+extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
+                               struct ecommunity *ecom, uint64_t cum_bw);
 
 static inline void ecommunity_strip_rts(struct ecommunity *ecom)
 {
index e85335192801771a7ae7539eb520bf945a3c4e2b..8bb4bb075b14460e0d0e9d494b674e33c1f0787a 100644 (file)
@@ -1560,6 +1560,8 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
        afi_t afi;
        safi_t safi;
        int samepeer_safe = 0; /* for synthetic mplsvpns routes */
+       bool nh_reset = false;
+       uint64_t cum_bw;
 
        if (DISABLE_BGP_ANNOUNCE)
                return false;
@@ -1983,12 +1985,14 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                                  PEER_FLAG_FORCE_NEXTHOP_SELF)) {
                        if (!reflect
                            || CHECK_FLAG(peer->af_flags[afi][safi],
-                                         PEER_FLAG_FORCE_NEXTHOP_SELF))
+                                         PEER_FLAG_FORCE_NEXTHOP_SELF)) {
                                subgroup_announce_reset_nhop(
                                        (peer_cap_enhe(peer, afi, safi)
                                                 ? AF_INET6
                                                 : p->family),
                                        attr);
+                               nh_reset = true;
+                       }
                } else if (peer->sort == BGP_PEER_EBGP) {
                        /* Can also reset the nexthop if announcing to EBGP, but
                         * only if
@@ -1999,22 +2003,26 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                        if ((p->family == AF_INET) &&
                                (!bgp_subgrp_multiaccess_check_v4(
                                        piattr->nexthop,
-                                       subgrp, from)))
+                                       subgrp, from))) {
                                subgroup_announce_reset_nhop(
                                        (peer_cap_enhe(peer, afi, safi)
                                                 ? AF_INET6
                                                 : p->family),
                                                attr);
+                               nh_reset = true;
+                       }
 
                        if ((p->family == AF_INET6) &&
                                (!bgp_subgrp_multiaccess_check_v6(
                                        piattr->mp_nexthop_global,
-                                       subgrp, from)))
+                                       subgrp, from))) {
                                subgroup_announce_reset_nhop(
                                        (peer_cap_enhe(peer, afi, safi)
                                                ? AF_INET6
                                                : p->family),
                                                attr);
+                               nh_reset = true;
+                       }
 
 
 
@@ -2032,6 +2040,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                                        "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
                                        __func__, family2str(family));
                        subgroup_announce_reset_nhop(family, attr);
+                       nh_reset = true;
                }
        }
 
@@ -2044,10 +2053,25 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
         * the same interface.
         */
        if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
-               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
+               if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
                        subgroup_announce_reset_nhop(AF_INET6, attr);
+                               nh_reset = true;
+                       }
        }
 
+       /*
+        * When the next hop is set to ourselves, if all multipaths have
+        * link-bandwidth announce the cumulative bandwidth as that makes
+        * the most sense. However, don't modify if the link-bandwidth has
+        * been explicitly set by user policy.
+        */
+       if (nh_reset &&
+           bgp_path_info_mpath_chkwtd(pi) &&
+           (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
+           !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
+               attr->ecommunity = ecommunity_replace_linkbw(
+                                       bgp->as, attr->ecommunity, cum_bw);
+
        return true;
 }
 
index 7552ff2a666756b50eb31015167de9ec677c3c0b..7f23f6beca9b7a6e43e2a96ed01defc136f20862 100644 (file)
@@ -2609,6 +2609,10 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
        path->attr->ecommunity = new_ecom;
        path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
 
+       /* Mark that route-map has set link bandwidth; used in attribute
+        * setting decisions.
+        */
+       SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
 
        return RMAP_OKAY;
 }