extern struct zebra_t zebrad;
+static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
+ safi_t safi);
+static void zebra_rnhtable_node_cleanup(struct route_table *table,
+ struct route_node *node);
+
/* VRF information update. */
static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
{
struct route_table *stable;
struct route_node *rn;
struct static_route *si;
+ struct route_table *table;
struct interface *ifp;
afi_t afi;
safi_t safi;
*/
zebra_vrf_add_update(zvrf);
+ /* Allocate tables */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ zebra_vrf_table_create(zvrf, afi, safi);
+
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->rnh_table[afi] = table;
+
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->import_check_table[afi] = table;
+ }
+
/* Install any static routes configured for this VRF. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
struct route_table *stable;
struct route_node *rn;
struct static_route *si;
+ struct route_table *table;
+ struct interface *ifp;
u_int32_t table_id;
afi_t afi;
safi_t safi;
+ unsigned i;
assert(zvrf);
if (IS_ZEBRA_DEBUG_EVENT)
*/
zebra_vrf_delete_update(zvrf);
- /* uninstall all routes */
- if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) {
- struct interface *ifp;
-
- for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
- for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST;
- safi++)
- rib_close_table(zvrf->table[afi][safi]);
-
- if (vrf->vrf_id == VRF_DEFAULT)
- for (table_id = 0;
- table_id < ZEBRA_KERNEL_TABLE_MAX;
- table_id++)
- if (zvrf->other_table[afi][table_id])
- rib_close_table(
- zvrf->other_table
- [afi]
- [table_id]);
+ /* If asked to retain routes, there's nothing more to do. */
+ if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN))
+ return 0;
+
+ /* Remove all routes. */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ rib_close_table(zvrf->table[afi][safi]);
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
+ table_id++)
+ if (zvrf->other_table[afi][table_id])
+ rib_close_table(zvrf->other_table[afi][table_id]);
+ }
+
+ /* Cleanup Vxlan, MPLS and PW tables. */
+ zebra_vxlan_cleanup_tables(zvrf);
+ zebra_mpls_cleanup_tables(zvrf);
+ zebra_pw_exit(zvrf);
+
+ /* Remove link-local IPv4 addresses created for BGP unnumbered peering. */
+ FOR_ALL_INTERFACES (vrf, ifp)
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
+
+ /* clean-up work queues */
+ for (i = 0; i < MQ_SIZE; i++) {
+ struct listnode *lnode, *nnode;
+ struct route_node *rnode;
+ rib_dest_t *dest;
+
+ for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
+ dest = rib_dest_from_rnode(rnode);
+ if (dest && rib_dest_vrf(dest) == zvrf) {
+ route_unlock_node(rnode);
+ list_delete_node(zebrad.mq->subq[i], lnode);
+ zebrad.mq->size--;
+ }
}
+ }
- /* Cleanup Vxlan, MPLS and PW tables. */
- zebra_vxlan_cleanup_tables(zvrf);
- zebra_mpls_cleanup_tables(zvrf);
- zebra_pw_exit(zvrf);
+ /* Cleanup (free) routing tables and NHT tables. */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ void *table_info;
- FOR_ALL_INTERFACES (vrf, ifp)
- if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
+ table = zvrf->table[afi][safi];
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ zvrf->table[afi][safi] = NULL;
+ }
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
+ table_id++)
+ if (zvrf->other_table[afi][table_id]) {
+ table = zvrf->other_table[afi][table_id];
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ zvrf->other_table[afi][table_id] = NULL;
+ }
+
+ route_table_finish(zvrf->rnh_table[afi]);
+ zvrf->rnh_table[afi] = NULL;
+ route_table_finish(zvrf->import_check_table[afi]);
+ zvrf->import_check_table[afi] = NULL;
}
return 0;
struct route_node *rnode;
rib_dest_t *dest;
- for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
- rnode)) {
+ for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
dest = rib_dest_from_rnode(rnode);
if (dest && rib_dest_vrf(dest) == zvrf) {
route_unlock_node(rnode);
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
table = zvrf->table[afi][safi];
- table_info = table->info;
- route_table_finish(table);
- XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ if (table) {
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ }
table = zvrf->stable[afi][safi];
route_table_finish(table);
}
- for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
- table_id++)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
if (zvrf->other_table[afi][table_id]) {
table = zvrf->other_table[afi][table_id];
table_info = table->info;
zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
+ /* Allocate table for static route configuration. */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
- zebra_vrf_table_create(zvrf, afi, safi);
if (afi == AFI_IP6)
table = srcdest_table_init();
else
table->cleanup = zebra_stable_node_cleanup;
zvrf->stable[afi][safi] = table;
}
-
- table = route_table_init();
- table->cleanup = zebra_rnhtable_node_cleanup;
- zvrf->rnh_table[afi] = table;
-
- table = route_table_init();
- table->cleanup = zebra_rnhtable_node_cleanup;
- zvrf->import_check_table[afi] = table;
}
zebra_vxlan_init_tables(zvrf);