From a3ad688cd4322a773d6e2557a2fe915828dd7325 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Sun, 12 Jan 2014 21:51:56 +0100 Subject: isisd: Add cleanup code --- isisd/isis_redist.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++---- isisd/isis_redist.h | 3 +- isisd/isis_zebra.c | 9 ++++++ isisd/isis_zebra.h | 1 + isisd/isisd.c | 2 ++ isisd/isisd.h | 2 +- 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); } @@ -376,6 +398,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, @@ -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 @@ -625,6 +625,15 @@ isis_zebra_redistribute_set(int type) zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, 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 () { 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 -- cgit v1.2.1