summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Franke <chris@opensourcerouting.org>2014-01-12 21:51:56 +0100
committerChristian Franke <chris@opensourcerouting.org>2014-01-12 21:53:47 +0100
commita3ad688cd4322a773d6e2557a2fe915828dd7325 (patch)
treed1b8a14e9e917017a8e3bce6d09917a6b111ddbe
parent40b50b6618d3de2da3f0b1d5cb78f2bc277c7f20 (diff)
isisd: Add cleanup codeisis-redist
-rw-r--r--isisd/isis_redist.c92
-rw-r--r--isisd/isis_redist.h3
-rw-r--r--isisd/isis_zebra.c9
-rw-r--r--isisd/isis_zebra.h1
-rw-r--r--isisd/isisd.c2
-rw-r--r--isisd/isisd.h2
6 files changed, 101 insertions, 8 deletions
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c
index f0ad6941..c0044fd9 100644
--- a/isisd/isis_redist.c
+++ b/isisd/isis_redist.c
@@ -107,6 +107,30 @@ get_ext_reach(struct isis_area *area, int family, int level)
return area->ext_reach[protocol][level-1];
}
+static struct route_node *
+isis_redist_route_node_create(route_table_delegate_t *delegate,
+ struct route_table *table)
+{
+ struct route_node *node;
+ node = XCALLOC(MTYPE_ROUTE_NODE, sizeof(*node));
+ return node;
+}
+
+static void
+isis_redist_route_node_destroy(route_table_delegate_t *delegate,
+ struct route_table *table,
+ struct route_node *node)
+{
+ if (node->info)
+ XFREE(MTYPE_ISIS, node->info);
+ XFREE (MTYPE_ROUTE_NODE, node);
+}
+
+static route_table_delegate_t isis_redist_rt_delegate = {
+ .create_node = isis_redist_route_node_create,
+ .destroy_node = isis_redist_route_node_destroy
+};
+
/* Install external reachability information into a
* specific area for a specific level.
* Schedule an lsp regenerate if necessary */
@@ -169,7 +193,6 @@ isis_redist_uninstall(struct isis_area *area, int level, struct prefix *p)
if (!er_node->info)
return;
- XFREE(MTYPE_ISIS, er_node->info);
route_unlock_node(er_node);
lsp_regenerate_schedule(area, level, 0);
}
@@ -358,7 +381,6 @@ isis_redist_delete(int type, struct prefix *p)
isis_redist_uninstall(area, level, p);
}
- XFREE(MTYPE_ISIS, ei_node->info);
route_unlock_node(ei_node);
}
@@ -377,6 +399,33 @@ isis_redist_routemap_set(struct isis_redist *redist, const char *routemap)
}
static void
+isis_redist_update_zebra_subscriptions(struct isis *isis)
+{
+ struct listnode *node;
+ struct isis_area *area;
+ int type;
+ int level;
+ int protocol;
+
+ char do_subscribe[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)
+ do_subscribe[type] = 1;
+
+ for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
+ if (do_subscribe[type])
+ isis_zebra_redistribute_set(type);
+ else
+ isis_zebra_redistribute_unset(type);
+}
+
+static void
isis_redist_set(struct isis_area *area, int level,
int family, int type, uint32_t metric,
const char *routemap, int originate_type)
@@ -393,13 +442,19 @@ isis_redist_set(struct isis_area *area, int level,
isis_redist_routemap_set(redist, routemap);
if (!area->ext_reach[protocol][level-1])
- area->ext_reach[protocol][level-1] = route_table_init();
+ {
+ area->ext_reach[protocol][level-1] =
+ route_table_init_with_delegate(&isis_redist_rt_delegate);
+ }
for (i = 0; i < REDIST_PROTOCOL_COUNT; i++)
if (!area->isis->ext_info[i])
- area->isis->ext_info[i] = route_table_init();
+ {
+ area->isis->ext_info[i] =
+ route_table_init_with_delegate(&isis_redist_rt_delegate);
+ }
- isis_zebra_redistribute_set(type);
+ isis_redist_update_zebra_subscriptions(area->isis);
if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
isis_redist_ensure_default(area->isis, family);
@@ -462,11 +517,36 @@ isis_redist_unset(struct isis_area *area, int level,
continue;
}
- XFREE(MTYPE_ISIS, rn->info);
route_unlock_node(rn);
}
lsp_regenerate_schedule(area, level, 0);
+ isis_redist_update_zebra_subscriptions(area->isis);
+}
+
+void
+isis_redist_area_finish(struct isis_area *area)
+{
+ int protocol;
+ int level;
+ int type;
+
+ 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;
+ if (redist->map_name)
+ XFREE(MTYPE_ISIS, redist->map_name);
+ }
+ route_table_finish(area->ext_reach[protocol][level]);
+ }
+
+ isis_redist_update_zebra_subscriptions(area->isis);
}
DEFUN(isis_redistribute_ipv4,
diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h
index d2982bbc..ed9e747b 100644
--- a/isisd/isis_redist.h
+++ b/isisd/isis_redist.h
@@ -14,8 +14,8 @@
struct isis_ext_info
{
int origin;
- u_char distance;
uint32_t metric;
+ u_char distance;
};
struct isis_redist
@@ -37,5 +37,6 @@ void isis_redist_delete(int type, struct prefix *p);
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);
#endif
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 7f814fbb..4ce468dd 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -626,6 +626,15 @@ isis_zebra_redistribute_set(int type)
}
void
+isis_zebra_redistribute_unset(int type)
+{
+ if (type == DEFAULT_ROUTE)
+ zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
+ else
+ zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+}
+
+void
isis_zebra_init ()
{
zclient = zclient_new ();
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
index 8efd20ac..0b21f14b 100644
--- a/isisd/isis_zebra.h
+++ b/isisd/isis_zebra.h
@@ -29,5 +29,6 @@ void isis_zebra_route_update (struct prefix *prefix,
struct isis_route_info *route_info);
int isis_distribute_list_update (int routetype);
void isis_zebra_redistribute_set(int type);
+void isis_zebra_redistribute_unset(int type);
#endif /* _ZEBRA_ISIS_ZEBRA_H */
diff --git a/isisd/isisd.c b/isisd/isisd.c
index a100319c..5062b96a 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -282,6 +282,8 @@ isis_area_destroy (struct vty *vty, const char *area_tag)
}
#endif /* HAVE_IPV6 */
+ isis_redist_area_finish(area);
+
for (ALL_LIST_ELEMENTS (area->area_addrs, node, nnode, addr))
{
list_delete_node (area->area_addrs, node);
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 3a4e844d..8066a57a 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -28,7 +28,7 @@
#include "isisd/isis_redist.h"
/* uncomment if you are a developer in bug hunt */
-/* #define EXTREME_DEBUG */
+/* #define EXTREME_DEBUG */
/* #define EXTREME_TLV_DEBUG */
struct isis