From 01d6daea2f5487cd7fd589569a0dbc6205ab8914 Mon Sep 17 00:00:00 2001 From: huachao01 <1945995178@qq.com> Date: Wed, 12 Mar 2025 09:19:02 -0400 Subject: [PATCH] isisd: Fix the issue where redistributed routes do not change when the route-map is modified. Signed-off-by: huachao01 <1945995178@qq.com> --- isisd/isis_redist.c | 46 +++++++++++++++++++++++++++++++++++++++++++ isisd/isis_redist.h | 2 ++ isisd/isis_routemap.c | 41 ++++++++++++++++++++++++++++++++++++++ isisd/isisd.h | 1 + 4 files changed, 90 insertions(+) diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2cb08db27b..76189edcdc 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -44,6 +44,17 @@ static int redist_protocol(int family) return 0; } +int afi_skt_for_redist_protocol(int protocol) +{ + if (protocol == 0) + return AF_INET; + if (protocol == 1) + return AF_INET6; + + assert(!"Unknown redist protocol!"); + return AF_INET; +} + afi_t afi_for_redist_protocol(int protocol) { if (protocol == 0) @@ -430,6 +441,41 @@ void isis_redist_free(struct isis *isis) } } +void isis_redist_update(struct isis_area *area, int level, int family, int type, uint16_t table) +{ + struct isis_redist *redist; + struct route_table *ei_table; + struct route_node *rn; + struct isis_ext_info *info; + + redist = isis_redist_lookup(area, family, type, level, table); + if (!redist) + return; + + ei_table = get_ext_info(area->isis, family); + for (rn = route_top(ei_table); rn; rn = srcdest_route_next(rn)) { + if (!rn->info) + continue; + info = rn->info; + + const struct prefix *p, *src_p; + + srcdest_rnode_prefixes(rn, &p, &src_p); + + if (type == DEFAULT_ROUTE) { + if (!is_default_prefix(p) || (src_p && src_p->prefixlen)) { + continue; + } + } else { + if (info->origin != type) + continue; + } + + isis_redist_update_ext_reach(area, level, redist, p, + (const struct prefix_ipv6 *)src_p, info); + } +} + void isis_redist_set(struct isis_area *area, int level, int family, int type, uint32_t metric, const char *routemap, int originate_type, uint16_t table) diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 688f27e62d..7ae3c0e52a 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -43,6 +43,7 @@ struct prefix; struct prefix_ipv6; struct vty; +int afi_skt_for_redist_protocol(int protocol); afi_t afi_for_redist_protocol(int protocol); struct route_table *get_ext_reach(struct isis_area *area, int family, @@ -60,6 +61,7 @@ void isis_redist_area_finish(struct isis_area *area); void isis_redist_set(struct isis_area *area, int level, int family, int type, uint32_t metric, const char *routemap, int originate_type, uint16_t table); +void isis_redist_update(struct isis_area *area, int level, int family, int type, uint16_t table); void isis_redist_unset(struct isis_area *area, int level, int family, int type, uint16_t table); diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index 9be133c788..7aaba08c44 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -234,10 +234,51 @@ static const struct route_map_rule_cmd route_set_metric_cmd = { route_set_metric_free }; +static void isis_route_map_update(const char *name) +{ + struct isis *isis; + struct listnode *node, *lnode; + struct isis_area *area; + int type; + int level; + int protocol; + struct isis_redist *redist; + + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) + for (level = 0; level < ISIS_LEVELS; level++) { + if (area->redist_settings[protocol][type][level] == + NULL) + continue; + for (ALL_LIST_ELEMENTS_RO(area->redist_settings + [protocol][type] + [level], + lnode, redist)) { + if (redist->redist == 0) + continue; + + if (redist->map_name && + strcmp(redist->map_name, name) == 0) { + isis_redist_update(area, level + 1, + afi_skt_for_redist_protocol( + protocol), + type, + redist->table); + } + } + } +} + void isis_route_map_init(void) { route_map_init(); + route_map_add_hook(isis_route_map_update); + route_map_delete_hook(isis_route_map_update); + route_map_event_hook(isis_route_map_update); + route_map_match_ip_address_hook(generic_match_add); route_map_no_match_ip_address_hook(generic_match_delete); diff --git a/isisd/isisd.h b/isisd/isisd.h index ae39502023..f9723c22e1 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -56,6 +56,7 @@ static const bool fabricd = false; extern void isis_cli_init(void); #endif + #define ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) \ if (argv_find(argv, argc, "vrf", &idx_vrf)) { \ vrf_name = argv[idx_vrf + 1]->arg; \