diff --git a/sys/net/route.c b/sys/net/route.c index 6c42e8f6eda5..0b7a0e2d55b6 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -348,7 +348,7 @@ rt_table_init(int offset, int family, u_int fibnum) nhops_init_rib(rh); /* Init subscription system */ - CK_STAILQ_INIT(&rh->rnh_subscribers); + rib_init_subscriptions(rh); /* Finally, set base callbacks */ rh->rnh_addaddr = rn_addroute; @@ -383,6 +383,8 @@ rt_table_destroy(struct rib_head *rh) nhops_destroy_rib(rh); + rib_destroy_subscriptions(rh); + /* Assume table is already empty */ RIB_LOCK_DESTROY(rh); free(rh, M_RTABLE); diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index 6218b82a935a..a573a07178e4 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -847,3 +847,28 @@ destroy_subscription_epoch(epoch_context_t ctx) free(rs, M_RTABLE); } + +void +rib_init_subscriptions(struct rib_head *rnh) +{ + + CK_STAILQ_INIT(&rnh->rnh_subscribers); +} + +void +rib_destroy_subscriptions(struct rib_head *rnh) +{ + struct rib_subscription *rs; + struct epoch_tracker et; + + NET_EPOCH_ENTER(et); + RIB_WLOCK(rnh); + while ((rs = CK_STAILQ_FIRST(&rnh->rnh_subscribers)) != NULL) { + CK_STAILQ_REMOVE_HEAD(&rnh->rnh_subscribers, next); + epoch_call(net_epoch_preempt, destroy_subscription_epoch, + &rs->epoch_ctx); + } + RIB_WUNLOCK(rnh); + NET_EPOCH_EXIT(et); +} + diff --git a/sys/net/route/shared.h b/sys/net/route/shared.h index ce5075896c96..4ea20c5e011e 100644 --- a/sys/net/route/shared.h +++ b/sys/net/route/shared.h @@ -67,6 +67,10 @@ int nhop_create_from_nhop(struct rib_head *rnh, const struct nhop_object *nh_ori void nhops_update_ifmtu(struct rib_head *rh, struct ifnet *ifp, uint32_t mtu); int nhops_dump_sysctl(struct rib_head *rh, struct sysctl_req *w); +/* subscriptions */ +void rib_init_subscriptions(struct rib_head *rnh); +void rib_destroy_subscriptions(struct rib_head *rnh); + /* route */ VNET_DECLARE(uma_zone_t, rtzone); /* Routing table UMA zone. */ #define V_rtzone VNET(rtzone)