From fb8bf9cf5929967e9a453679ae7b498203936ff8 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Thu, 22 Aug 2024 11:12:29 +0200 Subject: [PATCH] zebra: remove vrf route entries at vrf disabling This is the continuation of the previous commit. When a VRF is deleted, the kernel retains only its own routing entries in the former VRF table and removes all others. This change ensures that routing entries created by FRR daemons are also removed from the former zebra VRF table when the VRF is disabled. To test: > echo "100 my_table" | tee -a /etc/iproute2/rt_tables > ip l add du0 type dummy > ifconfig du0 192.168.0.1/24 up > ip route add blackhole default table 100 > ip route show table 100 > ip l add red type vrf table 100 > ip l set du0 master red > vtysh -c 'configure' -c 'vrf red' -c 'ip route 10.0.0.0/24 192.168.0.254' > vtysh -c 'show ip route table 100' > sleep 0.1 > ip l del red > sleep 0.1 > vtysh -c 'show ip route table 100' > ip l add red type vrf table 100 > ip l set du0 master red > vtysh -c 'configure' -c 'vrf red' -c 'ip route 10.0.0.0/24 192.168.0.254' > vtysh -c 'show ip route table 100' > sleep 0.1 > ip l del red > sleep 0.1 > vtysh -c 'show ip route table 100' Fixes: d8612e6 ("zebra: Track tables allocated by vrf and cleanup") Signed-off-by: Louis Scalbert --- zebra/zebra_rib.c | 5 +++++ zebra/zebra_vrf.c | 32 +++++++++++++++++++++++++------- zebra/zebra_vrf.h | 2 ++ 3 files changed, 32 insertions(+), 7 deletions(-) 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 }