diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2023-07-03 18:01:52 +0200 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2023-07-12 14:06:00 +0200 |
commit | 4aee03bfd5767a8eebbcf0a99cd55d82605ebda5 (patch) | |
tree | 430ca1a1d13af5bd866bb940641633dc0c6243cc /isisd/isis_redist.c | |
parent | isisd: add redistribute table identifier in nb configuration (diff) | |
download | frr-4aee03bfd5767a8eebbcf0a99cd55d82605ebda5.tar.xz frr-4aee03bfd5767a8eebbcf0a99cd55d82605ebda5.zip |
isisd: add the 'redistribute table' internal support
The 'redistribute table' command does not create the internal
contexts with the appropriate table identifier.
Redistributed prefixes in IS-IS do not care about the
table identifier. Add a linked list of redistribution
contexts, and map the nb configuration to the linked list.
- A new 'table' attribute is added in the 'struct
isis_redist' context.
- The 'isis_redist_update_zebra_subscriptions()' function
is removed and is replaced by direct call to zebra API
for turning on/off redirection.
- The redistributed routes coming from zebra import the
'tableid' information.
- The fabricd redistribute running-config is reworked,
and the 'get_redist_settings()' function is removed.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'isisd/isis_redist.c')
-rw-r--r-- | isisd/isis_redist.c | 207 |
1 files changed, 115 insertions, 92 deletions
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2b3facc43..2cb08db27 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -31,6 +31,7 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route"); DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info"); DEFINE_MTYPE_STATIC(ISISD, ISIS_RMAP_NAME, "ISIS redistribute route-map name"); +DEFINE_MTYPE_STATIC(ISISD, ISIS_REDISTRIBUTE, "ISIS redistribute"); static int redist_protocol(int family) { @@ -61,12 +62,43 @@ static struct route_table *get_ext_info(struct isis *i, int family) return i->ext_info[protocol]; } -static struct isis_redist *get_redist_settings(struct isis_area *area, - int family, int type, int level) +static struct isis_redist *isis_redist_lookup(struct isis_area *area, + int family, int type, int level, + uint16_t table) { int protocol = redist_protocol(family); + struct listnode *node; + struct isis_redist *red; + + if (area->redist_settings[protocol][type][level - 1]) { + for (ALL_LIST_ELEMENTS_RO(area->redist_settings[protocol][type] + [level - 1], + node, red)) + if (red->table == table) + return red; + } + return NULL; +} + +static struct isis_redist *isis_redist_get(struct isis_area *area, int family, + int type, int level, uint16_t table) +{ + struct isis_redist *red; + int protocol; + + red = isis_redist_lookup(area, family, type, level, table); + if (red) + return red; + + protocol = redist_protocol(family); + if (area->redist_settings[protocol][type][level - 1] == NULL) + area->redist_settings[protocol][type][level - 1] = list_new(); - return &area->redist_settings[protocol][type][level - 1]; + red = XCALLOC(MTYPE_ISIS_REDISTRIBUTE, sizeof(struct isis_redist)); + red->table = table; + + listnode_add(area->redist_settings[protocol][type][level - 1], red); + return red; } struct route_table *get_ext_reach(struct isis_area *area, int family, int level) @@ -256,7 +288,7 @@ bool isis_redist_table_is_present(const struct vty *vty, /* 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, const route_tag_t tag) + uint32_t metric, const route_tag_t tag, uint16_t table) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -296,8 +328,9 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p, for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = 1; level <= ISIS_LEVELS; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist = isis_redist_lookup(area, family, type, level, + table); + if (!redist || !redist->redist) continue; isis_redist_update_ext_reach(area, level, redist, p, @@ -306,7 +339,7 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p, } void isis_redist_delete(struct isis *isis, int type, struct prefix *p, - struct prefix_ipv6 *src_p) + struct prefix_ipv6 *src_p, uint16_t table) { int family = p->family; struct route_table *ei_table = get_ext_info(isis, family); @@ -326,7 +359,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, 0); + MAX_WIDE_PATH_METRIC, 0, table); return; } @@ -349,8 +382,9 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p, for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist = isis_redist_lookup(area, family, type, level, + table); + if (!redist || !redist->redist) continue; isis_redist_uninstall(area, level, p, src_p); @@ -376,53 +410,6 @@ static void isis_redist_routemap_set(struct isis_redist *redist, } } -static void isis_redist_update_zebra_subscriptions(struct isis *isis) -{ - struct listnode *node; - struct isis_area *area; - int type; - int level; - int protocol; - - if (isis->vrf_id == VRF_UNKNOWN) - return; - - char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; - - memset(do_subscribe, 0, sizeof(do_subscribe)); - - 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] - .redist - == 1) - do_subscribe[protocol][type] = - 1; - - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { - /* This field is actually controlling transmission of - * the IS-IS - * routes to Zebra and has nothing to do with - * redistribution, - * so skip it. */ - if (type == PROTO_TYPE) - continue; - - afi_t afi = afi_for_redist_protocol(protocol); - - if (do_subscribe[protocol][type]) - isis_zebra_redistribute_set(afi, type, - isis->vrf_id); - else - isis_zebra_redistribute_unset(afi, type, - isis->vrf_id); - } -} - void isis_redist_free(struct isis *isis) { struct route_node *rn; @@ -444,11 +431,12 @@ void isis_redist_free(struct isis *isis) } void isis_redist_set(struct isis_area *area, int level, int family, int type, - uint32_t metric, const char *routemap, int originate_type) + uint32_t metric, const char *routemap, int originate_type, + uint16_t table) { int protocol = redist_protocol(family); - struct isis_redist *redist = - get_redist_settings(area, family, type, level); + struct isis_redist *redist = isis_redist_get(area, family, type, level, + table); int i; struct route_table *ei_table; struct route_node *rn; @@ -468,7 +456,8 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, } } - isis_redist_update_zebra_subscriptions(area->isis); + isis_zebra_redistribute_set(afi_for_redist_protocol(protocol), type, + area->isis->vrf_id, redist->table); if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS) isis_redist_ensure_default(area->isis, family); @@ -499,18 +488,26 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, } } -void isis_redist_unset(struct isis_area *area, int level, int family, int type) +void isis_redist_unset(struct isis_area *area, int level, int family, int type, + uint16_t table) { - struct isis_redist *redist = - get_redist_settings(area, family, type, level); + struct isis_redist *redist = isis_redist_lookup(area, family, type, + level, table); struct route_table *er_table = get_ext_reach(area, family, level); struct route_node *rn; struct isis_ext_info *info; + struct list *redist_list; + int protocol = redist_protocol(family); - if (!redist->redist) + if (!redist || !redist->redist) return; redist->redist = 0; + + redist_list = area->redist_settings[protocol][type][level - 1]; + listnode_delete(redist_list, redist); + XFREE(MTYPE_ISIS_REDISTRIBUTE, redist); + if (!er_table) { zlog_warn("%s: External reachability table uninitialized.", __func__); @@ -540,7 +537,8 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type) } lsp_regenerate_schedule(area, level, 0); - isis_redist_update_zebra_subscriptions(area->isis); + isis_zebra_redistribute_unset(afi_for_redist_protocol(protocol), type, + area->isis->vrf_id, table); } void isis_redist_area_finish(struct isis_area *area) @@ -549,16 +547,30 @@ void isis_redist_area_finish(struct isis_area *area) int protocol; int level; int type; + struct isis_redist *redist; + struct listnode *node, *nnode; + struct list *redist_list; for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) for (level = 0; level < ISIS_LEVELS; level++) { for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { - struct isis_redist *redist; - - redist = &area->redist_settings[protocol][type] - [level]; - redist->redist = 0; - XFREE(MTYPE_ISIS_RMAP_NAME, redist->map_name); + redist_list = area->redist_settings[protocol] + [type][level]; + if (!redist_list) + continue; + for (ALL_LIST_ELEMENTS(redist_list, node, nnode, + redist)) { + redist->redist = 0; + XFREE(MTYPE_ISIS_RMAP_NAME, + redist->map_name); + isis_zebra_redistribute_unset( + afi_for_redist_protocol(protocol), + type, area->isis->vrf_id, + redist->table); + listnode_delete(redist_list, redist); + XFREE(MTYPE_ISIS_REDISTRIBUTE, redist); + } + list_delete(&redist_list); } if (!area->ext_reach[protocol][level]) continue; @@ -570,8 +582,6 @@ void isis_redist_area_finish(struct isis_area *area) route_table_finish(area->ext_reach[protocol][level]); area->ext_reach[protocol][level] = NULL; } - - isis_redist_update_zebra_subscriptions(area->isis); } #ifdef FABRICD @@ -628,7 +638,7 @@ DEFUN (isis_redistribute, routemap = argv[idx_metric_rmap + 1]->arg; } - isis_redist_set(area, level, family, type, metric, routemap, 0); + isis_redist_set(area, level, family, type, metric, routemap, 0, 0); return 0; } @@ -664,7 +674,7 @@ DEFUN (no_isis_redistribute, level = 2; - isis_redist_unset(area, level, family, type); + isis_redist_unset(area, level, family, type, 0); return 0; } @@ -724,7 +734,7 @@ DEFUN (isis_default_originate, } isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, - originate_type); + originate_type, 0); return 0; } @@ -748,7 +758,7 @@ DEFUN (no_isis_default_originate, level = 2; - isis_redist_unset(area, level, family, DEFAULT_ROUTE); + isis_redist_unset(area, level, family, DEFAULT_ROUTE, 0); return 0; } #endif /* ifdef FABRICD */ @@ -760,7 +770,9 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, int level; int write = 0; struct isis_redist *redist; + struct list *redist_list; const char *family_str; + struct listnode *node; if (family == AF_INET) family_str = "ipv4"; @@ -774,25 +786,36 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, continue; for (level = 1; level <= ISIS_LEVELS; level++) { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) + redist_list = area->redist_settings[redist_protocol( + family)][type][level - 1]; + if (!redist_list) continue; - vty_out(vty, " redistribute %s %s", family_str, - zebra_route_string(type)); - if (!fabricd) - vty_out(vty, " level-%d", level); - if (redist->metric) - vty_out(vty, " metric %u", redist->metric); - if (redist->map_name) - vty_out(vty, " route-map %s", redist->map_name); - vty_out(vty, "\n"); - write++; + for (ALL_LIST_ELEMENTS_RO(redist_list, node, redist)) { + if (!redist->redist) + continue; + vty_out(vty, " redistribute %s %s", family_str, + zebra_route_string(type)); + if (type == ZEBRA_ROUTE_TABLE) + vty_out(vty, " %u", redist->table); + if (!fabricd) + vty_out(vty, " level-%d", level); + if (redist->metric) + vty_out(vty, " metric %u", + redist->metric); + if (redist->map_name) + vty_out(vty, " route-map %s", + redist->map_name); + vty_out(vty, "\n"); + write++; + } } } for (level = 1; level <= ISIS_LEVELS; level++) { - redist = - get_redist_settings(area, family, DEFAULT_ROUTE, level); + redist = isis_redist_lookup(area, family, DEFAULT_ROUTE, level, + 0); + if (!redist) + continue; if (!redist->redist) continue; vty_out(vty, " default-information originate %s", |