Index: sys/netinet/in_proto.c =================================================================== --- sys/netinet/in_proto.c +++ sys/netinet/in_proto.c @@ -120,7 +120,6 @@ .pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD| PR_CAPATTACH, .pr_ctloutput = tcp_ctloutput, - .pr_slowtimo = tcp_slowtimo, .pr_drain = tcp_drain, .pr_usrreqs = &tcp_usrreqs }, Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c +++ sys/netinet/tcp_subr.c @@ -1568,6 +1568,9 @@ #ifdef INET6 IP6PROTO_REGISTER(IPPROTO_TCP, tcp6_input, tcp6_ctlinput); #endif + + callout_init(&tcpslow_callout, 1); + callout_reset(&tcpslow_callout, hz / 2, tcp_slowtimo, NULL); } SYSINIT(tcp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, tcp_init, NULL); Index: sys/netinet/tcp_timer.c =================================================================== --- sys/netinet/tcp_timer.c +++ sys/netinet/tcp_timer.c @@ -233,15 +233,17 @@ } /* - * Tcp protocol timeout routine called every 500 ms. - * Updates timestamps used for TCP - * causes finite state machine actions if timers expire. + * Legacy TCP global callout routine called every 500 ms. + * Used to cleanup timewait states, which lack their own callouts. */ +struct callout tcpslow_callout; void -tcp_slowtimo(void) +tcp_slowtimo(void *arg __unused) { + struct epoch_tracker et; VNET_ITERATOR_DECL(vnet_iter); + NET_EPOCH_ENTER(et); VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); @@ -249,6 +251,9 @@ CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); + NET_EPOCH_EXIT(et); + + callout_reset(&tcpslow_callout, hz / 2, tcp_slowtimo, NULL); } int tcp_backoff[TCP_MAXRXTSHIFT + 1] = Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -1187,7 +1187,8 @@ int tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); void tcp_setpersist(struct tcpcb *); -void tcp_slowtimo(void); +extern struct callout tcpslow_callout; +void tcp_slowtimo(void *); void tcp_record_dsack(struct tcpcb *tp, tcp_seq start, tcp_seq end, int tlp); struct tcptemp * tcpip_maketemplate(struct inpcb *); Index: sys/netinet6/in6_proto.c =================================================================== --- sys/netinet6/in6_proto.c +++ sys/netinet6/in6_proto.c @@ -163,7 +163,6 @@ PR_LISTEN|PR_CAPATTACH, .pr_ctloutput = tcp_ctloutput, #ifndef INET /* don't call initialization, timeout, and drain routines twice */ - .pr_slowtimo = tcp_slowtimo, .pr_drain = tcp_drain, #endif .pr_usrreqs = &tcp6_usrreqs,