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>
This commit is contained in:
Philippe Guibert 2023-07-03 18:01:52 +02:00
parent 2150647069
commit 4aee03bfd5
7 changed files with 225 additions and 163 deletions

View File

@ -1088,7 +1088,7 @@ void default_info_origin_apply_finish(const struct lyd_node *dnode, int family)
routemap = yang_dnode_get_string(dnode, "./route-map");
isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
originate_type);
originate_type, 0);
}
void default_info_origin_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
@ -1119,7 +1119,7 @@ int isis_instance_default_information_originate_ipv4_destroy(
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE);
isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE, 0);
return NB_OK;
}
@ -1182,7 +1182,7 @@ int isis_instance_default_information_originate_ipv6_destroy(
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE);
isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE, 0);
return NB_OK;
}
@ -1244,7 +1244,7 @@ void redistribute_apply_finish(const struct lyd_node *dnode, int family)
if (yang_dnode_exists(dnode, "./route-map"))
routemap = yang_dnode_get_string(dnode, "./route-map");
isis_redist_set(area, level, family, type, metric, routemap, 0);
isis_redist_set(area, level, family, type, metric, routemap, 0, 0);
}
void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
@ -1274,7 +1274,7 @@ int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args)
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
type = yang_dnode_get_enum(args->dnode, "./protocol");
isis_redist_unset(area, level, AF_INET, type);
isis_redist_unset(area, level, AF_INET, type, 0);
return NB_OK;
}
@ -1319,14 +1319,44 @@ int isis_instance_redistribute_ipv4_metric_destroy(struct nb_cb_destroy_args *ar
*/
int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args)
{
uint16_t table;
int type, level;
unsigned long metric = 0;
const char *routemap = NULL;
struct isis_area *area;
if (args->event != NB_EV_APPLY)
return NB_OK;
/* TODO */
type = yang_dnode_get_enum(args->dnode, "../protocol");
level = yang_dnode_get_enum(args->dnode, "../level");
area = nb_running_get_entry(args->dnode, "../.", true);
if (yang_dnode_exists(args->dnode, "./metric"))
metric = yang_dnode_get_uint32(args->dnode, "./metric");
if (yang_dnode_exists(args->dnode, "./route-map"))
routemap = yang_dnode_get_string(args->dnode, "./route-map");
table = yang_dnode_get_uint16(args->dnode, "./table");
isis_redist_set(area, level, AF_INET, type, metric, routemap, 0, table);
return NB_OK;
}
int isis_instance_redistribute_ipv4_table_destroy(struct nb_cb_destroy_args *args)
{
struct isis_area *area;
int level, type;
uint16_t table;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_get_entry(args->dnode, "../.", true);
level = yang_dnode_get_enum(args->dnode, "../level");
type = yang_dnode_get_enum(args->dnode, "../protocol");
table = yang_dnode_get_uint16(args->dnode, "./table");
isis_redist_unset(area, level, AF_INET, type, table);
return NB_OK;
}
@ -1350,7 +1380,7 @@ int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args)
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
type = yang_dnode_get_enum(args->dnode, "./protocol");
isis_redist_unset(area, level, AF_INET6, type);
isis_redist_unset(area, level, AF_INET6, type, 0);
return NB_OK;
}

View File

@ -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;
return &area->redist_settings[protocol][type][level - 1];
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();
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",

View File

@ -26,6 +26,7 @@ struct isis_redist {
uint32_t metric;
char *map_name;
struct route_map *map;
uint16_t table;
};
struct isis_redist_table_present_args {
@ -48,17 +49,19 @@ 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, route_tag_t tag);
uint32_t metric, route_tag_t tag, uint16_t instance);
void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p);
struct prefix_ipv6 *src_p, uint16_t tableid);
int isis_redist_config_write(struct vty *vty, struct isis_area *area,
int family);
void isis_redist_init(void);
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);
void isis_redist_unset(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_unset(struct isis_area *area, int level, int family, int type,
uint16_t table);
void isis_redist_free(struct isis *isis);

View File

@ -498,10 +498,10 @@ 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.tag);
api.distance, api.metric, api.tag, api.instance);
else
isis_redist_delete(isis, api.type, &api.prefix,
&api.src_prefix);
isis_redist_delete(isis, api.type, &api.prefix, &api.src_prefix,
api.instance);
return 0;
}
@ -511,24 +511,26 @@ int isis_distribute_list_update(int routetype)
return 0;
}
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id)
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
0, vrf_id);
tableid, vrf_id);
}
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id)
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
type, 0, vrf_id);
type, tableid, vrf_id);
}
/**

View File

@ -43,8 +43,10 @@ void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
struct isis_sr_psid_info *psid);
void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra);
int isis_distribute_list_update(int routetype);
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id);
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id);
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid);
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid);
int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa);
void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree);
bool isis_zebra_label_manager_ready(void);

View File

@ -599,64 +599,66 @@ static int isis_vrf_delete(struct vrf *vrf)
static void isis_set_redist_vrf_bitmaps(struct isis *isis, bool set)
{
struct listnode *node;
struct listnode *node, *lnode;
struct isis_area *area;
int type;
int level;
int protocol;
char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
memset(do_subscribe, 0, sizeof(do_subscribe));
struct isis_redist *redist;
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 (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;
/* This field is actually
* controlling transmission of
* the IS-IS
* routes to Zebra and has
* nothing to do with
* redistribution,
* so skip it. */
afi_t afi =
afi_for_redist_protocol(
protocol);
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;
if (!do_subscribe[protocol][type])
continue;
afi_t afi = afi_for_redist_protocol(protocol);
if (type == DEFAULT_ROUTE) {
if (set)
vrf_bitmap_set(
&zclient->default_information
[afi],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->default_information
[afi],
isis->vrf_id);
} else {
if (set)
vrf_bitmap_set(
&zclient->redist[afi][type],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->redist[afi][type],
isis->vrf_id);
}
}
if (type == DEFAULT_ROUTE) {
if (set)
vrf_bitmap_set(
&zclient->default_information
[afi],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->default_information
[afi],
isis->vrf_id);
} else {
if (set)
vrf_bitmap_set(
&zclient->redist
[afi]
[type],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->redist
[afi]
[type],
isis->vrf_id);
}
}
}
}
static int isis_vrf_enable(struct vrf *vrf)

View File

@ -230,8 +230,8 @@ struct isis_area {
#endif /* ifndef FABRICD */
/* Counters */
uint32_t circuit_state_changes;
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
[ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS];
struct list *redist_settings[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]
[ISIS_LEVELS];
struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS];
struct spf_backoff *spf_delay_ietf[ISIS_LEVELS]; /*Structure with IETF