diff options
| author | Philippe Guibert <philippe.guibert@6wind.com> | 2018-02-08 11:46:29 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-08 11:46:29 +0100 |
| commit | 8e71b98f72e843d4910abd02410f07fe1e6565cc (patch) | |
| tree | a84f92632eb0deed948f6b961c489573ede1ac0b /zebra/zebra_vrf.c | |
| parent | 25236dd35df008a1484f2605299c8228ea1cfc5b (diff) | |
| parent | 9d00a48754440cc9d4674e9b9405642edd983f0f (diff) | |
Merge pull request #1654 from mkanjari/evpn-symm-routing-enhancements
Evpn symmetric routing enhancements
Diffstat (limited to 'zebra/zebra_vrf.c')
| -rw-r--r-- | zebra/zebra_vrf.c | 233 |
1 files changed, 176 insertions, 57 deletions
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 246a7e7e4c..b9b3048486 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -41,6 +41,11 @@ 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) { @@ -82,7 +87,7 @@ static int zebra_vrf_new(struct vrf *vrf) 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( @@ -101,14 +106,36 @@ static int zebra_vrf_enable(struct vrf *vrf) 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]; @@ -132,6 +159,9 @@ static int zebra_vrf_enable(struct vrf *vrf) } } + /* Kick off any VxLAN-EVPN processing. */ + zebra_vxlan_vrf_enable(zvrf); + return 0; } @@ -142,13 +172,19 @@ static int zebra_vrf_disable(struct vrf *vrf) 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]; @@ -161,6 +197,84 @@ static int zebra_vrf_disable(struct vrf *vrf) 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; } @@ -174,38 +288,9 @@ static int zebra_vrf_delete(struct vrf *vrf) 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++) { @@ -213,8 +298,7 @@ static int zebra_vrf_delete(struct vrf *vrf) 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); @@ -224,22 +308,27 @@ static int zebra_vrf_delete(struct vrf *vrf) } } + /* 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; @@ -251,7 +340,7 @@ static int zebra_vrf_delete(struct vrf *vrf) 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); @@ -262,6 +351,37 @@ static int zebra_vrf_delete(struct vrf *vrf) 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. */ @@ -354,9 +474,9 @@ struct zebra_vrf *zebra_vrf_alloc(void) 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 @@ -364,14 +484,6 @@ struct zebra_vrf *zebra_vrf_alloc(void) 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); @@ -477,16 +589,23 @@ static int vrf_config_write(struct vty *vty) 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"); } |
