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
"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",
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);
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);
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);
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,
(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) \
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,
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,
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(
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;
"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
+ "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;