summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_routemap.c118
-rw-r--r--lib/routemap.c16
-rw-r--r--lib/routemap.h27
-rw-r--r--lib/routemap_cli.c5
-rw-r--r--lib/routemap_northbound.c10
-rw-r--r--yang/frr-route-map.yang7
6 files changed, 167 insertions, 16 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index b46fd1352..b2eb70a9c 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3023,10 +3023,60 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
route_match_ipv6_address_free
};
+/* `match ipv6 next-hop ACCESSLIST6_NAME' */
+static enum route_map_cmd_result_t
+route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+{
+ struct bgp_path_info *path;
+ struct access_list *alist;
+ 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;
+
+ alist = access_list_lookup(AFI_IP6, (char *)rule);
+ if (!alist)
+ return RMAP_NOMATCH;
+
+ if (access_list_apply(alist, &p) == FILTER_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 (access_list_apply(alist, &p) == FILTER_PERMIT)
+ return RMAP_MATCH;
+ }
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
+ "ipv6 next-hop",
+ route_match_ipv6_next_hop,
+ route_match_ipv6_next_hop_compile,
+ route_match_ipv6_next_hop_free
+};
+
/* `match ipv6 next-hop IP_ADDRESS' */
static enum route_map_cmd_result_t
-route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
+route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
+ void *object)
{
struct in6_addr *addr = rule;
struct bgp_path_info *path;
@@ -3043,7 +3093,7 @@ route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
return RMAP_NOMATCH;
}
-static void *route_match_ipv6_next_hop_compile(const char *arg)
+static void *route_match_ipv6_next_hop_address_compile(const char *arg)
{
struct in6_addr *address;
int ret;
@@ -3059,16 +3109,16 @@ static void *route_match_ipv6_next_hop_compile(const char *arg)
return address;
}
-static void route_match_ipv6_next_hop_free(void *rule)
+static void route_match_ipv6_next_hop_address_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
-static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
+static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
"ipv6 next-hop address",
- route_match_ipv6_next_hop,
- route_match_ipv6_next_hop_compile,
- route_match_ipv6_next_hop_free
+ route_match_ipv6_next_hop_address,
+ route_match_ipv6_next_hop_address_compile,
+ route_match_ipv6_next_hop_address_free
};
/* `match ip next-hop IP_ADDRESS' */
@@ -6047,6 +6097,43 @@ DEFUN_YANG (no_set_aggregator_as,
DEFUN_YANG (match_ipv6_next_hop,
match_ipv6_next_hop_cmd,
+ "match ipv6 next-hop ACCESSLIST6_NAME",
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 access-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-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,
+ no_match_ipv6_next_hop_cmd,
+ "no match ipv6 next-hop [ACCESSLIST6_NAME]",
+ NO_STR
+ MATCH_STR
+ IPV6_STR
+ "Match IPv6 next-hop address of route\n"
+ "IPv6 access-list name\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (match_ipv6_next_hop_address,
+ match_ipv6_next_hop_address_cmd,
"match ipv6 next-hop address X:X::X:X",
MATCH_STR
IPV6_STR
@@ -6062,13 +6149,14 @@ DEFUN_YANG (match_ipv6_next_hop,
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[argc - 1]->arg);
+ 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,
- no_match_ipv6_next_hop_cmd,
+DEFUN_YANG (no_match_ipv6_next_hop_address,
+ no_match_ipv6_next_hop_address_cmd,
"no match ipv6 next-hop address X:X::X:X",
NO_STR
MATCH_STR
@@ -6084,7 +6172,7 @@ DEFUN_YANG (no_match_ipv6_next_hop,
return nb_cli_apply_changes(vty, NULL);
}
-ALIAS_HIDDEN (match_ipv6_next_hop,
+ALIAS_HIDDEN (match_ipv6_next_hop_address,
match_ipv6_next_hop_old_cmd,
"match ipv6 next-hop X:X::X:X",
MATCH_STR
@@ -6092,7 +6180,7 @@ ALIAS_HIDDEN (match_ipv6_next_hop,
"Match IPv6 next-hop address of route\n"
"IPv6 address of next hop\n")
-ALIAS_HIDDEN (no_match_ipv6_next_hop,
+ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
no_match_ipv6_next_hop_old_cmd,
"no match ipv6 next-hop X:X::X:X",
NO_STR
@@ -6460,6 +6548,9 @@ void bgp_route_map_init(void)
route_map_match_ip_next_hop_hook(generic_match_add);
route_map_no_match_ip_next_hop_hook(generic_match_delete);
+ route_map_match_ipv6_next_hop_hook(generic_match_add);
+ route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
+
route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
@@ -6657,6 +6748,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_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);
@@ -6666,7 +6758,9 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
+ install_element(RMAP_NODE, &match_ipv6_next_hop_address_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, &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/lib/routemap.c b/lib/routemap.c
index 09da095af..c4651f39a 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -175,6 +175,22 @@ void route_map_no_match_ip_next_hop_hook(int (*func)(
rmap_match_set_hook.no_match_ip_next_hop = func;
}
+/* match ipv6 next-hop */
+void route_map_match_ipv6_next_hop_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 = func;
+}
+
+/* no match ipv6 next-hop */
+void route_map_no_match_ipv6_next_hop_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 = func;
+}
+
/* match ip next hop prefix list */
void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
diff --git a/lib/routemap.h b/lib/routemap.h
index 7e17e14fa..675f89ba9 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -244,6 +244,8 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(C, "frr-route-map:ipv6-address-list"))
#define IS_MATCH_IPv4_NEXTHOP_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-next-hop-list"))
+#define IS_MATCH_IPv6_NEXTHOP_LIST(C) \
+ (strmatch(C, "frr-route-map:ipv6-next-hop-list"))
#define IS_MATCH_IPv4_PREFIX_LIST(C) \
(strmatch(C, "frr-route-map:ipv4-prefix-list"))
#define IS_MATCH_IPv6_PREFIX_LIST(C) \
@@ -555,9 +557,16 @@ extern void route_map_match_ip_next_hop_hook(int (*func)(
char *errmsg, size_t errmsg_len));
/* no match ip next hop */
extern void route_map_no_match_ip_next_hop_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));
+ 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 */
+extern void route_map_match_ipv6_next_hop_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 */
+extern void route_map_no_match_ipv6_next_hop_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 ip next hop prefix list */
extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
struct route_map_index *index, const char *command,
@@ -743,6 +752,18 @@ struct route_map_match_set_hooks {
route_map_event_t type,
char *errmsg, size_t errmsg_len);
+ /* match ipv6 next hop */
+ int (*match_ipv6_next_hop)(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 */
+ int (*no_match_ipv6_next_hop)(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 f85be05f5..e26e3a6d2 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -551,6 +551,7 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(
dnode, "./rmap-match-condition/interface"));
} else if (IS_MATCH_IPv4_ADDRESS_LIST(condition)
+ || IS_MATCH_IPv6_NEXTHOP_LIST(condition)
|| IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
acl = NULL;
if ((ln = yang_dnode_get(dnode,
@@ -562,8 +563,10 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
if (IS_MATCH_IPv4_ADDRESS_LIST(condition))
vty_out(vty, " match ip address %s\n", acl);
- else
+ else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition))
vty_out(vty, " match ip next-hop %s\n", acl);
+ else
+ vty_out(vty, " match ipv6 next-hop %s\n", acl);
} else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
vty_out(vty, " match ip address prefix-list %s\n",
yang_dnode_get_string(
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 3473ca2ae..7f7bc9f9c 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -601,6 +601,16 @@ static int lib_route_map_entry_match_condition_list_name_modify(
rhc->rhc_rmi, "ip next-hop", acl,
RMAP_EVENT_FILTER_ADDED,
args->errmsg, args->errmsg_len);
+ } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
+ if (rmap_match_set_hook.match_ipv6_next_hop == NULL)
+ return NB_OK;
+ rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop;
+ rhc->rhc_rule = "ipv6 next-hop";
+ rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
+ rv = rmap_match_set_hook.match_ipv6_next_hop(
+ rhc->rhc_rmi, "ipv6 next-hop", acl,
+ RMAP_EVENT_FILTER_ADDED, args->errmsg,
+ args->errmsg_len);
} else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
if (rmap_match_set_hook.match_ip_next_hop_prefix_list == NULL)
return NB_OK;
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index c4eb78608..fa55a8c7c 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -106,6 +106,12 @@ module frr-route-map {
"Match an IPv6 prefix-list";
}
+ identity ipv6-next-hop-list {
+ base rmap-match-type;
+ description
+ "Match an IPv6 next-hop";
+ }
+
identity ipv6-next-hop-type {
base rmap-match-type;
description
@@ -200,6 +206,7 @@ module frr-route-map {
+ "derived-from-or-self(../condition, 'ipv4-next-hop-list') or "
+ "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-prefix-list')";
leaf list-name {
type filter:access-list-name;