summaryrefslogtreecommitdiffstats
path: root/isisd/isis_redist.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2023-07-03 18:01:52 +0200
committerPhilippe Guibert <philippe.guibert@6wind.com>2023-07-12 14:06:00 +0200
commit4aee03bfd5767a8eebbcf0a99cd55d82605ebda5 (patch)
tree430ca1a1d13af5bd866bb940641633dc0c6243cc /isisd/isis_redist.c
parentisisd: add redistribute table identifier in nb configuration (diff)
downloadfrr-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.c207
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",