diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2018-08-22 13:50:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-22 13:50:14 +0200 |
commit | dca5ef30533ab2a7a5573f065537e7a05067bec7 (patch) | |
tree | cabdc1fc450c57f56ede9d7e8ab6110334b2d01f /zebra | |
parent | Merge pull request #2888 from pguibert6WIND/misc_fix_static_tableid (diff) | |
parent | zebra : routemap "match ipv6 address prefix list" does not work (diff) | |
download | frr-dca5ef30533ab2a7a5573f065537e7a05067bec7.tar.xz frr-dca5ef30533ab2a7a5573f065537e7a05067bec7.zip |
Merge pull request #2818 from kssoman/rmap_fix
Zebra does not properly track which route-maps are changed (#2493)
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/redistribute.c | 7 | ||||
-rw-r--r-- | zebra/redistribute.h | 3 | ||||
-rw-r--r-- | zebra/rib.h | 2 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 13 | ||||
-rw-r--r-- | zebra/zebra_routemap.c | 136 |
5 files changed, 139 insertions, 22 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c index e3101fbe7..640d58e17 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty) return write; } -void zebra_import_table_rm_update() +void zebra_import_table_rm_update(const char *rmap) { afi_t afi; int i; @@ -730,9 +730,8 @@ void zebra_import_table_rm_update() continue; rmap_name = zebra_get_import_table_route_map(afi, i); - if (!rmap_name) - return; - + if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) + continue; table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT); for (rn = route_top(table); rn; rn = route_next(rn)) { diff --git a/zebra/redistribute.h b/zebra/redistribute.h index a0fbd13cf..f67480da9 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id); extern int zebra_import_table_config(struct vty *); -extern void zebra_import_table_rm_update(void); - +extern void zebra_import_table_rm_update(const char *rmap); #endif /* _ZEBRA_REDISTRIBUTE_H */ diff --git a/zebra/rib.h b/zebra/rib.h index a37b2bf22..f821c6edb 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id); extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event); +extern void rib_update_table(struct route_table *table, + rib_update_event_t event); extern void rib_sweep_route(void); extern void rib_sweep_table(struct route_table *table); extern void rib_close_table(struct route_table *table); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b477cd470..99b83d5cd 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2651,8 +2651,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, } /* Schedule routes of a particular table (address-family) based on event. */ -static void rib_update_table(struct route_table *table, - rib_update_event_t event) +void rib_update_table(struct route_table *table, rib_update_event_t event) { struct route_node *rn; struct route_entry *re, *next; @@ -2732,12 +2731,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event) /* Process routes of interested address-families. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP event %d", __func__, event); rib_update_table(table, event); + } table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 event %d", __func__, event); rib_update_table(table, event); + } } /* Delete self installed routes after zebra is relaunched. */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index fc17ee349..7a6bc6684 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object, afi_t afi) { struct prefix_list *plist; if (type == RMAP_ZEBRA) { - plist = prefix_list_lookup(AFI_IP, (char *)rule); + plist = prefix_list_lookup(afi, (char *)rule); if (plist == NULL) return RMAP_NOMATCH; @@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, return RMAP_NOMATCH; } -static void *route_match_ip_address_prefix_list_compile(const char *arg) +static route_map_result_t +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) +{ + return (route_match_address_prefix_list(rule, prefix, type, object, + AFI_IP)); +} + +static void *route_match_address_prefix_list_compile(const char *arg) { return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void route_match_ip_address_prefix_list_free(void *rule) +static void route_match_address_prefix_list_free(void *rule) { XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { "ip address prefix-list", route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free}; + route_match_address_prefix_list_compile, + route_match_address_prefix_list_free}; +static route_map_result_t +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) +{ + return (route_match_address_prefix_list(rule, prefix, type, object, + AFI_IP6)); +} + +static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { + "ipv6 address prefix-list", route_match_ipv6_address_prefix_list, + route_match_address_prefix_list_compile, + route_match_address_prefix_list_free}; /* `match ip address prefix-len PREFIXLEN' */ @@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = { "src", route_set_src, route_set_src_compile, route_set_src_free, }; +/* The function checks if the changed routemap specified by parameter rmap + * matches the configured protocol routemaps in proto_rm table. If there is + * a match then rib_update_table() to process the routes. + */ +static void zebra_rib_table_rm_update(const char *rmap) +{ + int i = 0; + struct route_table *table; + char *rmap_name; + char afi_ip = 0; + char afi_ipv6 = 0; + + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + /* Check for ip routemap table */ + rmap_name = proto_rm[AFI_IP][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP rmap %s, route type %s", + __func__, rmap, zebra_route_string(i)); + /* There is single rib table for all protocols */ + if (afi_ip == 0) { + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, + VRF_DEFAULT); + if (table) { + afi_ip = 1; + rib_update_table(table, + RIB_UPDATE_RMAP_CHANGE); + } + } + } + + /* Check for ipv6 routemap table */ + rmap_name = proto_rm[AFI_IP6][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 rmap %s,route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ipv6 == 0) { + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, + VRF_DEFAULT); + if (table) { + afi_ipv6 = 1; + rib_update_table(table, + RIB_UPDATE_RMAP_CHANGE); + } + } + } + } +} + +/* The function checks if the changed routemap specified by parameter rmap + * matches the configured protocol routemaps in nht_rm table. If there is + * a match then zebra_evaluate_rnh() to process the nexthops. + */ +static void zebra_nht_rm_update(const char *rmap) +{ + int i = 0; + char *rmap_name; + char afi_ip = 0; + char afi_ipv6 = 0; + + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + rmap_name = nht_rm[AFI_IP][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP rmap %s route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ip == 0) { + afi_ip = 1; + zebra_evaluate_rnh(0, AF_INET, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } + rmap_name = nht_rm[AFI_IP6][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 rmap %s route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ipv6 == 0) { + afi_ipv6 = 1; + zebra_evaluate_rnh(0, AF_INET6, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } + } +} + static void zebra_route_map_process_update_cb(char *rmap_name) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("Event handler for route-map: %s", rmap_name); + zebra_import_table_rm_update(rmap_name); + zebra_rib_table_rm_update(rmap_name); + zebra_nht_rm_update(rmap_name); } static int zebra_route_map_update_timer(struct thread *thread) @@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread) * 1) VRF Aware <sigh> * 2) Route-map aware */ - zebra_import_table_rm_update(); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return (0); } @@ -1555,12 +1660,19 @@ void zebra_route_map_init() route_map_match_tag_hook(generic_match_add); route_map_no_match_tag_hook(generic_match_delete); + route_map_match_ipv6_address_hook(generic_match_add); + route_map_no_match_ipv6_address_hook(generic_match_delete); + + 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_install_match(&route_match_tag_cmd); route_map_install_match(&route_match_interface_cmd); route_map_install_match(&route_match_ip_next_hop_cmd); route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); route_map_install_match(&route_match_ip_address_cmd); route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); route_map_install_match(&route_match_ip_address_prefix_len_cmd); route_map_install_match(&route_match_ipv6_address_prefix_len_cmd); route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd); |