From 0cf08685d2ed61659ba11695d142b56ebbc13a9f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Feb 2019 07:51:41 -0500 Subject: [PATCH 1/5] sharpd: Setup route installation to be able to select vrf to use Modify the sharp code to allow for vrf route installation. At this point in time the code is nascent. Future commits will turn on this behavior. Signed-off-by: Donald Sharp --- sharpd/sharp_globals.h | 1 + sharpd/sharp_vty.c | 9 +++++++-- sharpd/sharp_zebra.c | 29 ++++++++++++++++------------- sharpd/sharp_zebra.h | 15 ++++++++------- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/sharpd/sharp_globals.h b/sharpd/sharp_globals.h index 065fb092d4..4e5c933667 100644 --- a/sharpd/sharp_globals.h +++ b/sharpd/sharp_globals.h @@ -38,6 +38,7 @@ struct sharp_routes { int32_t repeat; uint8_t inst; + vrf_id_t vrf_id; struct timeval t_start; struct timeval t_end; diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 9018cfb359..72a46d5e6d 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -195,12 +195,15 @@ DEFPY (install_routes, sg.r.nhop.type = NEXTHOP_TYPE_IPV6; } + sg.r.nhop.vrf_id = VRF_DEFAULT; sg.r.nhop_group.nexthop = &sg.r.nhop; } sg.r.inst = instance; + sg.r.vrf_id = VRF_DEFAULT; rts = routes; - sharp_install_routes_helper(&prefix, sg.r.inst, &sg.r.nhop_group, rts); + sharp_install_routes_helper(&prefix, sg.r.vrf_id, + sg.r.inst, &sg.r.nhop_group, rts); return CMD_SUCCESS; } @@ -266,8 +269,10 @@ DEFPY (remove_routes, } sg.r.inst = instance; + sg.r.vrf_id = VRF_DEFAULT; rts = routes; - sharp_remove_routes_helper(&prefix, sg.r.inst, rts); + sharp_remove_routes_helper(&prefix, sg.r.vrf_id, + sg.r.inst, rts); return CMD_SUCCESS; } diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 4682dbc73a..942040b802 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -131,8 +131,8 @@ static int interface_state_down(int command, struct zclient *zclient, return 0; } -void sharp_install_routes_helper(struct prefix *p, uint8_t instance, - struct nexthop_group *nhg, +void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, struct nexthop_group *nhg, uint32_t routes) { uint32_t temp, i; @@ -148,7 +148,7 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance, monotime(&sg.r.t_start); for (i = 0; i < routes; i++) { - route_add(p, (uint8_t)instance, nhg); + route_add(p, vrf_id, (uint8_t)instance, nhg); if (v4) p->u.prefix4.s_addr = htonl(++temp); else @@ -156,8 +156,8 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance, } } -void sharp_remove_routes_helper(struct prefix *p, uint8_t instance, - uint32_t routes) +void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t routes) { uint32_t temp, i; bool v4 = false; @@ -172,7 +172,7 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance, monotime(&sg.r.t_start); for (i = 0; i < routes; i++) { - route_delete(p, (uint8_t)instance); + route_delete(p, vrf_id, (uint8_t)instance); if (v4) p->u.prefix4.s_addr = htonl(++temp); else @@ -190,12 +190,14 @@ static void handle_repeated(bool installed) if (installed) { sg.r.removed_routes = 0; - sharp_remove_routes_helper(&p, sg.r.inst, sg.r.total_routes); + sharp_remove_routes_helper(&p, sg.r.vrf_id, + sg.r.inst, sg.r.total_routes); } if (installed) { sg.r.installed_routes = 0; - sharp_install_routes_helper(&p, sg.r.inst, &sg.r.nhop_group, + sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst, + &sg.r.nhop_group, sg.r.total_routes); } } @@ -255,7 +257,8 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label) zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP); } -void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg) +void route_add(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, struct nexthop_group *nhg) { struct zapi_route api; struct zapi_nexthop *api_nh; @@ -263,7 +266,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg) int i = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = vrf_id; api.type = ZEBRA_ROUTE_SHARP; api.instance = instance; api.safi = SAFI_UNICAST; @@ -274,7 +277,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg) for (ALL_NEXTHOPS_PTR(nhg, nh)) { api_nh = &api.nexthops[i]; - api_nh->vrf_id = VRF_DEFAULT; + api_nh->vrf_id = nh->vrf_id; api_nh->type = nh->type; switch (nh->type) { case NEXTHOP_TYPE_IPV4: @@ -305,12 +308,12 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg) zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } -void route_delete(struct prefix *p, uint8_t instance) +void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) { struct zapi_route api; memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = vrf_id; api.type = ZEBRA_ROUTE_SHARP; api.safi = SAFI_UNICAST; api.instance = instance; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index b219022f02..7c3c39c892 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -25,15 +25,16 @@ extern void sharp_zebra_init(void); extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); -extern void route_add(struct prefix *p, uint8_t instance, +extern void route_add(struct prefix *p, vrf_id_t, uint8_t instance, struct nexthop_group *nhg); -extern void route_delete(struct prefix *p, uint8_t instance); +extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance); extern void sharp_zebra_nexthop_watch(struct prefix *p, bool import, bool watch, bool connected); -extern void sharp_install_routes_helper(struct prefix *p, uint8_t instance, - struct nexthop_group *nhg, - uint32_t routes); -extern void sharp_remove_routes_helper(struct prefix *p, uint8_t instance, - uint32_t routes); +extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, + struct nexthop_group *nhg, + uint32_t routes); +extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, + uint8_t instance, uint32_t routes); #endif From 4a7d47374b44399077913c6378a0fd002f89925c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Feb 2019 08:09:53 -0500 Subject: [PATCH 2/5] sharpd: Add cli to allow vrf route installation Add a bit of code to allow the end user to specify a [vrf NAME] for route installation/deletion. Signed-off-by: Donald Sharp --- sharpd/sharp_vty.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 72a46d5e6d..21fa3cf744 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -132,10 +132,12 @@ DEFPY (install_routes_data_dump, DEFPY (install_routes, install_routes_cmd, - "sharp install routes |nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", + "sharp install routes [vrf NAME$name] |nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", "Sharp routing Protocol\n" "install some routes\n" "Routes to install\n" + "The vrf we would like to install into if non-default\n" + "The NAME of the vrf\n" "v4 Address to start /32 generation at\n" "v6 Address to start /32 generation at\n" "Nexthop to use(Can be an IPv4 or IPv6 address)\n" @@ -149,6 +151,7 @@ DEFPY (install_routes, "Should we repeat this command\n" "How many times to repeat this command\n") { + struct vrf *vrf; struct prefix prefix; uint32_t rts; @@ -176,6 +179,13 @@ DEFPY (install_routes, } sg.r.orig_prefix = prefix; + vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME); + if (!vrf) { + vty_out(vty, "The vrf NAME specified: %s does not exist\n", + name ? name : VRF_DEFAULT_NAME); + return CMD_WARNING; + } + if (nexthop_group) { struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group); if (!nhgc) { @@ -195,12 +205,12 @@ DEFPY (install_routes, sg.r.nhop.type = NEXTHOP_TYPE_IPV6; } - sg.r.nhop.vrf_id = VRF_DEFAULT; + sg.r.nhop.vrf_id = vrf->vrf_id; sg.r.nhop_group.nexthop = &sg.r.nhop; } sg.r.inst = instance; - sg.r.vrf_id = VRF_DEFAULT; + sg.r.vrf_id = vrf->vrf_id; rts = routes; sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, &sg.r.nhop_group, rts); @@ -240,16 +250,19 @@ DEFPY(vrf_label, vrf_label_cmd, DEFPY (remove_routes, remove_routes_cmd, - "sharp remove routes (1-1000000)$routes [instance (0-255)$instance]", + "sharp remove routes [vrf NAME$name] (1-1000000)$routes [instance (0-255)$instance]", "Sharp Routing Protocol\n" "Remove some routes\n" "Routes to remove\n" + "The vrf we would like to remove from if non-default\n" + "The NAME of the vrf\n" "v4 Starting spot\n" "v6 Starting spot\n" "Routes to uninstall\n" "instance to use\n" "Value of instance\n") { + struct vrf *vrf; struct prefix prefix; sg.r.total_routes = routes; @@ -268,8 +281,15 @@ DEFPY (remove_routes, prefix.u.prefix6 = start6; } + vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME); + if (!vrf) { + vty_out(vty, "The vrf NAME specified: %s does not exist\n", + name ? name : VRF_DEFAULT_NAME); + return CMD_WARNING; + } + sg.r.inst = instance; - sg.r.vrf_id = VRF_DEFAULT; + sg.r.vrf_id = vrf->vrf_id; rts = routes; sharp_remove_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, rts); From 91529dc88d20394b64488ade43ec48454f5eb7c6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Feb 2019 08:12:32 -0500 Subject: [PATCH 3/5] sharpd: Add ability to pass vrf we want to watch Add the ability for the sharp zebra code to pass down the vrf that we want to watch. At this point in time, we cannot use it. Signed-off-by: Donald Sharp --- sharpd/sharp_vty.c | 6 ++++-- sharpd/sharp_zebra.c | 4 ++-- sharpd/sharp_zebra.h | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 21fa3cf744..74550d82d4 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -63,7 +63,8 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, p.family = AF_INET6; sharp_nh_tracker_get(&p); - sharp_zebra_nexthop_watch(&p, type_import, true, !!connected); + sharp_zebra_nexthop_watch(&p, VRF_DEFAULT, type_import, + true, !!connected); return CMD_SUCCESS; } @@ -92,7 +93,8 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, p.family = AF_INET; sharp_nh_tracker_get(&p); - sharp_zebra_nexthop_watch(&p, type_import, true, !!connected); + sharp_zebra_nexthop_watch(&p, VRF_DEFAULT, type_import, + true, !!connected); return CMD_SUCCESS; } diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 942040b802..f1e83628c2 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -323,7 +323,7 @@ void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance) return; } -void sharp_zebra_nexthop_watch(struct prefix *p, bool import, +void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import, bool watch, bool connected) { int command; @@ -340,7 +340,7 @@ void sharp_zebra_nexthop_watch(struct prefix *p, bool import, command = ZEBRA_IMPORT_ROUTE_UNREGISTER; } - if (zclient_send_rnh(zclient, command, p, connected, VRF_DEFAULT) < 0) + if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0) zlog_warn("%s: Failure to send nexthop to zebra", __PRETTY_FUNCTION__); } diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 7c3c39c892..57ffcc7690 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -28,8 +28,8 @@ extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label); extern void route_add(struct prefix *p, vrf_id_t, uint8_t instance, struct nexthop_group *nhg); extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance); -extern void sharp_zebra_nexthop_watch(struct prefix *p, bool import, - bool watch, bool connected); +extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, + bool import, bool watch, bool connected); extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, uint8_t instance, From a3b6aa82db8f0caf9e04d93e0c74849db1cc63b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Feb 2019 08:24:20 -0500 Subject: [PATCH 4/5] sharpd: Add code to allow nexthops to be watched from non-default vrf Add a bit of code to the sharp cli to allow it to specify a non-default vrf. Signed-off-by: Donald Sharp --- sharpd/sharp_vty.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 74550d82d4..fbcbbe3fdc 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -39,17 +39,28 @@ #endif DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, - "sharp watch X:X::X:X$nhop [connected$connected]", + "sharp watch [vrf NAME$name] X:X::X:X$nhop [connected$connected]", "Sharp routing Protocol\n" "Watch for changes\n" + "The vrf we would like to watch if non-default\n" + "The NAME of the vrf\n" "Watch for nexthop changes\n" "Watch for import check changes\n" "The v6 nexthop to signal for watching\n" "Should the route be connected\n") { + struct vrf *vrf; struct prefix p; bool type_import; + if (!name) + name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(name); + if (!vrf) { + vty_out(vty, "The vrf NAME specified: %s does not exist\n", + name); + return CMD_WARNING; + } if (n) type_import = false; @@ -63,24 +74,36 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, p.family = AF_INET6; sharp_nh_tracker_get(&p); - sharp_zebra_nexthop_watch(&p, VRF_DEFAULT, type_import, + sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import, true, !!connected); return CMD_SUCCESS; } DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, - "sharp watch A.B.C.D$nhop [connected$connected]", + "sharp watch [vrf NAME$name] A.B.C.D$nhop [connected$connected]", "Sharp routing Protocol\n" "Watch for changes\n" + "The vrf we would like to watch if non-default\n" + "The NAME of the vrf\n" "Watch for nexthop changes\n" "Watch for import check changes\n" "The v4 nexthop to signal for watching\n" "Should the route be connected\n") { + struct vrf *vrf; struct prefix p; bool type_import; + if (!name) + name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(name); + if (!vrf) { + vty_out(vty, "The vrf NAME specified: %s does not exist\n", + name); + return CMD_WARNING; + } + memset(&p, 0, sizeof(p)); if (n) @@ -93,7 +116,7 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, p.family = AF_INET; sharp_nh_tracker_get(&p); - sharp_zebra_nexthop_watch(&p, VRF_DEFAULT, type_import, + sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import, true, !!connected); return CMD_SUCCESS; @@ -181,10 +204,13 @@ DEFPY (install_routes, } sg.r.orig_prefix = prefix; - vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME); + if (!name) + name = VRF_DEFAULT_NAME; + + vrf = vrf_lookup_by_name(name); if (!vrf) { vty_out(vty, "The vrf NAME specified: %s does not exist\n", - name ? name : VRF_DEFAULT_NAME); + name); return CMD_WARNING; } From bd4fb6158ddafa10b86a3a382934ed7a8c6e7afc Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 28 Feb 2019 09:11:41 -0500 Subject: [PATCH 5/5] zebra: Upon vrf deletion, actually release this data. When a vrf is deleted we need to tell the zebra_router that we have finished using the tables we are keeping track of. This will allow us to properly cleanup the data structures associated with them. This fixes this valgrind error found: ==8579== Invalid read of size 8 ==8579== at 0x430034: zvrf_id (zebra_vrf.h:167) ==8579== by 0x432366: rib_process (zebra_rib.c:1580) ==8579== by 0x432366: process_subq (zebra_rib.c:2092) ==8579== by 0x432366: meta_queue_process (zebra_rib.c:2188) ==8579== by 0x48C99FE: work_queue_run (workqueue.c:291) ==8579== by 0x48C3788: thread_call (thread.c:1607) ==8579== by 0x48A2E9E: frr_run (libfrr.c:1011) ==8579== by 0x41316A: main (main.c:473) ==8579== Address 0x5aeb750 is 0 bytes inside a block of size 4,424 free'd ==8579== at 0x4839A0C: free (vg_replace_malloc.c:540) ==8579== by 0x438914: zebra_vrf_delete (zebra_vrf.c:279) ==8579== by 0x48C4225: vrf_delete (vrf.c:243) ==8579== by 0x48C4225: vrf_delete (vrf.c:217) ==8579== by 0x4151CE: netlink_vrf_change (if_netlink.c:364) ==8579== by 0x416810: netlink_link_change (if_netlink.c:1189) ==8579== by 0x41C1FC: netlink_parse_info (kernel_netlink.c:904) ==8579== by 0x41C2D3: kernel_read (kernel_netlink.c:389) ==8579== by 0x48C3788: thread_call (thread.c:1607) ==8579== by 0x48A2E9E: frr_run (libfrr.c:1011) ==8579== by 0x41316A: main (main.c:473) ==8579== Block was alloc'd at ==8579== at 0x483AB1A: calloc (vg_replace_malloc.c:762) ==8579== by 0x48A6030: qcalloc (memory.c:110) ==8579== by 0x4389EF: zebra_vrf_alloc (zebra_vrf.c:382) ==8579== by 0x438A42: zebra_vrf_new (zebra_vrf.c:93) ==8579== by 0x48C40AD: vrf_get (vrf.c:209) ==8579== by 0x415144: netlink_vrf_change (if_netlink.c:319) ==8579== by 0x415E90: netlink_interface (if_netlink.c:653) ==8579== by 0x41C1FC: netlink_parse_info (kernel_netlink.c:904) ==8579== by 0x4163E8: interface_lookup_netlink (if_netlink.c:760) ==8579== by 0x42BB37: zebra_ns_enable (zebra_ns.c:130) ==8579== by 0x42BC5E: zebra_ns_init (zebra_ns.c:208) ==8579== by 0x4130F4: main (main.c:401) This can be found by: `ip link del ` then `ip link add type vrf table X` again and then attempting to use the vrf. Signed-off-by: Donald Sharp --- zebra/zebra_router.c | 21 +++++++++++++++++++++ zebra/zebra_router.h | 2 ++ zebra/zebra_vrf.c | 13 +++++++------ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index c3b861c242..cabc8be8dd 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -168,10 +168,31 @@ static void zebra_router_free_table(struct zebra_router_table *zrt) table_info = route_table_get_info(zrt->table); route_table_finish(zrt->table); + RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); XFREE(MTYPE_ZEBRA_NS, zrt); } +void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid, + afi_t afi, safi_t safi) +{ + struct zebra_router_table finder; + struct zebra_router_table *zrt; + + memset(&finder, 0, sizeof(finder)); + finder.afi = afi; + finder.safi = safi; + finder.tableid = tableid; + finder.ns_id = zvrf->zns->ns_id; + zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder); + + if (!zrt) + return; + + zebra_router_free_table(zrt); +} + uint32_t zebra_router_get_next_sequence(void) { return 1 diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index fb28495917..e5043f38ae 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -117,6 +117,8 @@ extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf, extern struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf, uint32_t tableid, afi_t afi, safi_t safi); +extern void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid, + afi_t afi, safi_t safi); extern int zebra_router_config_write(struct vty *vty); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index d18305495b..390c01dc67 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -208,8 +208,11 @@ static int zebra_vrf_disable(struct vrf *vrf) * table, see rib_close_table above * we no-longer need this pointer. */ - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { + zebra_router_release_table(zvrf, zvrf->table_id, afi, + safi); zvrf->table[afi][safi] = NULL; + } route_table_finish(zvrf->rnh_table[afi]); zvrf->rnh_table[afi] = NULL; @@ -256,14 +259,12 @@ static int zebra_vrf_delete(struct vrf *vrf) /* release allocated memory */ for (afi = AFI_IP; afi <= AFI_IP6; afi++) { - void *table_info; - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { table = zvrf->table[afi][safi]; if (table) { - table_info = route_table_get_info(table); - route_table_finish(table); - XFREE(MTYPE_RIB_TABLE_INFO, table_info); + zebra_router_release_table(zvrf, zvrf->table_id, + afi, safi); + zvrf->table[afi][safi] = NULL; } }