summaryrefslogtreecommitdiff
path: root/bgpd/bgp_routemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_routemap.c')
-rw-r--r--bgpd/bgp_routemap.c201
1 files changed, 197 insertions, 4 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 2d92136450..6b57afc5c1 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -39,6 +39,7 @@
#include "hash.h"
#include "queue.h"
#include "frrstr.h"
+#include "network.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -63,8 +64,9 @@
#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
+#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
#endif
@@ -1534,7 +1536,7 @@ static enum route_map_cmd_result_t
route_match_probability(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
- long r = random();
+ long r = frr_weak_random();
switch (*(long *)rule) {
case 0:
@@ -2531,6 +2533,146 @@ static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
route_set_ecommunity_free,
};
+/* `set extcommunity bandwidth' */
+
+struct rmap_ecomm_lb_set {
+ uint8_t lb_type;
+#define RMAP_ECOMM_LB_SET_VALUE 1
+#define RMAP_ECOMM_LB_SET_CUMUL 2
+#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
+ bool non_trans;
+ uint32_t bw;
+};
+
+static enum route_map_cmd_result_t
+route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct rmap_ecomm_lb_set *rels = rule;
+ struct bgp_path_info *path;
+ struct peer *peer;
+ 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;
+
+ if (type != RMAP_BGP)
+ return RMAP_OKAY;
+
+ path = object;
+ peer = path->peer;
+ if (!peer || !peer->bgp)
+ return RMAP_ERROR;
+
+ /* 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) {
+ 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);
+
+ /* add to route or merge with existing */
+ old_ecom = path->attr->ecommunity;
+ if (old_ecom) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_add_val(new_ecom, &lb_eval, true, true);
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else {
+ ecom_lb.size = 1;
+ ecom_lb.val = (uint8_t *)lb_eval.val;
+ new_ecom = ecommunity_dup(&ecom_lb);
+ }
+
+ /* new_ecom will be intern()'d or attr_flush()'d in call stack */
+ 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;
+}
+
+static void *route_set_ecommunity_lb_compile(const char *arg)
+{
+ struct rmap_ecomm_lb_set *rels;
+ uint8_t lb_type;
+ uint32_t bw = 0;
+ char bw_str[40] = {0};
+ char *p, *str;
+ bool non_trans = false;
+
+ str = (char *)arg;
+ p = strchr(arg, ' ');
+ if (p) {
+ int len;
+
+ len = p - arg;
+ memcpy(bw_str, arg, len);
+ non_trans = true;
+ str = bw_str;
+ }
+
+ if (strcmp(str, "cumulative") == 0)
+ lb_type = RMAP_ECOMM_LB_SET_CUMUL;
+ else if (strcmp(str, "num-multipaths") == 0)
+ lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
+ else {
+ char *end = NULL;
+
+ bw = strtoul(str, &end, 10);
+ if (*end != '\0')
+ return NULL;
+ lb_type = RMAP_ECOMM_LB_SET_VALUE;
+ }
+
+ rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
+ sizeof(struct rmap_ecomm_lb_set));
+ rels->lb_type = lb_type;
+ rels->bw = bw;
+ rels->non_trans = non_trans;
+
+ return rels;
+}
+
+static void route_set_ecommunity_lb_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
+ "extcommunity bandwidth",
+ route_set_ecommunity_lb,
+ route_set_ecommunity_lb_compile,
+ route_set_ecommunity_lb_free,
+};
+
/* `set origin ORIGIN' */
/* For origin set. */
@@ -3749,7 +3891,7 @@ static void bgp_route_map_process_update_cb(char *rmap_name)
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
bgp_route_map_process_update(bgp, rmap_name, 1);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
/* zlog_debug("%s: calling vnc_routemap_update", __func__); */
vnc_routemap_update(bgp, __func__);
#endif
@@ -3793,7 +3935,7 @@ static void bgp_route_map_mark_update(const char *rmap_name)
} else {
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
bgp_route_map_process_update(bgp, rmap_name, 0);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
zlog_debug("%s: calling vnc_routemap_update", __func__);
vnc_routemap_update(bgp, __func__);
#endif
@@ -5004,6 +5146,53 @@ ALIAS (no_set_ecommunity_soo,
"GP extended community attribute\n"
"Site-of-Origin extended community\n")
+DEFUN (set_ecommunity_lb,
+ set_ecommunity_lb_cmd,
+ "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ SET_STR
+ "BGP extended community attribute\n"
+ "Link bandwidth extended community\n"
+ "Bandwidth value in Mbps\n"
+ "Cumulative bandwidth of all multipaths (outbound-only)\n"
+ "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
+ "Attribute is set as non-transitive\n")
+{
+ int idx_lb = 3;
+ int ret;
+ char *str;
+
+ str = argv_concat(argv, argc, idx_lb);
+ ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity bandwidth", str);
+ XFREE(MTYPE_TMP, str);
+ return ret;
+}
+
+
+DEFUN (no_set_ecommunity_lb,
+ no_set_ecommunity_lb_cmd,
+ "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ NO_STR
+ SET_STR
+ "BGP extended community attribute\n"
+ "Link bandwidth extended community\n"
+ "Bandwidth value in Mbps\n"
+ "Cumulative bandwidth of all multipaths (outbound-only)\n"
+ "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
+ "Attribute is set as non-transitive\n")
+{
+ return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity bandwidth", NULL);
+}
+
+ALIAS (no_set_ecommunity_lb,
+ no_set_ecommunity_lb_short_cmd,
+ "no set extcommunity bandwidth",
+ NO_STR
+ SET_STR
+ "BGP extended community attribute\n"
+ "Link bandwidth extended community\n")
+
DEFUN (set_origin,
set_origin_cmd,
"set origin <egp|igp|incomplete>",
@@ -5549,6 +5738,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_originator_id_cmd);
route_map_install_set(&route_set_ecommunity_rt_cmd);
route_map_install_set(&route_set_ecommunity_soo_cmd);
+ route_map_install_set(&route_set_ecommunity_lb_cmd);
route_map_install_set(&route_set_tag_cmd);
route_map_install_set(&route_set_label_index_cmd);
@@ -5632,6 +5822,9 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
+ install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
+ install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
+ install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
#ifdef KEEP_OLD_VPN_COMMANDS
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);