diff options
Diffstat (limited to 'bgpd/bgp_routemap.c')
| -rw-r--r-- | bgpd/bgp_routemap.c | 201 |
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); |
