From 3b1e3aab803ff2874ed23a1c19042b9510ecdf8f Mon Sep 17 00:00:00 2001 From: Emanuele Altomare Date: Fri, 5 Mar 2021 22:12:00 +0000 Subject: [PATCH] isisd: added support for routemap match tag in redistribution Now it's possible to filter routes redistributed by another protocol using tag which comes from zebra daemon. Example of a possible configuration: ``` ! ipv6 route fd00::/48 blackhole tag 20 ipv6 route fd00::/60 blackhole tag 10 ! interface one ipv6 router isis COMMON isis circuit-type level-1 ! interface two ipv6 router isis COMMON isis circuit-type level-2-only ! router isis COMMON net fd.0000.0000.0000.0001.00 redistribute ipv6 static level-1 route-map static-l1 redistribute ipv6 static level-2 route-map static-l2 topology ipv6-unicast ! route-map static-l1 permit 10 match tag 10 ! route-map static-l2 permit 10 match tag 20 ! ``` Signed-off-by: Emanuele Altomare --- isisd/isis_redist.c | 5 +++-- isisd/isis_redist.h | 3 ++- isisd/isis_routemap.c | 33 +++++++++++++++++++++++++++++++++ isisd/isis_zebra.c | 2 +- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 240be27cf3..856c47b9b7 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -219,7 +219,7 @@ static void isis_redist_ensure_default(struct isis *isis, int family) /* Handle notification about route being added */ void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, - uint32_t metric) + uint32_t metric, const route_tag_t tag) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -250,6 +250,7 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p, info->origin = type; info->distance = distance; info->metric = metric; + info->tag = tag; if (is_default_prefix(p) && (!src_p || !src_p->prefixlen)) { @@ -288,7 +289,7 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p, * "always" setting will ignore routes with origin * DEFAULT_ROUTE. */ isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254, - MAX_WIDE_PATH_METRIC); + MAX_WIDE_PATH_METRIC, 0); return; } diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index afce922240..fcc4ceadf4 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -31,6 +31,7 @@ struct isis_ext_info { int origin; uint32_t metric; uint8_t distance; + route_tag_t tag; }; struct isis_redist { @@ -50,7 +51,7 @@ struct route_table *get_ext_reach(struct isis_area *area, int family, int level); void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, - uint32_t metric); + uint32_t metric, route_tag_t tag); void isis_redist_delete(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p); int isis_redist_config_write(struct vty *vty, struct isis_area *area, diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index db0f2fd8be..626e399e15 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -112,6 +112,35 @@ static const struct route_map_rule_cmd /* ------------------------------------------------------------*/ +/* `match tag TAG' */ +/* Match function return 1 if match is success else return zero. */ +static enum route_map_cmd_result_t +route_match_tag(void *rule, const struct prefix *p, void *object) +{ + route_tag_t *tag; + struct isis_ext_info *info; + route_tag_t info_tag; + + tag = rule; + info = object; + + info_tag = info->tag; + if (info_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; +} + +/* Route map commands for tag matching. */ +static const struct route_map_rule_cmd route_match_tag_cmd = { + "tag", + route_match_tag, + route_map_rule_tag_compile, + route_map_rule_tag_free, +}; + +/* ------------------------------------------------------------*/ + static enum route_map_cmd_result_t route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object) { @@ -234,6 +263,9 @@ void isis_route_map_init(void) route_map_match_ipv6_address_prefix_list_hook(generic_match_add); route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); + route_map_set_metric_hook(generic_set_add); route_map_no_set_metric_hook(generic_set_delete); @@ -241,5 +273,6 @@ void isis_route_map_init(void) route_map_install_match(&route_match_ip_address_prefix_list_cmd); route_map_install_match(&route_match_ipv6_address_cmd); route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); + route_map_install_match(&route_match_tag_cmd); route_map_install_set(&route_set_metric_cmd); } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 703532234a..cb4dd2569d 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -509,7 +509,7 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS) if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix, - api.distance, api.metric); + api.distance, api.metric, api.tag); else isis_redist_delete(isis, api.type, &api.prefix, &api.src_prefix);