diff --git a/lib/vrf.c b/lib/vrf.c index 9f4c5cdddc4b..e907626bae59 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -326,6 +326,33 @@ void vrf_disable(struct vrf *vrf) (*vrf_master.vrf_disable_hook)(vrf); } +void vrf_iterate(vrf_iter_func fnc) +{ + struct vrf *vrf, *tmp; + + if (debug_vrf) + zlog_debug("%s: vrf subsystem iteration", __func__); + + RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) { + if (vrf->vrf_id == VRF_DEFAULT) + continue; + + fnc(vrf); + } + + RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) { + if (vrf->vrf_id == VRF_DEFAULT) + continue; + + fnc(vrf); + } + + /* Finally process default VRF */ + vrf = vrf_lookup_by_id(VRF_DEFAULT); + if (vrf) + fnc(vrf); +} + const char *vrf_id_to_name(vrf_id_t vrf_id) { struct vrf *vrf; @@ -542,32 +569,12 @@ static void vrf_terminate_single(struct vrf *vrf) vrf_delete(vrf); } -/* Terminate VRF module. */ void vrf_terminate(void) { - struct vrf *vrf, *tmp; - if (debug_vrf) zlog_debug("%s: Shutting down vrf subsystem", __func__); - RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) { - if (vrf->vrf_id == VRF_DEFAULT) - continue; - - vrf_terminate_single(vrf); - } - - RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) { - if (vrf->vrf_id == VRF_DEFAULT) - continue; - - vrf_terminate_single(vrf); - } - - /* Finally terminate default VRF */ - vrf = vrf_lookup_by_id(VRF_DEFAULT); - if (vrf) - vrf_terminate_single(vrf); + vrf_iterate(vrf_terminate_single); } int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, diff --git a/lib/vrf.h b/lib/vrf.h index 4277a51bb1b8..3ebb6ddf5371 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -201,6 +201,12 @@ extern void vrf_init(int (*create)(struct vrf *vrf), int (*disable)(struct vrf *vrf), int (*destroy)(struct vrf *vrf)); +/* + * Iterate over custom VRFs and round up by processing the default VRF. + */ +typedef void (*vrf_iter_func)(struct vrf *vrf); +extern void vrf_iterate(vrf_iter_func fnc); + /* * Call vrf_terminate when the protocol is being shutdown */ diff --git a/zebra/main.c b/zebra/main.c index 27e98ed999f1..d83f1d0491bf 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -205,6 +205,12 @@ static void sigint(void) list_delete(&zrouter.client_list); list_delete(&zrouter.stale_client_list); + /* + * Besides other clean-ups zebra's vrf_disable() also enqueues installed + * routes for removal from the kernel, unless ZEBRA_VRF_RETAIN is set. + */ + vrf_iterate(vrf_disable); + /* Indicate that all new dplane work has been enqueued. When that * work is complete, the dataplane will enqueue an event * with the 'finalize' function.