Skip to content

Commit

Permalink
bgpd: add 'match community-list any' function
Browse files Browse the repository at this point in the history
There is no match mechanism to match one community from the
incoming community-list. Add the 'any' keyword to the 'match
route-map' command of communit-list and large-community-list.

> match community-list AAA any
> match large-community-list AAA any

Signed-off-by: Philippe Guibert <[email protected]>
  • Loading branch information
pguibert6WIND committed Jun 27, 2023
1 parent 2be9ce6 commit 10d10c8
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 52 deletions.
46 changes: 46 additions & 0 deletions bgpd/bgp_clist.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,30 @@ bool community_list_exact_match(struct community *com,
return false;
}

bool community_list_any_match(struct community *com,
struct community_list *list)
{
struct community_entry *entry;
uint32_t val;
int i;

for (i = 0; i < com->size; i++) {
val = community_val_get(com, i);

for (entry = list->head; entry; entry = entry->next) {
if ((entry->style == COMMUNITY_LIST_STANDARD) &&
(community_include(entry->u.com,
COMMUNITY_INTERNET) ||
community_include(entry->u.com, val)))
return entry->direct == COMMUNITY_PERMIT;
if ((entry->style == COMMUNITY_LIST_EXPANDED) &&
community_regexp_include(entry->reg, com, i))
return entry->direct == COMMUNITY_PERMIT;
}
}
return false;
}

/* Delete all permitted communities in the list from com. */
struct community *community_list_match_delete(struct community *com,
struct community_list *list)
Expand Down Expand Up @@ -938,6 +962,28 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
return 0;
}

bool lcommunity_list_any_match(struct lcommunity *lcom,
struct community_list *list)
{
struct community_entry *entry;
uint8_t *ptr;
int i;

for (i = 0; i < lcom->size; i++) {
ptr = lcom->val + (i * LCOMMUNITY_SIZE);

for (entry = list->head; entry; entry = entry->next) {
if ((entry->style == COMMUNITY_LIST_STANDARD) &&
lcommunity_include(entry->u.lcom, ptr))
return entry->direct == COMMUNITY_PERMIT;
if ((entry->style == COMMUNITY_LIST_EXPANDED) &&
lcommunity_regexp_include(entry->reg, lcom, i))
return entry->direct == COMMUNITY_PERMIT;
}
}
return false;
}

/* Delete all permitted large communities in the list from com. */
struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list)
Expand Down
4 changes: 4 additions & 0 deletions bgpd/bgp_clist.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,12 @@ extern bool community_list_exact_match(struct community *com,
struct community_list *list);
extern bool lcommunity_list_exact_match(struct lcommunity *lcom,
struct community_list *list);
extern bool community_list_any_match(struct community *com,
struct community_list *list);
extern struct community *
community_list_match_delete(struct community *com, struct community_list *list);
extern bool lcommunity_list_any_match(struct lcommunity *lcom,
struct community_list *list);
extern struct lcommunity *
lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list);
Expand Down
128 changes: 77 additions & 51 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,8 @@ static const struct route_map_rule_cmd route_match_aspath_cmd = {
struct rmap_community {
char *name;
uint32_t name_hash;
int exact;
bool exact;
bool any;
};

/* Match function for community match. */
Expand All @@ -1550,6 +1551,10 @@ route_match_community(void *rule, const struct prefix *prefix, void *object)
if (community_list_exact_match(
bgp_attr_get_community(path->attr), list))
return RMAP_MATCH;
} else if (rcom->any) {
if (community_list_any_match(bgp_attr_get_community(path->attr),
list))
return RMAP_MATCH;
} else {
if (community_list_match(bgp_attr_get_community(path->attr),
list))
Expand All @@ -1573,10 +1578,15 @@ static void *route_match_community_compile(const char *arg)
len = p - arg;
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
memcpy(rcom->name, arg, len);
rcom->exact = 1;
p++;
if (*p == 'e')
rcom->exact = true;
else
rcom->any = true;
} else {
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->exact = 0;
rcom->exact = false;
rcom->any = false;
}

rcom->name_hash = bgp_clist_hash_key(rcom->name);
Expand Down Expand Up @@ -1636,6 +1646,10 @@ route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
if (lcommunity_list_exact_match(
bgp_attr_get_lcommunity(path->attr), list))
return RMAP_MATCH;
} else if (rcom->any) {
if (lcommunity_list_any_match(
bgp_attr_get_lcommunity(path->attr), list))
return RMAP_MATCH;
} else {
if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
list))
Expand All @@ -1659,10 +1673,14 @@ static void *route_match_lcommunity_compile(const char *arg)
len = p - arg;
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
memcpy(rcom->name, arg, len);
rcom->exact = 1;
if (*p == 'e')
rcom->exact = true;
else
rcom->any = true;
} else {
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->exact = 0;
rcom->exact = false;
rcom->any = false;
}

rcom->name_hash = bgp_clist_hash_key(rcom->name);
Expand Down Expand Up @@ -5241,21 +5259,22 @@ DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
return nb_cli_apply_changes(vty, NULL);
}

DEFPY_YANG (match_community,
match_community_cmd,
"match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
MATCH_STR
"Match BGP community list\n"
"Community-list number (standard)\n"
"Community-list number (expanded)\n"
"Community-list name\n"
"Do exact matching of communities\n")
DEFPY_YANG(
match_community, match_community_cmd,
"match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [<exact-match|any>]",
MATCH_STR
"Match BGP community list\n"
"Community-list number (standard)\n"
"Community-list number (expanded)\n"
"Community-list name\n"
"Do exact matching of communities\n"
"Do matching of any community\n")
{
const char *xpath =
"./match-condition[condition='frr-bgp-route-map:match-community']";
char xpath_value[XPATH_MAXLEN];
char xpath_match[XPATH_MAXLEN];
int idx_comm_list = 2;
int idx_comm_list = 2, idx;

nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);

Expand All @@ -5265,21 +5284,24 @@ DEFPY_YANG (match_community,
xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);

if (argc == 4) {
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
if (argv_find(argv, argc, "exact-match", &idx))
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
"true");
} else {
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
"false");
}
else
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");

snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any",
xpath);
if (argv_find(argv, argc, "any", &idx))
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "true");
else
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");

return nb_cli_apply_changes(vty, NULL);
}
Expand All @@ -5302,21 +5324,22 @@ DEFUN_YANG (no_match_community,
return nb_cli_apply_changes(vty, NULL);
}

DEFPY_YANG (match_lcommunity,
match_lcommunity_cmd,
"match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
MATCH_STR
"Match BGP large community list\n"
"Large Community-list number (standard)\n"
"Large Community-list number (expanded)\n"
"Large Community-list name\n"
"Do exact matching of communities\n")
DEFPY_YANG(
match_lcommunity, match_lcommunity_cmd,
"match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [<exact-match|any>]",
MATCH_STR
"Match BGP large community list\n"
"Large Community-list number (standard)\n"
"Large Community-list number (expanded)\n"
"Large Community-list name\n"
"Do exact matching of communities\n"
"Do matching of any community\n")
{
const char *xpath =
"./match-condition[condition='frr-bgp-route-map:match-large-community']";
char xpath_value[XPATH_MAXLEN];
char xpath_match[XPATH_MAXLEN];
int idx_lcomm_list = 2;
int idx_lcomm_list = 2, idx;

nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);

Expand All @@ -5326,21 +5349,24 @@ DEFPY_YANG (match_lcommunity,
xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);

if (argc == 4) {
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
if (argv_find(argv, argc, "exact-match", &idx))
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
"true");
} else {
snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
xpath);
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
"false");
}
else
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");

snprintf(
xpath_match, sizeof(xpath_match),
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any",
xpath);
if (argv_find(argv, argc, "any", &idx))
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "true");
else
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");

return nb_cli_apply_changes(vty, NULL);
}
Expand Down
7 changes: 7 additions & 0 deletions bgpd/bgp_routemap_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_exact_match_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any",
.cbs = {
.modify = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_modify,
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_destroy,
}
},
{
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:ipv4-address",
.cbs = {
Expand Down
4 changes: 4 additions & 0 deletions bgpd/bgp_routemap_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_exact_match_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_exact_match_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_modify(
struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_destroy(
struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_ipv4_address_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_ipv4_address_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_ipv6_address_modify(struct nb_cb_modify_args *args);
Expand Down
45 changes: 44 additions & 1 deletion bgpd/bgp_routemap_nb_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
struct routemap_hook_context *rhc;
const char *value;
bool exact_match = false;
bool any = false;
char *argstr;
const char *condition;
route_map_event_t event;
Expand All @@ -1140,12 +1141,21 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
exact_match = yang_dnode_get_bool(
args->dnode, "./comm-list-name-exact-match");

if (yang_dnode_exists(args->dnode, "./comm-list-name-any"))
any = yang_dnode_get_bool(args->dnode, "./comm-list-name-any");

if (exact_match) {
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
strlen(value) + strlen("exact-match") + 2);

snprintf(argstr, (strlen(value) + strlen("exact-match") + 2),
"%s exact-match", value);
"%s any", value);
} else if (any) {
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
strlen(value) + strlen("any") + 2);

snprintf(argstr, (strlen(value) + strlen("any") + 2), "%s any",
value);
} else
argstr = (char *)value;

Expand Down Expand Up @@ -1217,6 +1227,39 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_nam

}

/*
* XPath:
* /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any
*/
int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_modify(
struct nb_cb_modify_args *args)
{
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
case NB_EV_APPLY:
break;
}

return NB_OK;
}

int lib_route_map_entry_match_condition_rmap_match_condition_comm_list_comm_list_name_any_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/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match
*/
Expand Down
6 changes: 6 additions & 0 deletions yang/frr-bgp-route-map.yang
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,12 @@ module frr-bgp-route-map {
description
"Do exact matching of communities";
}
leaf comm-list-name-any {
type boolean;
description
"Do matching of any community";
}

}
}

Expand Down

0 comments on commit 10d10c8

Please sign in to comment.