Index: sys/netinet/in_proto.c =================================================================== --- sys/netinet/in_proto.c +++ sys/netinet/in_proto.c @@ -113,7 +113,6 @@ .pr_domain = &inetdomain, .pr_protocol = IPPROTO_IP, .pr_flags = PR_CAPATTACH, - .pr_slowtimo = ip_slowtimo, .pr_drain = ip_drain, .pr_usrreqs = &nousrreqs }, Index: sys/netinet/ip_input.c =================================================================== --- sys/netinet/ip_input.c +++ sys/netinet/ip_input.c @@ -102,7 +102,6 @@ /* IP reassembly functions are defined in ip_reass.c. */ extern void ipreass_init(void); extern void ipreass_drain(void); -extern void ipreass_slowtimo(void); #ifdef VIMAGE extern void ipreass_destroy(void); #endif @@ -846,25 +845,6 @@ m_freem(m); } -/* - * IP timer processing; - * if a timer expires on a reassembly - * queue, discard it. - */ -void -ip_slowtimo(void) -{ - VNET_ITERATOR_DECL(vnet_iter); - - VNET_LIST_RLOCK_NOSLEEP(); - VNET_FOREACH(vnet_iter) { - CURVNET_SET(vnet_iter); - ipreass_slowtimo(); - CURVNET_RESTORE(); - } - VNET_LIST_RUNLOCK_NOSLEEP(); -} - void ip_drain(void) { Index: sys/netinet/ip_reass.c =================================================================== --- sys/netinet/ip_reass.c +++ sys/netinet/ip_reass.c @@ -93,7 +93,6 @@ void ipreass_init(void); void ipreass_drain(void); -void ipreass_slowtimo(void); #ifdef VIMAGE void ipreass_destroy(void); #endif @@ -556,6 +555,48 @@ #undef GETIP } +/* + * If a timer expires on a reassembly queue, discard it. + */ +static struct callout ipreass_callout; +static void +ipreass_slowtimo(void *arg __unused) +{ + VNET_ITERATOR_DECL(vnet_iter); + struct ipq *fp, *tmp; + + if (atomic_load_int(&nfrags) == 0) + return; + + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + for (int i = 0; i < IPREASS_NHASH; i++) { + if (TAILQ_EMPTY(&V_ipq[i].head)) + continue; + IPQ_LOCK(i); + TAILQ_FOREACH_SAFE(fp, &V_ipq[i].head, ipq_list, tmp) + if (--fp->ipq_ttl == 0) + ipq_timeout(&V_ipq[i], fp); + IPQ_UNLOCK(i); + } + CURVNET_RESTORE(); + } + VNET_LIST_RUNLOCK_NOSLEEP(); + + callout_reset_sbt(&ipreass_callout, SBT_1MS * 500, SBT_1MS * 10, + ipreass_slowtimo, NULL, 0); +} + +static void +ipreass_timer_init(void *arg __unused) +{ + + callout_init(&ipreass_callout, 1); + callout_reset_sbt(&ipreass_callout, SBT_1MS * 500, SBT_1MS * 10, + ipreass_slowtimo, NULL, 0); +} +SYSINIT(ipreass, SI_SUB_VNET_DONE, SI_ORDER_ANY, ipreass_timer_init, NULL); + /* * Initialize IP reassembly structures. */ @@ -585,28 +626,6 @@ } } -/* - * If a timer expires on a reassembly queue, discard it. - */ -void -ipreass_slowtimo(void) -{ - struct ipq *fp, *tmp; - - if (atomic_load_int(&nfrags) == 0) - return; - - for (int i = 0; i < IPREASS_NHASH; i++) { - if (TAILQ_EMPTY(&V_ipq[i].head)) - continue; - IPQ_LOCK(i); - TAILQ_FOREACH_SAFE(fp, &V_ipq[i].head, ipq_list, tmp) - if (--fp->ipq_ttl == 0) - ipq_timeout(&V_ipq[i], fp); - IPQ_UNLOCK(i); - } -} - /* * Drain off all datagram fragments. */ Index: sys/netinet/ip_var.h =================================================================== --- sys/netinet/ip_var.h +++ sys/netinet/ip_var.h @@ -228,7 +228,6 @@ ip_reass(struct mbuf *); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); -void ip_slowtimo(void); void ip_fillid(struct ip *); int rip_ctloutput(struct socket *, struct sockopt *); void rip_ctlinput(int, struct sockaddr *, void *);