mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 00:06:09 +00:00
bgpd: add set extended-comm-list <> delete command
Signed-off-by: Farid Mihoub <farid.mihoub@6wind.com> Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
1aa34e5fb7
commit
902a8d1fd3
@ -986,6 +986,44 @@ struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
|
||||
return lcom;
|
||||
}
|
||||
|
||||
/* Delete all permitted extended communities in the list from ecom.*/
|
||||
struct ecommunity *ecommunity_list_match_delete(struct ecommunity *ecom,
|
||||
struct community_list *list)
|
||||
{
|
||||
struct community_entry *entry;
|
||||
uint32_t com_index_to_delete[ecom->size];
|
||||
uint8_t *ptr;
|
||||
uint32_t delete_index = 0;
|
||||
uint32_t i;
|
||||
struct ecommunity local_ecom = {.size = 1};
|
||||
struct ecommunity_val local_eval = {0};
|
||||
|
||||
for (i = 0; i < ecom->size; i++) {
|
||||
local_ecom.val = ecom->val + (i * ECOMMUNITY_SIZE);
|
||||
for (entry = list->head; entry; entry = entry->next) {
|
||||
if (((entry->style == EXTCOMMUNITY_LIST_STANDARD) &&
|
||||
ecommunity_include(entry->u.ecom, &local_ecom)) ||
|
||||
((entry->style == EXTCOMMUNITY_LIST_EXPANDED) &&
|
||||
ecommunity_regexp_match(ecom, entry->reg))) {
|
||||
if (entry->direct == COMMUNITY_PERMIT) {
|
||||
com_index_to_delete[delete_index] = i;
|
||||
delete_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete all of the extended communities we flagged for deletion */
|
||||
for (i = delete_index; i > 0; i--) {
|
||||
ptr = ecom->val + (com_index_to_delete[i-1] * ECOMMUNITY_SIZE);
|
||||
memcpy(&local_eval.val, ptr, sizeof(local_eval.val));
|
||||
ecommunity_del_val(ecom, &local_eval);
|
||||
}
|
||||
|
||||
return ecom;
|
||||
}
|
||||
|
||||
/* Helper to check if every octet do not exceed UINT_MAX */
|
||||
bool lcommunity_list_valid(const char *community, int style)
|
||||
{
|
||||
|
@ -163,6 +163,9 @@ community_list_match_delete(struct community *com, struct community_list *list);
|
||||
extern struct lcommunity *
|
||||
lcommunity_list_match_delete(struct lcommunity *lcom,
|
||||
struct community_list *list);
|
||||
extern struct ecommunity *
|
||||
ecommunity_list_match_delete(struct ecommunity *ecom,
|
||||
struct community_list *list);
|
||||
|
||||
static inline uint32_t bgp_clist_hash_key(char *name)
|
||||
{
|
||||
|
@ -2852,6 +2852,83 @@ static const struct route_map_rule_cmd route_set_community_delete_cmd = {
|
||||
route_set_community_delete_free,
|
||||
};
|
||||
|
||||
/* `set extcomm-list (<1-99>|<100-500>|WORD) delete' */
|
||||
static enum route_map_cmd_result_t
|
||||
route_set_ecommunity_delete(void *rule, const struct prefix *prefix,
|
||||
void *object)
|
||||
{
|
||||
struct community_list *list;
|
||||
struct ecommunity *merge;
|
||||
struct ecommunity *new;
|
||||
struct ecommunity *old;
|
||||
struct bgp_path_info *path;
|
||||
struct rmap_community *rcom = rule;
|
||||
|
||||
if (!rcom)
|
||||
return RMAP_OKAY;
|
||||
|
||||
path = object;
|
||||
list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
|
||||
EXTCOMMUNITY_LIST_MASTER);
|
||||
old = bgp_attr_get_ecommunity(path->attr);
|
||||
if (list && old) {
|
||||
merge = ecommunity_list_match_delete(ecommunity_dup(old), list);
|
||||
new = ecommunity_uniq_sort(merge);
|
||||
ecommunity_free(&merge);
|
||||
|
||||
/* HACK: if the old community is not intern'd,
|
||||
* we should free it here, or all reference to it may be
|
||||
* lost.
|
||||
* Really need to cleanup attribute caching sometime.
|
||||
*/
|
||||
if (old->refcnt == 0)
|
||||
ecommunity_free(&old);
|
||||
|
||||
if (new->size == 0) {
|
||||
bgp_attr_set_ecommunity(path->attr, NULL);
|
||||
ecommunity_free(&new);
|
||||
} else {
|
||||
bgp_attr_set_ecommunity(path->attr, new);
|
||||
}
|
||||
}
|
||||
|
||||
return RMAP_OKAY;
|
||||
}
|
||||
|
||||
static void *route_set_ecommunity_delete_compile(const char *arg)
|
||||
{
|
||||
struct rmap_community *rcom;
|
||||
char **splits;
|
||||
int num;
|
||||
|
||||
frrstr_split(arg, " ", &splits, &num);
|
||||
|
||||
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
||||
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
|
||||
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
XFREE(MTYPE_TMP, splits[i]);
|
||||
XFREE(MTYPE_TMP, splits);
|
||||
|
||||
return rcom;
|
||||
}
|
||||
|
||||
static void route_set_ecommunity_delete_free(void *rule)
|
||||
{
|
||||
struct rmap_community *rcom = rule;
|
||||
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
||||
}
|
||||
|
||||
static const struct route_map_rule_cmd route_set_ecommunity_delete_cmd = {
|
||||
"extended-comm-list",
|
||||
route_set_ecommunity_delete,
|
||||
route_set_ecommunity_delete_compile,
|
||||
route_set_ecommunity_delete_free,
|
||||
};
|
||||
|
||||
/* `set extcommunity rt COMMUNITY' */
|
||||
|
||||
struct rmap_ecom_set {
|
||||
@ -5522,6 +5599,51 @@ DEFUN_YANG (no_match_ecommunity,
|
||||
}
|
||||
|
||||
|
||||
DEFPY_YANG (set_ecommunity_delete,
|
||||
set_ecommunity_delete_cmd,
|
||||
"set extended-comm-list " EXTCOMM_LIST_CMD_STR " delete",
|
||||
SET_STR
|
||||
"set BGP extended community list (for deletion)\n"
|
||||
EXTCOMM_STD_LIST_NUM_STR
|
||||
EXTCOMM_EXP_LIST_NUM_STR
|
||||
EXTCOMM_LIST_NAME_STR
|
||||
"Delete matching extended communities\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:extended-comm-list-delete']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
int idx_comm_list = 2;
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
|
||||
xpath);
|
||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
|
||||
argv[idx_comm_list]->arg);
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
|
||||
DEFPY_YANG (no_set_ecommunity_delete,
|
||||
no_set_ecommunity_delete_cmd,
|
||||
"no set extended-comm-list [" EXTCOMM_LIST_CMD_STR "] delete",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"set BGP extended community list (for deletion)\n"
|
||||
EXTCOMM_STD_LIST_NUM_STR
|
||||
EXTCOMM_EXP_LIST_NUM_STR
|
||||
EXTCOMM_LIST_NAME_STR
|
||||
"Delete matching extended communities\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:extended-comm-list-delete']";
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
|
||||
DEFUN_YANG (match_aspath,
|
||||
match_aspath_cmd,
|
||||
"match as-path AS_PATH_FILTER_NAME",
|
||||
@ -7605,6 +7727,7 @@ void bgp_route_map_init(void)
|
||||
route_map_install_set(&route_set_aggregator_as_cmd);
|
||||
route_map_install_set(&route_set_community_cmd);
|
||||
route_map_install_set(&route_set_community_delete_cmd);
|
||||
route_map_install_set(&route_set_ecommunity_delete_cmd);
|
||||
route_map_install_set(&route_set_lcommunity_cmd);
|
||||
route_map_install_set(&route_set_lcommunity_delete_cmd);
|
||||
route_map_install_set(&route_set_vpnv4_nexthop_cmd);
|
||||
@ -7724,6 +7847,8 @@ void bgp_route_map_init(void)
|
||||
install_element(RMAP_NODE, &set_ecommunity_color_cmd);
|
||||
install_element(RMAP_NODE, &no_set_ecommunity_color_cmd);
|
||||
install_element(RMAP_NODE, &no_set_ecommunity_color_all_cmd);
|
||||
install_element(RMAP_NODE, &set_ecommunity_delete_cmd);
|
||||
install_element(RMAP_NODE, &no_set_ecommunity_delete_cmd);
|
||||
#ifdef KEEP_OLD_VPN_COMMANDS
|
||||
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
|
||||
install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
|
||||
|
@ -2835,6 +2835,8 @@ int lib_route_map_entry_set_action_rmap_set_action_comm_list_name_modify(
|
||||
"../../frr-route-map:action");
|
||||
if (IS_SET_COMM_LIST_DEL(action))
|
||||
rhc->rhc_rule = "comm-list";
|
||||
else if (IS_SET_EXTCOMM_LIST_DEL(action))
|
||||
rhc->rhc_rule = "extended-comm-list";
|
||||
else
|
||||
rhc->rhc_rule = "large-comm-list";
|
||||
|
||||
|
@ -335,6 +335,10 @@ Route Map Set Command
|
||||
|
||||
Set the BGP community attribute.
|
||||
|
||||
.. clicmd:: set extended-comm-list <EXTCOMMUNITY_LIST_NAME> delete
|
||||
|
||||
Set BGP extended community list for deletion.
|
||||
|
||||
.. clicmd:: set ipv6 next-hop local IPV6_ADDRESS
|
||||
|
||||
Set the BGP-4+ link local IPv6 nexthop address.
|
||||
|
@ -416,6 +416,10 @@ struct cmd_node {
|
||||
#define COMMUNITY_AANN_STR "Community number where AA and NN are (0-65535)\n"
|
||||
#define COMMUNITY_VAL_STR \
|
||||
"Community number in AA:NN format (where AA and NN are (0-65535)) or local-AS|no-advertise|no-export|internet|graceful-shutdown|accept-own-nexthop|accept-own|route-filter-translated-v4|route-filter-v4|route-filter-translated-v6|route-filter-v6|llgr-stale|no-llgr|blackhole|no-peer or additive\n"
|
||||
#define EXTCOMM_LIST_CMD_STR "<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>"
|
||||
#define EXTCOMM_STD_LIST_NUM_STR "Extended community-list number (standard)\n"
|
||||
#define EXTCOMM_EXP_LIST_NUM_STR "Extended community-list number (expanded)\n"
|
||||
#define EXTCOMM_LIST_NAME_STR "Extended community-list name\n"
|
||||
#define MPLS_TE_STR "MPLS-TE specific commands\n"
|
||||
#define LINK_PARAMS_STR "Configure interface link parameters\n"
|
||||
#define OSPF_RI_STR "OSPF Router Information specific commands\n"
|
||||
|
@ -348,6 +348,8 @@ DECLARE_QOBJ_TYPE(route_map);
|
||||
(strmatch(A, "frr-bgp-route-map:comm-list-delete"))
|
||||
#define IS_SET_LCOMM_LIST_DEL(A) \
|
||||
(strmatch(A, "frr-bgp-route-map:large-comm-list-delete"))
|
||||
#define IS_SET_EXTCOMM_LIST_DEL(A) \
|
||||
(strmatch(A, "frr-bgp-route-map:extended-comm-list-delete"))
|
||||
#define IS_SET_LCOMMUNITY(A) \
|
||||
(strmatch(A, "frr-bgp-route-map:set-large-community"))
|
||||
#define IS_SET_COMMUNITY(A) \
|
||||
|
@ -1186,6 +1186,16 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
|
||||
assert(acl);
|
||||
|
||||
vty_out(vty, " set large-comm-list %s delete\n", acl);
|
||||
} else if (IS_SET_EXTCOMM_LIST_DEL(action)) {
|
||||
acl = NULL;
|
||||
ln = yang_dnode_get(dnode, "./rmap-set-action/frr-bgp-route-map:comm-list-name");
|
||||
|
||||
if (ln)
|
||||
acl = yang_dnode_get_string(ln, NULL);
|
||||
|
||||
assert(acl);
|
||||
|
||||
vty_out(vty, " set extended-comm-list %s delete\n", acl);
|
||||
} else if (IS_SET_LCOMMUNITY(action)) {
|
||||
if (yang_dnode_exists(
|
||||
dnode,
|
||||
|
@ -352,6 +352,12 @@ identity set-extcommunity-color {
|
||||
"Set BGP large community list (for deletion)";
|
||||
}
|
||||
|
||||
identity extended-comm-list-delete {
|
||||
base frr-route-map:rmap-set-type;
|
||||
description
|
||||
"Set BGP extended community list (for deletion)";
|
||||
}
|
||||
|
||||
identity set-evpn-gateway-ip-ipv4 {
|
||||
base frr-route-map:rmap-set-type;
|
||||
description
|
||||
@ -1109,7 +1115,9 @@ identity set-extcommunity-color {
|
||||
|
||||
case comm-list-name {
|
||||
when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:comm-list-delete') or "
|
||||
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:large-comm-list-delete')";
|
||||
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:large-comm-list-delete') or "
|
||||
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
|
||||
'frr-bgp-route-map:extended-comm-list-delete')";
|
||||
leaf comm-list-name {
|
||||
type bgp-filter:bgp-list-name;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user