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 zebra_vrf *zvrf;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
+ zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id);
zvrf = zebra_vrf_alloc();
zvrf->zns = zebra_ns_lookup(
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;
assert(zvrf);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u is now active",
+ zvrf_name(zvrf), zvrf_id(zvrf));
+ /* Inform clients that the VRF is now active. This is an
+ * add for the clients.
+ */
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++) {
stable = zvrf->stable[afi][safi];
}
}
+ /* Kick off any VxLAN-EVPN processing. */
+ zebra_vxlan_vrf_enable(zvrf);
+
return 0;
}
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;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf),
- zvrf_id(zvrf));
+ assert(zvrf);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u is now inactive",
+ zvrf_name(zvrf), zvrf_id(zvrf));
+ /* Uninstall any static routes configured for this VRF. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
stable = zvrf->stable[afi][safi];
afi, safi, &rn->p, NULL, si);
}
+ /* Stop any VxLAN-EVPN processing. */
+ zebra_vxlan_vrf_disable(zvrf);
+
+ /* Inform clients that the VRF is now inactive. This is a
+ * delete for the clients.
+ */
+ zebra_vrf_delete_update(zvrf);
+
+ /* 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 (free) routing tables and NHT tables. */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ void *table_info;
+
+ 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;
}
unsigned i;
assert(zvrf);
-
- zebra_vrf_delete_update(zvrf);
-
- /* uninstall everything */
- 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]);
- }
-
- /* Cleanup Vxlan table and update kernel */
- zebra_vxlan_close_tables(zvrf);
-
- zebra_mpls_close_tables(zvrf);
- zebra_pw_exit(zvrf);
-
- FOR_ALL_INTERFACES (vrf, ifp)
- if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
- }
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u deleted",
+ zvrf_name(zvrf), zvrf_id(zvrf));
/* clean-up work queues */
for (i = 0; i < MQ_SIZE; i++) {
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);
}
}
+ /* Free Vxlan and MPLS. */
+ zebra_vxlan_close_tables(zvrf);
+ zebra_mpls_close_tables(zvrf);
+
/* 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];
- 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;
route_table_finish(zvrf->import_check_table[afi]);
}
- /* cleanup evpn states for vrf */
+ /* Cleanup EVPN states for vrf */
zebra_vxlan_vrf_delete(zvrf);
list_delete_all_node(zvrf->rid_all_sorted_list);
return 0;
}
+/* Return if this VRF has any FRR configuration or not.
+ * IMPORTANT: This function needs to be updated when additional configuration
+ * is added for a VRF.
+ */
+int zebra_vrf_has_config(struct zebra_vrf *zvrf)
+{
+ afi_t afi;
+ safi_t safi;
+ struct route_table *stable;
+
+ /* NOTE: This is a don't care for the default VRF, but we go through
+ * the motions to keep things consistent.
+ */
+ /* Any static routes? */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ stable = zvrf->stable[afi][safi];
+ if (!stable)
+ continue;
+ if (route_table_count(stable))
+ return 1;
+ }
+ }
+
+ /* EVPN L3-VNI? */
+ if (zvrf->l3vni)
+ return 1;
+
+ return 0;
+}
+
/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
* NOTE: Table-id is relevant only in the Default VRF.
*/
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);
if (!zvrf)
continue;
- if (vrf->vrf_id != VRF_DEFAULT)
+ if (zvrf_id(zvrf) == VRF_DEFAULT) {
+ if (zvrf->l3vni)
+ vty_out(vty, "vni %u\n", zvrf->l3vni);
+ vty_out(vty, "!\n");
+ }
+
+ if (vrf_is_user_cfged(vrf)) {
vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
+ if (zvrf->l3vni)
+ vty_out(vty, " vni %u\n", zvrf->l3vni);
+ vty_out(vty, "!\n");
+ }
static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
- if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
- vty_out(vty, " vni %u\n", zvrf->l3vni);
-
if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "!\n");
}