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 Oct 2, 2023
1 parent 3651803 commit aa51100
Show file tree
Hide file tree
Showing 15 changed files with 281 additions and 71 deletions.
43 changes: 43 additions & 0 deletions bgpd/bgp_clist.c
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,27 @@ 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, 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 @@ -922,6 +943,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 == LARGE_COMMUNITY_LIST_STANDARD) &&
lcommunity_include(entry->u.lcom, ptr))
return entry->direct == COMMUNITY_PERMIT;
if ((entry->style == LARGE_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
161 changes: 92 additions & 69 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1528,7 +1528,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 @@ -1551,6 +1552,12 @@ 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 (!bgp_attr_get_community(path->attr))
return RMAP_OKAY;
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 @@ -1574,10 +1581,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 @@ -1637,6 +1649,12 @@ 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 (!bgp_attr_get_lcommunity(path->attr))
return RMAP_OKAY;
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 @@ -1660,10 +1678,15 @@ 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;
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 @@ -5493,15 +5516,15 @@ 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$exact|any$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']";
Expand All @@ -5517,35 +5540,35 @@ 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 (exact)
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 (any)
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);
}

DEFUN_YANG (no_match_community,
no_match_community_cmd,
"no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
NO_STR
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")
DEFUN_YANG(
no_match_community, no_match_community_cmd,
"no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [<exact-match$exact|any$any>]]",
NO_STR 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']";
Expand All @@ -5554,15 +5577,15 @@ 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$exact|any$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']";
Expand All @@ -5578,35 +5601,35 @@ 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 (exact)
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 (any)
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);
}

DEFUN_YANG (no_match_lcommunity,
no_match_lcommunity_cmd,
"no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
NO_STR
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")
DEFUN_YANG(
no_match_lcommunity, no_match_lcommunity_cmd,
"no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [<exact-match|any>]]",
NO_STR 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']";
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
Loading

0 comments on commit aa51100

Please sign in to comment.