summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2023-10-03 14:55:30 +0200
committerGitHub <noreply@github.com>2023-10-03 14:55:30 +0200
commitd6a9c7ec8776c6d937bc51c3cd4df1c1f59b5c58 (patch)
tree11b3cfcea5d76040b32c07bcca644283345693f3
parentMerge pull request #14508 from LabNConsulting/chopps/darr-use-frrmemfunc (diff)
parenttopotests: add bgp_large_comm_list_match test (diff)
downloadfrr-d6a9c7ec8776c6d937bc51c3cd4df1c1f59b5c58.tar.xz
frr-d6a9c7ec8776c6d937bc51c3cd4df1c1f59b5c58.zip
Merge pull request #13814 from pguibert6WIND/comm_list_expanded_match_no_exact
bgpd: add match community "any" to match any incoming community
-rw-r--r--bgpd/bgp_clist.c43
-rw-r--r--bgpd/bgp_clist.h4
-rw-r--r--bgpd/bgp_routemap.c161
-rw-r--r--bgpd/bgp_routemap_nb.c7
-rw-r--r--bgpd/bgp_routemap_nb.h4
-rw-r--r--bgpd/bgp_routemap_nb_config.c43
-rw-r--r--lib/routemap_cli.c8
-rw-r--r--tests/topotests/bgp_comm_list_match/r1/bgpd.conf5
-rw-r--r--tests/topotests/bgp_comm_list_match/r1/zebra.conf1
-rw-r--r--tests/topotests/bgp_comm_list_match/r2/bgpd.conf3
-rw-r--r--tests/topotests/bgp_comm_list_match/r2/zebra.conf3
-rw-r--r--tests/topotests/bgp_comm_list_match/r3/bgpd.conf21
-rw-r--r--tests/topotests/bgp_comm_list_match/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp_comm_list_match/test_bgp_comm_list_match.py36
-rw-r--r--tests/topotests/bgp_large_comm_list_match/__init__.py0
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r1/bgpd.conf28
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r1/zebra.conf12
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r2/bgpd.conf24
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r3/bgpd.conf21
-rw-r--r--tests/topotests/bgp_large_comm_list_match/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py145
-rw-r--r--yang/frr-bgp-route-map.yang7
23 files changed, 526 insertions, 71 deletions
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 3fd246397..e52230713 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -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)
@@ -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)
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
index 251169876..a435b92ce 100644
--- a/bgpd/bgp_clist.h
+++ b/bgpd/bgp_clist.h
@@ -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);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 274df5197..e0db43f67 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -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. */
@@ -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))
@@ -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);
@@ -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))
@@ -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);
@@ -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']";
@@ -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']";
@@ -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']";
@@ -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']";
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index ae695a6f8..abebfe515 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -165,6 +165,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .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 = {
.modify = lib_route_map_entry_match_condition_rmap_match_condition_ipv4_address_modify,
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index 3ff58f71a..28e418802 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -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);
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 9ef9031e5..370295b6c 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -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;
@@ -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);
+ } 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;
@@ -1218,6 +1228,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
*/
int
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index a5e66880a..20a157e95 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -729,6 +729,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-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");
} else if (IS_MATCH_LCOMMUNITY(condition)) {
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,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-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");
} else if (IS_MATCH_EXTCOMMUNITY(condition)) {
vty_out(vty, " match extcommunity %s\n",
diff --git a/tests/topotests/bgp_comm_list_match/r1/bgpd.conf b/tests/topotests/bgp_comm_list_match/r1/bgpd.conf
index 89c9f7728..bac841208 100644
--- a/tests/topotests/bgp_comm_list_match/r1/bgpd.conf
+++ b/tests/topotests/bgp_comm_list_match/r1/bgpd.conf
@@ -11,6 +11,7 @@ router bgp 65001
!
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 p4 seq 5 permit 172.16.255.4/32
!
route-map r2 permit 10
match ip address prefix-list p1
@@ -19,5 +20,9 @@ route-map r2 permit 20
match ip address prefix-list p3
set community 65001:3
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
!
diff --git a/tests/topotests/bgp_comm_list_match/r1/zebra.conf b/tests/topotests/bgp_comm_list_match/r1/zebra.conf
index 17d0eccea..4219a7ca3 100644
--- a/tests/topotests/bgp_comm_list_match/r1/zebra.conf
+++ b/tests/topotests/bgp_comm_list_match/r1/zebra.conf
@@ -3,6 +3,7 @@ interface lo
ip address 172.16.255.1/32
ip address 172.16.255.2/32
ip address 172.16.255.3/32
+ ip address 172.16.255.4/32
!
interface r1-eth0
ip address 192.168.0.1/24
diff --git a/tests/topotests/bgp_comm_list_match/r2/bgpd.conf b/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
index 98a978068..cb2f89e5c 100644
--- a/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
+++ b/tests/topotests/bgp_comm_list_match/r2/bgpd.conf
@@ -6,6 +6,9 @@ router bgp 65002
neighbor 192.168.0.1 remote-as external
neighbor 192.168.0.1 timers 1 3
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
neighbor 192.168.0.1 route-map r1 in
neighbor 192.168.0.1 soft-reconfiguration inbound
diff --git a/tests/topotests/bgp_comm_list_match/r2/zebra.conf b/tests/topotests/bgp_comm_list_match/r2/zebra.conf
index a69c62235..7fe82bac8 100644
--- a/tests/topotests/bgp_comm_list_match/r2/zebra.conf
+++ b/tests/topotests/bgp_comm_list_match/r2/zebra.conf
@@ -2,5 +2,8 @@
interface r2-eth0
ip address 192.168.0.2/24
!
+interface r2-eth1
+ ip address 192.168.1.2/24
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_comm_list_match/r3/bgpd.conf b/tests/topotests/bgp_comm_list_match/r3/bgpd.conf
new file mode 100644
index 000000000..e68a3e44e
--- /dev/null
+++ b/tests/topotests/bgp_comm_list_match/r3/bgpd.conf
@@ -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
+!
diff --git a/tests/topotests/bgp_comm_list_match/r3/zebra.conf b/tests/topotests/bgp_comm_list_match/r3/zebra.conf
new file mode 100644
index 000000000..755dd18bf
--- /dev/null
+++ b/tests/topotests/bgp_comm_list_match/r3/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 192.168.1.3/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_comm_list_match/test_bgp_comm_list_match.py b/tests/topotests/bgp_comm_list_match/test_bgp_comm_list_match.py
index 03fa8da9d..de69ea938 100644
--- a/tests/topotests/bgp_comm_list_match/test_bgp_comm_list_match.py
+++ b/tests/topotests/bgp_comm_list_match/test_bgp_comm_list_match.py
@@ -39,12 +39,15 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
- for routern in range(1, 3):
+ for routern in range(1, 4):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
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):
@@ -95,12 +98,41 @@ def test_bgp_comm_list_match():
}
return topotest.json_cmp(output, expected)
- step("Initial BGP converge")
+ step("Initial BGP converge between R1 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 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__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_large_comm_list_match/__init__.py b/tests/topotests/bgp_large_comm_list_match/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/__init__.py
diff --git a/tests/topotests/bgp_large_comm_list_match/r1/bgpd.conf b/tests/topotests/bgp_large_comm_list_match/r1/bgpd.conf
new file mode 100644
index 000000000..1a91f0f5c
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r1/bgpd.conf
@@ -0,0 +1,28 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.0.2 remote-as external
+ neighbor 192.168.0.2 timers 1 3
+ neighbor 192.168.0.2 timers connect 1
+ address-family ipv4
+ redistribute connected
+ neighbor 192.168.0.2 route-map r2 out
+ exit-address-family
+!
+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 p4 seq 5 permit 172.16.255.4/32
+!
+route-map r2 permit 10
+ match ip address prefix-list p1
+ set large-community 65001:1:1 65001:2:1
+route-map r2 permit 20
+ match ip address prefix-list p3
+ set large-community 65001:3:1
+route-map r2 permit 30
+ match ip address prefix-list p4
+ set large-community 65001:10:1 65001:12:1 65001:13:1
+exit
+route-map r2 permit 40
+exit
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/r1/zebra.conf b/tests/topotests/bgp_large_comm_list_match/r1/zebra.conf
new file mode 100644
index 000000000..4219a7ca3
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r1/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+ ip address 172.16.255.2/32
+ ip address 172.16.255.3/32
+ ip address 172.16.255.4/32
+!
+interface r1-eth0
+ ip address 192.168.0.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/r2/bgpd.conf b/tests/topotests/bgp_large_comm_list_match/r2/bgpd.conf
new file mode 100644
index 000000000..779b705b5
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r2/bgpd.conf
@@ -0,0 +1,24 @@
+!
+!debug bgp updates
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.0.1 remote-as external
+ neighbor 192.168.0.1 timers 1 3
+ 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
+ neighbor 192.168.0.1 route-map r1 in
+ neighbor 192.168.0.1 soft-reconfiguration inbound
+ exit-address-family
+!
+bgp large-community-list 1 seq 5 permit 65001:1:1 65001:2:1
+bgp large-community-list 1 seq 10 permit 65001:3:1
+!
+route-map r1 deny 10
+ match large-community 1
+route-map r1 permit 20
+exit
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/r2/zebra.conf b/tests/topotests/bgp_large_comm_list_match/r2/zebra.conf
new file mode 100644
index 000000000..7fe82bac8
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r2/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface r2-eth0
+ ip address 192.168.0.2/24
+!
+interface r2-eth1
+ ip address 192.168.1.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/r3/bgpd.conf b/tests/topotests/bgp_large_comm_list_match/r3/bgpd.conf
new file mode 100644
index 000000000..e7cb76a43
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r3/bgpd.conf
@@ -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 large-community-list 2 seq 10 permit 65001:12:1
+!
+route-map r1 deny 10
+ match large-community 2 any
+exit
+route-map r1 permit 20
+exit
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/r3/zebra.conf b/tests/topotests/bgp_large_comm_list_match/r3/zebra.conf
new file mode 100644
index 000000000..755dd18bf
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/r3/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 192.168.1.3/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
new file mode 100644
index 000000000..483c048d2
--- /dev/null
+++ b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright 2023 by 6WIND S.A.
+#
+
+"""
+Check if BGP large-community-list works
+when used as match rule in incoming route-maps.
+
+- case 1 should deny incoming updates with large-community-list 1
+bgp large-community-list 1 seq 5 permit 65001:1:1 65001:2:1
+bgp large-community-list 1 seq 10 permit 65001:3:1
+!
+route-map r1 deny 10
+ match large-community 1
+
+route-map test deny 10
+ match community 1
+
+- case 2 should deny incoming updates with any large-community-list 1
+bgp large-community-list 2 seq 10 permit 65001:12:1
+!
+route-map r1 deny 10
+ match large-community 2 any
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ 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):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_large_comm_list_match():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(
+ router.vtysh_cmd(
+ "show bgp ipv4 unicast neighbors 192.168.0.1 filtered-routes json"
+ )
+ )
+ expected = {
+ "receivedRoutes": {
+ "172.16.255.1/32": {
+ "path": "65001",
+ },
+ "172.16.255.3/32": {
+ "path": "65001",
+ },
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("BGP filtering check with large-community-list on 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 large-community-list on R2"
+
+
+def test_bgp_large_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("BGP filtering check with large-community-list on R3")
+ 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 large-community-list on R3"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index 05fe57c7d..c50c51389 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -777,6 +777,13 @@ identity set-extcommunity-color {
description
"Do exact matching of communities";
}
+
+ leaf comm-list-name-any {
+ type boolean;
+ description
+ "Do matching of any community";
+ }
+
}
}