summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Ryzhov <iryzhov@nfware.com>2021-11-24 19:38:07 +0300
committerGitHub <noreply@github.com>2021-11-24 19:38:07 +0300
commitaf36ea8434c227efea3e130fd72429b73c5f833c (patch)
treee90f5e2b3f2bd739ddd312eee07e55464a3266cb
parent1b5a41b41e7a0e0edddb094a74211d978afa6b43 (diff)
parentc75d6ccbfe95d2708618ade7cc7198e46ee467dd (diff)
Merge pull request #10121 from ton31337/feature/match_ipv6_nexthop_prefixlist
bgpd: Add an ability to match ipv6 next-hop by prefix-list
-rw-r--r--bgpd/bgp_routemap.c96
-rw-r--r--doc/user/routemap.rst4
-rw-r--r--lib/routemap.c16
-rw-r--r--lib/routemap.h25
-rw-r--r--lib/routemap_cli.c4
-rw-r--r--lib/routemap_northbound.c10
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/__init__.py)0
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/bgpd.conf)5
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/zebra.conf)0
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/bgpd.conf)4
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/zebra.conf)1
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py (renamed from tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/test_bgp_route_map_match_ipv6_nexthop_access_list.py)7
-rw-r--r--yang/frr-route-map.yang7
13 files changed, 178 insertions, 1 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index b2eb70a9cc..2a1dc1896c 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -725,6 +725,57 @@ static const struct route_map_rule_cmd
route_match_ip_next_hop_prefix_list_free
};
+/* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct prefix_list *plist;
+ struct bgp_path_info *path;
+ struct prefix_ipv6 p;
+
+ if (prefix->family == AF_INET6) {
+ path = object;
+ p.family = AF_INET6;
+ p.prefix = path->attr->mp_nexthop_global;
+ p.prefixlen = IPV6_MAX_BITLEN;
+
+ plist = prefix_list_lookup(AFI_IP6, (char *)rule);
+ if (!plist)
+ return RMAP_NOMATCH;
+
+ if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+ return RMAP_MATCH;
+
+ if (path->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ p.prefix = path->attr->mp_nexthop_local;
+ if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
+ return RMAP_MATCH;
+ }
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd
+ route_match_ipv6_next_hop_prefix_list_cmd = {
+ "ipv6 next-hop prefix-list",
+ route_match_ipv6_next_hop_prefix_list,
+ route_match_ipv6_next_hop_prefix_list_compile,
+ route_match_ipv6_next_hop_prefix_list_free
+};
+
/* `match ip next-hop type <blackhole>' */
static enum route_map_cmd_result_t
@@ -6189,6 +6240,45 @@ ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
"Match IPv6 next-hop address of route\n"
"IPv6 address of next hop\n")
+DEFUN_YANG (match_ipv6_next_hop_prefix_list,
+ match_ipv6_next_hop_prefix_list_cmd,
+ "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "Match entries by prefix-list\n"
+ "IPv6 prefix-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/list-name", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[argc - 1]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
+ no_match_ipv6_next_hop_prefix_list_cmd,
+ "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "Match entries by prefix-list\n"
+ "IPv6 prefix-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFPY_YANG (match_ipv4_next_hop,
match_ipv4_next_hop_cmd,
"match ip next-hop address A.B.C.D",
@@ -6566,6 +6656,9 @@ void bgp_route_map_init(void)
route_map_match_ipv6_next_hop_type_hook(generic_match_add);
route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+ route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
+ route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
+
route_map_match_metric_hook(generic_match_add);
route_map_no_match_metric_hook(generic_match_delete);
@@ -6749,6 +6842,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_next_hop_cmd);
route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
+ route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ipv4_next_hop_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
@@ -6759,8 +6853,10 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
+ install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index d99911dc02..01d3501333 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -160,6 +160,10 @@ Route Map Match Command
This is a BGP specific match command. Matches the specified `ipv6_addr`.
+.. clicmd:: match ipv6 next-hop prefix-list PREFIX_LIST
+
+ Match the next-hop according to the given prefix-list.
+
.. clicmd:: match as-path AS_PATH
Matches the specified `as_path`.
diff --git a/lib/routemap.c b/lib/routemap.c
index c4651f39a4..7f733c8114 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -282,6 +282,22 @@ void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
}
+/* match ipv6 next-hop prefix-list */
+void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.match_ipv6_next_hop_prefix_list = func;
+}
+
+/* no match ipv6 next-hop prefix-list */
+void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list = func;
+}
+
/* match metric */
void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
diff --git a/lib/routemap.h b/lib/routemap.h
index 675f89ba92..6c4916898a 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -252,6 +252,8 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(C, "frr-route-map:ipv6-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-prefix-list"))
+#define IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-prefix-list"))
#define IS_MATCH_IPv4_NEXTHOP_TYPE(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-type"))
#define IS_MATCH_IPv6_NEXTHOP_TYPE(C) \
@@ -617,6 +619,14 @@ extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type,
char *errmsg, size_t errmsg_len));
+/* match ipv6 next-hop prefix-list */
+extern void route_map_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
+/* no match ipv6 next-hop prefix-list */
+extern void route_map_no_match_ipv6_next_hop_prefix_list_hook(int (*func)(
+ struct route_map_index *index, const char *command, const char *arg,
+ route_map_event_t type, char *errmsg, size_t errmsg_len));
/* match metric */
extern void route_map_match_metric_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -764,6 +774,21 @@ struct route_map_match_set_hooks {
route_map_event_t type, char *errmsg,
size_t errmsg_len);
+ /* match ipv6 next hop prefix-list */
+ int (*match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg, size_t errmsg_len);
+
+ /* no match ipv6 next-hop prefix-list */
+ int (*no_match_ipv6_next_hop_prefix_list)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ route_map_event_t type,
+ char *errmsg,
+ size_t errmsg_len);
+
/* match ip next hop prefix list */
int (*match_ip_next_hop_prefix_list)(struct route_map_index *index,
const char *command,
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index 552ba565b4..52fcaaba53 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -575,6 +575,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
vty_out(vty, " match ip next-hop prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ vty_out(vty, " match ipv6 next-hop prefix-list %s\n",
+ yang_dnode_get_string(
+ dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
vty_out(vty, " match ipv6 address %s\n",
yang_dnode_get_string(
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 7f7bc9f9c4..51b879959f 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -622,6 +622,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop prefix-list", acl,
RMAP_EVENT_PLIST_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop_prefix_list == NULL)
+ return NB_OK;
+ rhc->rhc_mhook =
+ rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list;
+ rhc->rhc_rule = "ipv6 next-hop prefix-list";
+ rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop_prefix_list(
+ rhc->rhc_rmi, "ipv6 next-hop prefix-list", acl,
+ RMAP_EVENT_PLIST_ADDED, args->errmsg, args->errmsg_len);
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
if (rmap_match_set_hook.match_ipv6_address == NULL)
return NB_OK;
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/__init__.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/__init__.py
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/__init__.py
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
index 5f35d353f4..c2a49252d6 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/bgpd.conf
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/bgpd.conf
@@ -3,6 +3,8 @@ ipv6 access-list nh1 permit 2001:db8:1::/64
ipv6 access-list nh2 permit 2001:db8:2::/64
ipv6 access-list nh3 permit 2001:db8:3::/64
!
+ipv6 prefix-list nh4 permit 2001:db8:5::/64 le 128
+!
router bgp 65001
bgp router-id 10.10.10.1
no bgp ebgp-requires-policy
@@ -24,4 +26,7 @@ route-map r2 permit 30
route-map r2 permit 40
match ipv6 next-hop address 2001:db8:4::1
set community 65002:4
+route-map r2 permit 50
+ match ipv6 next-hop prefix-list nh4
+ set community 65002:5
!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
index 1d4374bd8f..1d4374bd8f 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r1/zebra.conf
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r1/zebra.conf
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/bgpd.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
index bca67c5363..19dcf3664b 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/bgpd.conf
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/bgpd.conf
@@ -13,6 +13,7 @@ ipv6 prefix-list p1 permit 2001:db8:1::1/128
ipv6 prefix-list p2 permit 2001:db8:2::1/128
ipv6 prefix-list p3 permit 2001:db8:3::1/128
ipv6 prefix-list p4 permit 2001:db8:4::1/128
+ipv6 prefix-list p5 permit 2001:db8:5::1/128
!
route-map r1 permit 10
match ipv6 address prefix-list p1
@@ -26,4 +27,7 @@ route-map r1 permit 30
route-map r1 permit 40
match ipv6 address prefix-list p4
set ipv6 next-hop global 2001:db8:4::1
+route-map r1 permit 50
+ match ipv6 address prefix-list p5
+ set ipv6 next-hop global 2001:db8:5::1
!
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/zebra.conf b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
index 9039f1dec1..e69345f4f6 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/r2/zebra.conf
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/r2/zebra.conf
@@ -4,6 +4,7 @@ int lo
ipv6 address 2001:db8:2::1/128
ipv6 address 2001:db8:3::1/128
ipv6 address 2001:db8:4::1/128
+ ipv6 address 2001:db8:5::1/128
!
int r2-eth0
ip address 2001:db8::2/64
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/test_bgp_route_map_match_ipv6_nexthop_access_list.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
index 3efe1eca76..8c86526bf1 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop_access_list/test_bgp_route_map_match_ipv6_nexthop_access_list.py
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
@@ -20,7 +20,7 @@
"""
Test if we can match BGP prefixes by next-hop which is
-specified by an IPv6 Access-list.
+specified by an IPv6 Access-list, prefix-list or just an address.
"""
import os
@@ -103,6 +103,11 @@ def test_bgp_route_map_match_ipv6_next_hop_access_list():
"communities": "65002:4",
}
],
+ "2001:db8:5::1/128": [
+ {
+ "communities": "65002:5",
+ }
+ ],
}
return topotest.json_cmp(output, expected)
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index fa55a8c7cb..1e8c04bc6f 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -112,6 +112,12 @@ module frr-route-map {
"Match an IPv6 next-hop";
}
+ identity ipv6-next-hop-prefix-list {
+ base rmap-match-type;
+ description
+ "Match an IPv6 next-hop prefix list";
+ }
+
identity ipv6-next-hop-type {
base rmap-match-type;
description
@@ -207,6 +213,7 @@ module frr-route-map {
+ "derived-from-or-self(../condition, 'ipv4-next-hop-prefix-list') or "
+ "derived-from-or-self(../condition, 'ipv6-address-list') or "
+ "derived-from-or-self(../condition, 'ipv6-next-hop-list') or "
+ + "derived-from-or-self(../condition, 'ipv6-next-hop-prefix-list') or "
+ "derived-from-or-self(../condition, 'ipv6-prefix-list')";
leaf list-name {
type filter:access-list-name;