mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 19:06:07 +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;
|
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 */
|
/* Helper to check if every octet do not exceed UINT_MAX */
|
||||||
bool lcommunity_list_valid(const char *community, int style)
|
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 *
|
extern struct lcommunity *
|
||||||
lcommunity_list_match_delete(struct lcommunity *lcom,
|
lcommunity_list_match_delete(struct lcommunity *lcom,
|
||||||
struct community_list *list);
|
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)
|
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,
|
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' */
|
/* `set extcommunity rt COMMUNITY' */
|
||||||
|
|
||||||
struct rmap_ecom_set {
|
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,
|
DEFUN_YANG (match_aspath,
|
||||||
match_aspath_cmd,
|
match_aspath_cmd,
|
||||||
"match as-path AS_PATH_FILTER_NAME",
|
"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_aggregator_as_cmd);
|
||||||
route_map_install_set(&route_set_community_cmd);
|
route_map_install_set(&route_set_community_cmd);
|
||||||
route_map_install_set(&route_set_community_delete_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_cmd);
|
||||||
route_map_install_set(&route_set_lcommunity_delete_cmd);
|
route_map_install_set(&route_set_lcommunity_delete_cmd);
|
||||||
route_map_install_set(&route_set_vpnv4_nexthop_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, &set_ecommunity_color_cmd);
|
||||||
install_element(RMAP_NODE, &no_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, &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
|
#ifdef KEEP_OLD_VPN_COMMANDS
|
||||||
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
|
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
|
||||||
install_element(RMAP_NODE, &no_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");
|
"../../frr-route-map:action");
|
||||||
if (IS_SET_COMM_LIST_DEL(action))
|
if (IS_SET_COMM_LIST_DEL(action))
|
||||||
rhc->rhc_rule = "comm-list";
|
rhc->rhc_rule = "comm-list";
|
||||||
|
else if (IS_SET_EXTCOMM_LIST_DEL(action))
|
||||||
|
rhc->rhc_rule = "extended-comm-list";
|
||||||
else
|
else
|
||||||
rhc->rhc_rule = "large-comm-list";
|
rhc->rhc_rule = "large-comm-list";
|
||||||
|
|
||||||
|
@ -335,6 +335,10 @@ Route Map Set Command
|
|||||||
|
|
||||||
Set the BGP community attribute.
|
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
|
.. clicmd:: set ipv6 next-hop local IPV6_ADDRESS
|
||||||
|
|
||||||
Set the BGP-4+ link local IPv6 nexthop 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_AANN_STR "Community number where AA and NN are (0-65535)\n"
|
||||||
#define COMMUNITY_VAL_STR \
|
#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"
|
"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 MPLS_TE_STR "MPLS-TE specific commands\n"
|
||||||
#define LINK_PARAMS_STR "Configure interface link parameters\n"
|
#define LINK_PARAMS_STR "Configure interface link parameters\n"
|
||||||
#define OSPF_RI_STR "OSPF Router Information specific commands\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"))
|
(strmatch(A, "frr-bgp-route-map:comm-list-delete"))
|
||||||
#define IS_SET_LCOMM_LIST_DEL(A) \
|
#define IS_SET_LCOMM_LIST_DEL(A) \
|
||||||
(strmatch(A, "frr-bgp-route-map:large-comm-list-delete"))
|
(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) \
|
#define IS_SET_LCOMMUNITY(A) \
|
||||||
(strmatch(A, "frr-bgp-route-map:set-large-community"))
|
(strmatch(A, "frr-bgp-route-map:set-large-community"))
|
||||||
#define IS_SET_COMMUNITY(A) \
|
#define IS_SET_COMMUNITY(A) \
|
||||||
|
@ -1186,6 +1186,16 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
|
|||||||
assert(acl);
|
assert(acl);
|
||||||
|
|
||||||
vty_out(vty, " set large-comm-list %s delete\n", 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)) {
|
} else if (IS_SET_LCOMMUNITY(action)) {
|
||||||
if (yang_dnode_exists(
|
if (yang_dnode_exists(
|
||||||
dnode,
|
dnode,
|
||||||
|
@ -352,6 +352,12 @@ identity set-extcommunity-color {
|
|||||||
"Set BGP large community list (for deletion)";
|
"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 {
|
identity set-evpn-gateway-ip-ipv4 {
|
||||||
base frr-route-map:rmap-set-type;
|
base frr-route-map:rmap-set-type;
|
||||||
description
|
description
|
||||||
@ -1109,7 +1115,9 @@ identity set-extcommunity-color {
|
|||||||
|
|
||||||
case comm-list-name {
|
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 "
|
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 {
|
leaf comm-list-name {
|
||||||
type bgp-filter:bgp-list-name;
|
type bgp-filter:bgp-list-name;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user