]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Refine cleanup when a VRF with configuration gets deleted
authorvivek <vivek@cumulusnetworks.com>
Mon, 11 Dec 2017 22:38:15 +0000 (14:38 -0800)
committermitesh <mitesh@cumulusnetworks.com>
Wed, 24 Jan 2018 00:27:25 +0000 (16:27 -0800)
When a VRF gets deleted - e.g., networking restart or ifdown of the VRF - but
has associated FRR configuration, additional cleanup of all dynamic data pertaining
to this VRF is necessary. This includes the routing tables, next hop tables,
temporary queues for this VRF etc. Only the FRR configuration for this VRF must
be retained.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Reviewed-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-19148
Reviewed By: CCR-7030
Testing Done:
1. Manual testing - This scenario and EVPN configuration
2. Various smoke tests - vrf, bgp, pim, l3-smoke

zebra/zebra_vrf.c

index 6c9171c95cde753e03d5715eaf7ffcd5638ec686..54c9f573c94375eaab293ddc79ffe031fc4c52d6 100644 (file)
 
 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)
 {
@@ -101,6 +106,7 @@ 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;
@@ -115,6 +121,20 @@ static int zebra_vrf_enable(struct vrf *vrf)
         */
        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++) {
@@ -152,9 +172,12 @@ 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;
 
        assert(zvrf);
        if (IS_ZEBRA_DEBUG_EVENT)
@@ -182,33 +205,74 @@ static int zebra_vrf_disable(struct vrf *vrf)
         */
        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;
@@ -234,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);
@@ -255,16 +318,17 @@ static int zebra_vrf_delete(struct vrf *vrf)
 
                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;
@@ -379,9 +443,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
@@ -389,14 +453,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);