diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8cea605f41..e7ab7a47c5 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -903,6 +903,11 @@ void zebra_rtable_node_cleanup(struct route_table *table, rib_unlink(node, re); } + zebra_node_info_cleanup(node); +} + +void zebra_node_info_cleanup(struct route_node *node) +{ if (node->info) { rib_dest_t *dest = node->info; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 7f30067197..7e53a2e804 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -166,9 +166,10 @@ static int zebra_vrf_enable(struct vrf *vrf) static void zebra_vrf_disable_update_vrfid(struct zebra_vrf *zvrf, afi_t afi, safi_t safi) { struct rib_table_info *info; - struct route_entry *re; - struct route_node *rn; + struct route_entry *re, *nre; + struct route_node *rn, *nrn; bool empty_table = true; + bool rn_delete; /* Assign the table to the default VRF. * Although the table is not technically owned by the default VRF, @@ -187,13 +188,30 @@ static void zebra_vrf_disable_update_vrfid(struct zebra_vrf *zvrf, afi_t afi, sa continue; } - /* Assign the route entries to the default VRF, + /* Assign the kernel route entries to the default VRF, * even though they are not actually owned by it. + * + * Remove route nodes that have been created by FRR daemons. + * They are not needed if the VRF is disabled. */ - RNODE_FOREACH_RE (rn, re) - nexthop_vrf_update(rn, re, VRF_DEFAULT); - - rn = route_next(rn); + rn_delete = true; + RNODE_FOREACH_RE_SAFE (rn, re, nre) { + if (re->type == ZEBRA_ROUTE_KERNEL) { + nexthop_vrf_update(rn, re, VRF_DEFAULT); + rn_delete = false; + } else + rib_unlink(rn, re); + } + if (rn_delete) { + nrn = route_next(rn); + zebra_node_info_cleanup(rn); + rn->info = NULL; + route_unlock_node(rn); + rn = nrn; + } else { + empty_table = false; + rn = route_next(rn); + } } if (empty_table) diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 334bb93684..289a8fcc47 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -263,6 +263,8 @@ extern void zebra_vrf_init(void); extern void zebra_rtable_node_cleanup(struct route_table *table, struct route_node *node); +extern void zebra_node_info_cleanup(struct route_node *node); + #ifdef __cplusplus }