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 <louis.scalbert@6wind.com>
This commit is contained in:
Louis Scalbert 2024-08-22 11:12:29 +02:00
parent 7395e399b1
commit fb8bf9cf59
3 changed files with 32 additions and 7 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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
}