mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 17:01:51 +00:00
bgpd: add 'match extcommunity-count' command to restrict comm count
Add a mechanism in route-map to filter out route-map which have a list of extended communities greater than the given number. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
e27631e10a
commit
c3084cacf4
@ -1358,6 +1358,65 @@ static const struct route_map_rule_cmd route_match_community_limit_cmd = {
|
||||
route_match_community_limit_compile, route_match_community_limit_free
|
||||
};
|
||||
|
||||
/* `match extcommunity-limit' */
|
||||
|
||||
/* Match function should return :
|
||||
* - RMAP_MATCH if the bgp update extcommunity list count
|
||||
* is less or equal to the configured limit.
|
||||
* - RMAP_NOMATCH if the extcommunity list count is greater than the
|
||||
* configured limit.
|
||||
*/
|
||||
static enum route_map_cmd_result_t
|
||||
route_match_extcommunity_limit(void *rule, const struct prefix *prefix, void *object)
|
||||
{
|
||||
struct bgp_path_info *path = NULL;
|
||||
struct ecommunity *piextcomm = NULL, *pi6extcomm = NULL;
|
||||
uint16_t count = 0;
|
||||
uint16_t *limit_rule = rule;
|
||||
|
||||
path = (struct bgp_path_info *)object;
|
||||
|
||||
piextcomm = bgp_attr_get_ecommunity(path->attr);
|
||||
if (piextcomm)
|
||||
count = piextcomm->size;
|
||||
|
||||
pi6extcomm = bgp_attr_get_ipv6_ecommunity(path->attr);
|
||||
if (pi6extcomm)
|
||||
count += pi6extcomm->size;
|
||||
|
||||
if (count <= *limit_rule)
|
||||
return RMAP_MATCH;
|
||||
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
/* Route map `extcommunity-limit' match statement. */
|
||||
static void *route_match_extcommunity_limit_compile(const char *arg)
|
||||
{
|
||||
uint16_t *limit = NULL;
|
||||
char *end = NULL;
|
||||
|
||||
limit = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint16_t));
|
||||
*limit = strtoul(arg, &end, 10);
|
||||
if (*end != '\0') {
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, limit);
|
||||
return NULL;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
/* Free route map's compiled `community-limit' value. */
|
||||
static void route_match_extcommunity_limit_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
/* Route map commands for community limit matching. */
|
||||
static const struct route_map_rule_cmd route_match_extcommunity_limit_cmd = {
|
||||
"extcommunity-limit", route_match_extcommunity_limit,
|
||||
route_match_extcommunity_limit_compile, route_match_extcommunity_limit_free
|
||||
};
|
||||
|
||||
static enum route_map_cmd_result_t
|
||||
route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
|
||||
{
|
||||
@ -5885,6 +5944,27 @@ DEFPY_YANG (match_ecommunity,
|
||||
}
|
||||
|
||||
|
||||
DEFPY_YANG(
|
||||
match_extcommunity_limit, match_extcommunity_limit_cmd,
|
||||
"[no$no] match extcommunity-limit ![(0-65535)$limit]",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
"Match BGP extended community limit\n"
|
||||
"Extended community limit number\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./match-condition[condition='frr-bgp-route-map:match-extcommunity-limit']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE, NULL);
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-match-condition/frr-bgp-route-map:extcommunity-limit", xpath);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath_value, no ? NB_OP_DESTROY : NB_OP_MODIFY, limit_str);
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
|
||||
DEFUN_YANG (no_match_ecommunity,
|
||||
no_match_ecommunity_cmd,
|
||||
"no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
|
||||
@ -7980,6 +8060,7 @@ void bgp_route_map_init(void)
|
||||
route_map_install_match(&route_match_evpn_route_type_cmd);
|
||||
route_map_install_match(&route_match_evpn_rd_cmd);
|
||||
route_map_install_match(&route_match_community_limit_cmd);
|
||||
route_map_install_match(&route_match_extcommunity_limit_cmd);
|
||||
route_map_install_match(&route_match_evpn_default_route_cmd);
|
||||
route_map_install_match(&route_match_vrl_source_vrf_cmd);
|
||||
|
||||
@ -8053,6 +8134,7 @@ void bgp_route_map_init(void)
|
||||
install_element(RMAP_NODE, &match_community_cmd);
|
||||
install_element(RMAP_NODE, &no_match_community_cmd);
|
||||
install_element(RMAP_NODE, &match_community_limit_cmd);
|
||||
install_element(RMAP_NODE, &match_extcommunity_limit_cmd);
|
||||
install_element(RMAP_NODE, &match_lcommunity_cmd);
|
||||
install_element(RMAP_NODE, &no_match_lcommunity_cmd);
|
||||
install_element(RMAP_NODE, &match_ecommunity_cmd);
|
||||
|
@ -221,6 +221,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
|
||||
.destroy = lib_route_map_entry_set_action_rmap_set_action_distance_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:extcommunity-limit",
|
||||
.cbs = {
|
||||
.modify = lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_modify,
|
||||
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-rt",
|
||||
.cbs = {
|
||||
|
@ -76,6 +76,10 @@ int lib_route_map_entry_match_condition_rmap_match_condition_community_limit_mod
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_community_limit_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_destroy(
|
||||
|
@ -1666,6 +1666,57 @@ int lib_route_map_entry_set_action_rmap_set_action_distance_destroy(
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:extcommunity-limit
|
||||
*/
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct routemap_hook_context *rhc;
|
||||
const char *limit;
|
||||
enum rmap_compile_rets ret;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
/* Add configuration. */
|
||||
rhc = nb_running_get_entry(args->dnode, NULL, true);
|
||||
limit = yang_dnode_get_string(args->dnode, NULL);
|
||||
|
||||
rhc->rhc_mhook = bgp_route_match_delete;
|
||||
rhc->rhc_rule = "extcommunity-limit";
|
||||
rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
|
||||
|
||||
ret = bgp_route_match_add(rhc->rhc_rmi, "extcommunity-limit", limit,
|
||||
RMAP_EVENT_MATCH_ADDED, args->errmsg, args->errmsg_len);
|
||||
|
||||
if (ret != RMAP_COMPILE_SUCCESS) {
|
||||
rhc->rhc_mhook = NULL;
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int lib_route_map_entry_match_condition_rmap_match_condition_extcommunity_limit_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
return lib_route_map_entry_match_destroy(args);
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath:
|
||||
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-rt
|
||||
|
@ -2920,6 +2920,13 @@ BGP Extended Communities in Route Map
|
||||
|
||||
.. clicmd:: match extcommunity WORD
|
||||
|
||||
.. clicmd:: match extcommunity-limit (0-65535)
|
||||
|
||||
This command matches BGP updates that use extended community list and IPv6
|
||||
extended community list, and with an extended community list count less or
|
||||
equal than the defined limit. Setting extended community-limit to 0 will
|
||||
only match BGP updates with no extended community.
|
||||
|
||||
.. clicmd:: set extcommunity none
|
||||
|
||||
This command resets the extended community value in BGP updates. If the attribute is
|
||||
|
@ -317,6 +317,7 @@ DECLARE_QOBJ_TYPE(route_map);
|
||||
(strmatch(C, "frr-bgp-route-map:match-large-community"))
|
||||
#define IS_MATCH_EXTCOMMUNITY(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:match-extcommunity"))
|
||||
#define IS_MATCH_EXTCOMMUNITY_LIMIT(C) (strmatch(C, "frr-bgp-route-map:match-extcommunity-limit"))
|
||||
#define IS_MATCH_IPV4_NH(C) \
|
||||
(strmatch(C, "frr-bgp-route-map:ipv4-nexthop"))
|
||||
#define IS_MATCH_IPV6_NH(C) \
|
||||
|
@ -715,6 +715,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
|
||||
yang_dnode_get_string(
|
||||
dnode,
|
||||
"./rmap-match-condition/frr-bgp-route-map:rpki"));
|
||||
} else if (IS_MATCH_EXTCOMMUNITY_LIMIT(condition)) {
|
||||
vty_out(vty, " match extcommunity-limit %s\n",
|
||||
yang_dnode_get_string(dnode,
|
||||
"./rmap-match-condition/frr-bgp-route-map:extcommunity-limit"));
|
||||
} else if (IS_MATCH_RPKI_EXTCOMMUNITY(condition)) {
|
||||
vty_out(vty, " match rpki-extcommunity %s\n",
|
||||
yang_dnode_get_string(
|
||||
|
@ -166,6 +166,12 @@ module frr-bgp-route-map {
|
||||
"Match BGP extcommunity list";
|
||||
}
|
||||
|
||||
identity match-extcommunity-limit {
|
||||
base frr-route-map:rmap-match-type;
|
||||
description
|
||||
"Match BGP extcommunity limit count";
|
||||
}
|
||||
|
||||
identity as-path-list {
|
||||
base frr-route-map:rmap-match-type;
|
||||
description
|
||||
@ -819,6 +825,17 @@ identity set-extcommunity-color {
|
||||
}
|
||||
}
|
||||
|
||||
case extcommunity-limit {
|
||||
when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-extcommunity-limit')";
|
||||
description
|
||||
"Match BGP updates when the list of extended communities count is less than the configured limit.";
|
||||
leaf extcommunity-limit {
|
||||
type uint16 {
|
||||
range "0..1024";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case comm-list-name {
|
||||
when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-community') or "
|
||||
+ "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-large-community') or "
|
||||
|
Loading…
Reference in New Issue
Block a user