mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 10:49:24 +00:00
bgpd: add 'match community-list any' function
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 <philippe.guibert@6wind.com>
This commit is contained in:
parent
3651803221
commit
aa511000e0
@ -735,6 +735,27 @@ bool community_list_exact_match(struct community *com,
|
|||||||
return false;
|
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. */
|
/* Delete all permitted communities in the list from com. */
|
||||||
struct community *community_list_match_delete(struct community *com,
|
struct community *community_list_match_delete(struct community *com,
|
||||||
struct community_list *list)
|
struct community_list *list)
|
||||||
@ -922,6 +943,28 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
|
|||||||
return 0;
|
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. */
|
/* Delete all permitted large communities in the list from com. */
|
||||||
struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
|
struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
|
||||||
struct community_list *list)
|
struct community_list *list)
|
||||||
|
@ -158,8 +158,12 @@ extern bool community_list_exact_match(struct community *com,
|
|||||||
struct community_list *list);
|
struct community_list *list);
|
||||||
extern bool lcommunity_list_exact_match(struct lcommunity *lcom,
|
extern bool lcommunity_list_exact_match(struct lcommunity *lcom,
|
||||||
struct community_list *list);
|
struct community_list *list);
|
||||||
|
extern bool community_list_any_match(struct community *com,
|
||||||
|
struct community_list *list);
|
||||||
extern struct community *
|
extern struct community *
|
||||||
community_list_match_delete(struct community *com, struct community_list *list);
|
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 *
|
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);
|
||||||
|
@ -1528,7 +1528,8 @@ static const struct route_map_rule_cmd route_match_aspath_cmd = {
|
|||||||
struct rmap_community {
|
struct rmap_community {
|
||||||
char *name;
|
char *name;
|
||||||
uint32_t name_hash;
|
uint32_t name_hash;
|
||||||
int exact;
|
bool exact;
|
||||||
|
bool any;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Match function for community match. */
|
/* Match function for community match. */
|
||||||
@ -1551,6 +1552,12 @@ route_match_community(void *rule, const struct prefix *prefix, void *object)
|
|||||||
if (community_list_exact_match(
|
if (community_list_exact_match(
|
||||||
bgp_attr_get_community(path->attr), list))
|
bgp_attr_get_community(path->attr), list))
|
||||||
return RMAP_MATCH;
|
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 {
|
} else {
|
||||||
if (community_list_match(bgp_attr_get_community(path->attr),
|
if (community_list_match(bgp_attr_get_community(path->attr),
|
||||||
list))
|
list))
|
||||||
@ -1574,10 +1581,15 @@ static void *route_match_community_compile(const char *arg)
|
|||||||
len = p - arg;
|
len = p - arg;
|
||||||
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
||||||
memcpy(rcom->name, arg, len);
|
memcpy(rcom->name, arg, len);
|
||||||
rcom->exact = 1;
|
p++;
|
||||||
|
if (*p == 'e')
|
||||||
|
rcom->exact = true;
|
||||||
|
else
|
||||||
|
rcom->any = true;
|
||||||
} else {
|
} else {
|
||||||
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
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);
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
||||||
@ -1637,6 +1649,12 @@ route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
|
|||||||
if (lcommunity_list_exact_match(
|
if (lcommunity_list_exact_match(
|
||||||
bgp_attr_get_lcommunity(path->attr), list))
|
bgp_attr_get_lcommunity(path->attr), list))
|
||||||
return RMAP_MATCH;
|
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 {
|
} else {
|
||||||
if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
|
if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
|
||||||
list))
|
list))
|
||||||
@ -1660,10 +1678,15 @@ static void *route_match_lcommunity_compile(const char *arg)
|
|||||||
len = p - arg;
|
len = p - arg;
|
||||||
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
||||||
memcpy(rcom->name, arg, len);
|
memcpy(rcom->name, arg, len);
|
||||||
rcom->exact = 1;
|
p++;
|
||||||
|
if (*p == 'e')
|
||||||
|
rcom->exact = true;
|
||||||
|
else
|
||||||
|
rcom->any = true;
|
||||||
} else {
|
} else {
|
||||||
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
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);
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
||||||
@ -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);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG (match_community,
|
DEFPY_YANG(
|
||||||
match_community_cmd,
|
match_community, match_community_cmd,
|
||||||
"match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
|
"match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [<exact-match$exact|any$any>]",
|
||||||
MATCH_STR
|
MATCH_STR "Match BGP community list\n"
|
||||||
"Match BGP community list\n"
|
|
||||||
"Community-list number (standard)\n"
|
"Community-list number (standard)\n"
|
||||||
"Community-list number (expanded)\n"
|
"Community-list number (expanded)\n"
|
||||||
"Community-list name\n"
|
"Community-list name\n"
|
||||||
"Do exact matching of communities\n")
|
"Do exact matching of communities\n"
|
||||||
|
"Do matching of any community\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./match-condition[condition='frr-bgp-route-map:match-community']";
|
"./match-condition[condition='frr-bgp-route-map:match-community']";
|
||||||
@ -5517,35 +5540,35 @@ DEFPY_YANG (match_community,
|
|||||||
xpath);
|
xpath);
|
||||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
|
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
|
||||||
|
|
||||||
if (argc == 4) {
|
snprintf(xpath_match, sizeof(xpath_match),
|
||||||
snprintf(
|
|
||||||
xpath_match, sizeof(xpath_match),
|
|
||||||
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
||||||
xpath);
|
xpath);
|
||||||
|
if (exact)
|
||||||
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
||||||
"true");
|
"true");
|
||||||
} else {
|
else
|
||||||
snprintf(
|
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");
|
||||||
xpath_match, sizeof(xpath_match),
|
|
||||||
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
snprintf(xpath_match, sizeof(xpath_match),
|
||||||
|
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any",
|
||||||
xpath);
|
xpath);
|
||||||
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
if (any)
|
||||||
"false");
|
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);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN_YANG (no_match_community,
|
DEFUN_YANG(
|
||||||
no_match_community_cmd,
|
no_match_community, no_match_community_cmd,
|
||||||
"no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
|
"no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [<exact-match$exact|any$any>]]",
|
||||||
NO_STR
|
NO_STR MATCH_STR "Match BGP community list\n"
|
||||||
MATCH_STR
|
|
||||||
"Match BGP community list\n"
|
|
||||||
"Community-list number (standard)\n"
|
"Community-list number (standard)\n"
|
||||||
"Community-list number (expanded)\n"
|
"Community-list number (expanded)\n"
|
||||||
"Community-list name\n"
|
"Community-list name\n"
|
||||||
"Do exact matching of communities\n")
|
"Do exact matching of communities\n"
|
||||||
|
"Do matching of any community\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./match-condition[condition='frr-bgp-route-map:match-community']";
|
"./match-condition[condition='frr-bgp-route-map:match-community']";
|
||||||
@ -5554,15 +5577,15 @@ DEFUN_YANG (no_match_community,
|
|||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG (match_lcommunity,
|
DEFPY_YANG(
|
||||||
match_lcommunity_cmd,
|
match_lcommunity, match_lcommunity_cmd,
|
||||||
"match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
|
"match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [<exact-match$exact|any$any>]",
|
||||||
MATCH_STR
|
MATCH_STR "Match BGP large community list\n"
|
||||||
"Match BGP large community list\n"
|
|
||||||
"Large Community-list number (standard)\n"
|
"Large Community-list number (standard)\n"
|
||||||
"Large Community-list number (expanded)\n"
|
"Large Community-list number (expanded)\n"
|
||||||
"Large Community-list name\n"
|
"Large Community-list name\n"
|
||||||
"Do exact matching of communities\n")
|
"Do exact matching of communities\n"
|
||||||
|
"Do matching of any community\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./match-condition[condition='frr-bgp-route-map:match-large-community']";
|
"./match-condition[condition='frr-bgp-route-map:match-large-community']";
|
||||||
@ -5578,35 +5601,35 @@ DEFPY_YANG (match_lcommunity,
|
|||||||
xpath);
|
xpath);
|
||||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
|
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
|
||||||
|
|
||||||
if (argc == 4) {
|
snprintf(xpath_match, sizeof(xpath_match),
|
||||||
snprintf(
|
|
||||||
xpath_match, sizeof(xpath_match),
|
|
||||||
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
||||||
xpath);
|
xpath);
|
||||||
|
if (exact)
|
||||||
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
||||||
"true");
|
"true");
|
||||||
} else {
|
else
|
||||||
snprintf(
|
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY, "false");
|
||||||
xpath_match, sizeof(xpath_match),
|
|
||||||
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
|
snprintf(xpath_match, sizeof(xpath_match),
|
||||||
|
"%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any",
|
||||||
xpath);
|
xpath);
|
||||||
nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
|
if (any)
|
||||||
"false");
|
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);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN_YANG (no_match_lcommunity,
|
DEFUN_YANG(
|
||||||
no_match_lcommunity_cmd,
|
no_match_lcommunity, no_match_lcommunity_cmd,
|
||||||
"no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
|
"no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [<exact-match|any>]]",
|
||||||
NO_STR
|
NO_STR MATCH_STR "Match BGP large community list\n"
|
||||||
MATCH_STR
|
|
||||||
"Match BGP large community list\n"
|
|
||||||
"Large Community-list number (standard)\n"
|
"Large Community-list number (standard)\n"
|
||||||
"Large Community-list number (expanded)\n"
|
"Large Community-list number (expanded)\n"
|
||||||
"Large Community-list name\n"
|
"Large Community-list name\n"
|
||||||
"Do exact matching of communities\n")
|
"Do exact matching of communities\n"
|
||||||
|
"Do matching of any community\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./match-condition[condition='frr-bgp-route-map:match-large-community']";
|
"./match-condition[condition='frr-bgp-route-map:match-large-community']";
|
||||||
|
@ -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,
|
.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",
|
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:ipv4-address",
|
||||||
.cbs = {
|
.cbs = {
|
||||||
|
@ -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_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_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_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_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_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);
|
int lib_route_map_entry_match_condition_rmap_match_condition_ipv6_address_modify(struct nb_cb_modify_args *args);
|
||||||
|
@ -1127,6 +1127,7 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
|
|||||||
struct routemap_hook_context *rhc;
|
struct routemap_hook_context *rhc;
|
||||||
const char *value;
|
const char *value;
|
||||||
bool exact_match = false;
|
bool exact_match = false;
|
||||||
|
bool any = false;
|
||||||
char *argstr;
|
char *argstr;
|
||||||
const char *condition;
|
const char *condition;
|
||||||
route_map_event_t event;
|
route_map_event_t event;
|
||||||
@ -1140,12 +1141,21 @@ lib_route_map_entry_match_condition_rmap_match_condition_comm_list_finish(
|
|||||||
exact_match = yang_dnode_get_bool(
|
exact_match = yang_dnode_get_bool(
|
||||||
args->dnode, "./comm-list-name-exact-match");
|
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) {
|
if (exact_match) {
|
||||||
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
||||||
strlen(value) + strlen("exact-match") + 2);
|
strlen(value) + strlen("exact-match") + 2);
|
||||||
|
|
||||||
snprintf(argstr, (strlen(value) + strlen("exact-match") + 2),
|
snprintf(argstr, (strlen(value) + strlen("exact-match") + 2),
|
||||||
"%s exact-match", value);
|
"%s exact-match", 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
|
} else
|
||||||
argstr = (char *)value;
|
argstr = (char *)value;
|
||||||
|
|
||||||
@ -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
|
* XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match
|
||||||
*/
|
*/
|
||||||
|
@ -729,6 +729,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
|
|||||||
dnode,
|
dnode,
|
||||||
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
|
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
|
||||||
vty_out(vty, " exact-match");
|
vty_out(vty, " exact-match");
|
||||||
|
if (yang_dnode_get_bool(
|
||||||
|
dnode,
|
||||||
|
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any"))
|
||||||
|
vty_out(vty, " any");
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
} else if (IS_MATCH_LCOMMUNITY(condition)) {
|
} else if (IS_MATCH_LCOMMUNITY(condition)) {
|
||||||
vty_out(vty, " match large-community %s",
|
vty_out(vty, " match large-community %s",
|
||||||
@ -739,6 +743,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
|
|||||||
dnode,
|
dnode,
|
||||||
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
|
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
|
||||||
vty_out(vty, " exact-match");
|
vty_out(vty, " exact-match");
|
||||||
|
if (yang_dnode_get_bool(
|
||||||
|
dnode,
|
||||||
|
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-any"))
|
||||||
|
vty_out(vty, " any");
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
} else if (IS_MATCH_EXTCOMMUNITY(condition)) {
|
} else if (IS_MATCH_EXTCOMMUNITY(condition)) {
|
||||||
vty_out(vty, " match extcommunity %s\n",
|
vty_out(vty, " match extcommunity %s\n",
|
||||||
|
@ -11,6 +11,7 @@ router bgp 65001
|
|||||||
!
|
!
|
||||||
ip prefix-list p1 seq 5 permit 172.16.255.1/32
|
ip prefix-list p1 seq 5 permit 172.16.255.1/32
|
||||||
ip prefix-list p3 seq 5 permit 172.16.255.3/32
|
ip prefix-list p3 seq 5 permit 172.16.255.3/32
|
||||||
|
ip prefix-list p4 seq 5 permit 172.16.255.4/32
|
||||||
!
|
!
|
||||||
route-map r2 permit 10
|
route-map r2 permit 10
|
||||||
match ip address prefix-list p1
|
match ip address prefix-list p1
|
||||||
@ -19,5 +20,9 @@ route-map r2 permit 20
|
|||||||
match ip address prefix-list p3
|
match ip address prefix-list p3
|
||||||
set community 65001:3
|
set community 65001:3
|
||||||
route-map r2 permit 30
|
route-map r2 permit 30
|
||||||
|
match ip address prefix-list p4
|
||||||
|
set community 65001:10 65001:12 65001:13
|
||||||
|
exit
|
||||||
|
route-map r2 permit 40
|
||||||
exit
|
exit
|
||||||
!
|
!
|
||||||
|
@ -3,6 +3,7 @@ interface lo
|
|||||||
ip address 172.16.255.1/32
|
ip address 172.16.255.1/32
|
||||||
ip address 172.16.255.2/32
|
ip address 172.16.255.2/32
|
||||||
ip address 172.16.255.3/32
|
ip address 172.16.255.3/32
|
||||||
|
ip address 172.16.255.4/32
|
||||||
!
|
!
|
||||||
interface r1-eth0
|
interface r1-eth0
|
||||||
ip address 192.168.0.1/24
|
ip address 192.168.0.1/24
|
||||||
|
@ -6,6 +6,9 @@ router bgp 65002
|
|||||||
neighbor 192.168.0.1 remote-as external
|
neighbor 192.168.0.1 remote-as external
|
||||||
neighbor 192.168.0.1 timers 1 3
|
neighbor 192.168.0.1 timers 1 3
|
||||||
neighbor 192.168.0.1 timers connect 1
|
neighbor 192.168.0.1 timers connect 1
|
||||||
|
neighbor 192.168.1.3 remote-as external
|
||||||
|
neighbor 192.168.1.3 timers 1 3
|
||||||
|
neighbor 192.168.1.3 timers connect 1
|
||||||
address-family ipv4
|
address-family ipv4
|
||||||
neighbor 192.168.0.1 route-map r1 in
|
neighbor 192.168.0.1 route-map r1 in
|
||||||
neighbor 192.168.0.1 soft-reconfiguration inbound
|
neighbor 192.168.0.1 soft-reconfiguration inbound
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
interface r2-eth0
|
interface r2-eth0
|
||||||
ip address 192.168.0.2/24
|
ip address 192.168.0.2/24
|
||||||
!
|
!
|
||||||
|
interface r2-eth1
|
||||||
|
ip address 192.168.1.2/24
|
||||||
|
!
|
||||||
ip forwarding
|
ip forwarding
|
||||||
!
|
!
|
||||||
|
21
tests/topotests/bgp_comm_list_match/r3/bgpd.conf
Normal file
21
tests/topotests/bgp_comm_list_match/r3/bgpd.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
!
|
||||||
|
!debug bgp updates
|
||||||
|
!
|
||||||
|
router bgp 65003
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
neighbor 192.168.1.2 remote-as external
|
||||||
|
neighbor 192.168.1.2 timers 1 3
|
||||||
|
neighbor 192.168.1.2 timers connect 1
|
||||||
|
address-family ipv4
|
||||||
|
neighbor 192.168.1.2 route-map r1 in
|
||||||
|
neighbor 192.168.1.2 soft-reconfiguration inbound
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
bgp community-list 2 seq 10 permit 65001:12
|
||||||
|
!
|
||||||
|
route-map r1 deny 10
|
||||||
|
match community 2 any
|
||||||
|
exit
|
||||||
|
route-map r1 permit 20
|
||||||
|
exit
|
||||||
|
!
|
6
tests/topotests/bgp_comm_list_match/r3/zebra.conf
Normal file
6
tests/topotests/bgp_comm_list_match/r3/zebra.conf
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
!
|
||||||
|
interface r3-eth0
|
||||||
|
ip address 192.168.1.3/24
|
||||||
|
!
|
||||||
|
ip forwarding
|
||||||
|
!
|
@ -39,12 +39,15 @@ pytestmark = [pytest.mark.bgpd]
|
|||||||
|
|
||||||
|
|
||||||
def build_topo(tgen):
|
def build_topo(tgen):
|
||||||
for routern in range(1, 3):
|
for routern in range(1, 4):
|
||||||
tgen.add_router("r{}".format(routern))
|
tgen.add_router("r{}".format(routern))
|
||||||
|
|
||||||
switch = tgen.add_switch("s1")
|
switch = tgen.add_switch("s1")
|
||||||
switch.add_link(tgen.gears["r1"])
|
switch.add_link(tgen.gears["r1"])
|
||||||
switch.add_link(tgen.gears["r2"])
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
switch = tgen.add_switch("s2")
|
||||||
|
switch.add_link(tgen.gears["r3"])
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
@ -95,12 +98,41 @@ def test_bgp_comm_list_match():
|
|||||||
}
|
}
|
||||||
return topotest.json_cmp(output, expected)
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
step("Initial BGP converge")
|
step("Initial BGP converge between R1 and R2")
|
||||||
test_func = functools.partial(_bgp_converge)
|
test_func = functools.partial(_bgp_converge)
|
||||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
assert result is None, "Failed to filter BGP UPDATES with community-list on R2"
|
assert result is None, "Failed to filter BGP UPDATES with community-list on R2"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bgp_comm_list_match_any():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
router = tgen.gears["r3"]
|
||||||
|
|
||||||
|
def _bgp_converge():
|
||||||
|
output = json.loads(
|
||||||
|
router.vtysh_cmd(
|
||||||
|
"show bgp ipv4 unicast neighbors 192.168.1.2 filtered-routes json"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
expected = {
|
||||||
|
"receivedRoutes": {
|
||||||
|
"172.16.255.4/32": {
|
||||||
|
"path": "65002 65001",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
step("Initial BGP converge between R3 and R2")
|
||||||
|
test_func = functools.partial(_bgp_converge)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Failed to filter BGP UPDATES with community-list on R3"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
sys.exit(pytest.main(args))
|
sys.exit(pytest.main(args))
|
||||||
|
@ -777,6 +777,13 @@ identity set-extcommunity-color {
|
|||||||
description
|
description
|
||||||
"Do exact matching of communities";
|
"Do exact matching of communities";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaf comm-list-name-any {
|
||||||
|
type boolean;
|
||||||
|
description
|
||||||
|
"Do matching of any community";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user