diff options
-rw-r--r-- | bgpd/bgp_routemap.c | 118 | ||||
-rw-r--r-- | lib/routemap.c | 16 | ||||
-rw-r--r-- | lib/routemap.h | 27 | ||||
-rw-r--r-- | lib/routemap_cli.c | 5 | ||||
-rw-r--r-- | lib/routemap_northbound.c | 10 | ||||
-rw-r--r-- | yang/frr-route-map.yang | 7 |
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; |