]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Additional options for generating link bandwidth
authorvivek <vivek@cumulusnetworks.com>
Tue, 24 Mar 2020 20:57:44 +0000 (13:57 -0700)
committervivek <vivek@cumulusnetworks.com>
Tue, 31 Mar 2020 03:12:31 +0000 (20:12 -0700)
Implement the code to handle the other route-map options to generate
the link bandwidth, namely, to use the cumulative bandwidth or to
base this on the number of multipaths. In the latter case, a reference
bandwidth is internally chosen - the implementation uses a value of
1 Gbps.

These additional options mean that the prefix may need to be advertised
if there is a link bandwidth change, which is a new criteria. Define a
new path (change) flag to support this and implement the advertisement.

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

index ed2b3c9235879c8707b64b03c2e2d417f0135040..6a7db87ec43ca592ad29b1732adf7b76549ac547 100644 (file)
@@ -1132,6 +1132,7 @@ static int evpn_es_route_select_install(struct bgp *bgp,
                                                   old_select->attr->nexthop);
                }
                UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
                bgp_zebra_clear_route_change_flags(rn);
                return ret;
        }
@@ -1152,6 +1153,7 @@ static int evpn_es_route_select_install(struct bgp *bgp,
                bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
                bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
                UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
        }
 
        if (new_select && new_select->type == ZEBRA_ROUTE_BGP
@@ -1211,6 +1213,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
                                bgp, vpn, (const struct prefix_evpn *)bgp_node_get_prefix(rn),
                                old_select);
                UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
                bgp_zebra_clear_route_change_flags(rn);
                return ret;
        }
@@ -1230,6 +1233,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
                bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
                bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
                UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
        }
 
        if (new_select && new_select->type == ZEBRA_ROUTE_BGP
index b30764d773ee6e9e74ace003a03d4d4d226be4aa..a3d40849ce7a5e5e4241b0fbabf4a40c10c028f8 100644 (file)
@@ -500,7 +500,7 @@ void bgp_path_info_mpath_update(struct bgp_node *rn,
 {
        uint16_t maxpaths, mpath_count, old_mpath_count;
        uint32_t bwval;
-       uint64_t cum_bw;
+       uint64_t cum_bw, old_cum_bw;
        struct listnode *mp_node, *mp_next_node;
        struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
        int mpath_changed, debug;
@@ -513,7 +513,7 @@ void bgp_path_info_mpath_update(struct bgp_node *rn,
        mpath_count = 0;
        cur_mpath = NULL;
        old_mpath_count = 0;
-       cum_bw = 0;
+       old_cum_bw = cum_bw = 0;
        prev_mpath = new_best;
        mp_node = listhead(mp_list);
        debug = bgp_debug_bestpath(rn);
@@ -530,6 +530,7 @@ void bgp_path_info_mpath_update(struct bgp_node *rn,
        if (old_best) {
                cur_mpath = bgp_path_info_mpath_first(old_best);
                old_mpath_count = bgp_path_info_mpath_count(old_best);
+               old_cum_bw = bgp_path_info_mpath_cumbw(old_best);
                bgp_path_info_mpath_count_set(old_best, 0);
                bgp_path_info_mpath_lb_update(old_best, false, false, 0);
                bgp_path_info_mpath_dequeue(old_best);
@@ -537,9 +538,10 @@ void bgp_path_info_mpath_update(struct bgp_node *rn,
 
        if (debug)
                zlog_debug(
-                       "%pRN: starting mpath update, newbest %s num candidates %d old-mpath-count %d",
+                       "%pRN: starting mpath update, newbest %s num candidates %d old-mpath-count %d old-cum-bw u%" PRIu64,
                        rn, new_best ? new_best->peer->host : "NONE",
-                       mp_list ? listcount(mp_list) : 0, old_mpath_count);
+                       mp_list ? listcount(mp_list) : 0,
+                       old_mpath_count, old_cum_bw);
 
        /*
         * We perform an ordered walk through both lists in parallel.
@@ -728,6 +730,9 @@ void bgp_path_info_mpath_update(struct bgp_node *rn,
                if (mpath_changed
                    || (bgp_path_info_mpath_count(new_best) != old_mpath_count))
                        SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG);
+               if ((mpath_count - 1) != old_mpath_count ||
+                   old_cum_bw != cum_bw)
+                       SET_FLAG(new_best->flags, BGP_PATH_LINK_BW_CHG);
        }
 }
 
@@ -752,6 +757,7 @@ void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best)
 
        bgp_path_info_mpath_count_set(dmed_best, 0);
        UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG);
+       UNSET_FLAG(dmed_best->flags, BGP_PATH_LINK_BW_CHG);
        assert(bgp_path_info_mpath_first(dmed_best) == NULL);
 }
 
index 9a3ab0d8eebad445f6ed3a09b3bca840168a0c1e..e85335192801771a7ae7539eb520bf945a3c4e2b 100644 (file)
@@ -2394,7 +2394,8 @@ bool bgp_zebra_has_route_changed(struct bgp_node *rn,
         * when the best path has an attribute change anyway.
         */
        if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
-           || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
+           || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
+           || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
                return true;
 
        /*
@@ -2563,12 +2564,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                                                           bgp, afi, safi);
                        }
                }
-               UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
-               bgp_zebra_clear_route_change_flags(rn);
 
                /* If there is a change of interest to peers, reannounce the
                 * route. */
                if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
+                   || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
                    || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
                        group_announce_route(bgp, afi, safi, rn, new_select);
 
@@ -2583,6 +2583,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                        UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
                }
 
+               UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
+               bgp_zebra_clear_route_change_flags(rn);
                UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
                return;
        }
@@ -2613,6 +2616,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
                bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
                UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
+               UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
        }
 
 #if ENABLE_BGP_VNC
index 9438b328ad02cea383adcad54f042a6799fb5c3d..bdcb2cdf6a25f7c8171ea14ffe53b59fe19eda3c 100644 (file)
@@ -237,6 +237,7 @@ struct bgp_path_info {
 #define BGP_PATH_MULTIPATH_CHG (1 << 12)
 #define BGP_PATH_RIB_ATTR_CHG (1 << 13)
 #define BGP_PATH_ANNC_NH_SELF (1 << 14)
+#define BGP_PATH_LINK_BW_CHG (1 << 15)
 
        /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
        uint8_t type;
@@ -477,6 +478,10 @@ static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi,
        dst_pi->peer = peer;
        dst_pi->attr = attr;
        dst_pi->net = rn;
+       dst_pi->flags = src_pi->flags;
+       dst_pi->type = src_pi->type;
+       dst_pi->sub_type = src_pi->sub_type;
+       dst_pi->mpath = src_pi->mpath;
        if (src_pi->extra) {
                memcpy(dst_pie, src_pi->extra,
                       sizeof(struct bgp_path_info_extra));
index ffcb65555be7fe468dca3f9a8acae2cc458c354a..7552ff2a666756b50eb31015167de9ec677c3c0b 100644 (file)
@@ -63,6 +63,7 @@
 #include "bgpd/bgp_pbr.h"
 #include "bgpd/bgp_flowspec_util.h"
 #include "bgpd/bgp_encap_types.h"
+#include "bgpd/bgp_mpath.h"
 
 #if ENABLE_BGP_VNC
 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
@@ -2552,6 +2553,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
        struct ecommunity ecom_lb = {0};
        struct ecommunity_val lb_eval;
        uint32_t bw_bytes = 0;
+       uint16_t mpath_count = 0;
        struct ecommunity *new_ecom;
        struct ecommunity *old_ecom;
        as_t as;
@@ -2566,8 +2568,27 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
 
        /* Build link bandwidth extended community */
        as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
-       if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE)
+       if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
                bw_bytes = ((uint64_t)(rels->bw * 1000 * 1000))/8;
+       } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
+               /* process this only for the best path. */
+               if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
+                       return RMAP_OKAY;
+
+               bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
+               if (!bw_bytes)
+                       return RMAP_OKAY;
+
+       } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
+
+               /* process this only for the best path. */
+               if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
+                       return RMAP_OKAY;
+
+               bw_bytes = ((uint64_t)(peer->bgp->lb_ref_bw * 1000 * 1000))/8;
+               mpath_count = bgp_path_info_mpath_count(path) + 1;
+               bw_bytes *= mpath_count;
+       }
 
        encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval);
 
index 6534ac19000242fc7066ff1aa88898789866c649..d1363b70a4c68f24b52912abd2ca8485b428a133 100644 (file)
@@ -2970,6 +2970,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
        bgp->rib_stale_time = BGP_DEFAULT_RIB_STALE_TIME;
        bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
        bgp->dynamic_neighbors_count = 0;
+       bgp->lb_ref_bw = BGP_LINK_BW_REF_BW;
        bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
        bgp->reject_as_sets = BGP_REJECT_AS_SETS_DISABLED;
        bgp_addpath_init_bgp_data(&bgp->tx_addpath);
index 2b67a39efd49b117e764e2ceefad149b9c2afdd3..24ea66b5a1819013389e13f249cd4f0e779ac7b1 100644 (file)
@@ -395,6 +395,14 @@ struct bgp {
 #define BGP_UPDATE_DELAY_MIN              0
 #define BGP_UPDATE_DELAY_MAX              3600
 
+       /* Reference bandwidth for BGP link-bandwidth. Used when
+        * the LB value has to be computed based on some other
+        * factor (e.g., number of multipaths for the prefix)
+        * Value is in Mbps
+        */
+       uint32_t lb_ref_bw;
+#define BGP_LINK_BW_REF_BW                1
+
        /* BGP flags. */
        uint32_t flags;
 #define BGP_FLAG_ALWAYS_COMPARE_MED       (1 << 0)