Author: jtl Date: Fri Oct 14 14:57:43 2016 New Revision: 307319 URL: https://svnweb.freebsd.org/changeset/base/307319
Log: The code currently resets the keepalive timer each time a packet is received on a TCP session that has entered the ESTABLISHED state. This results in a lot of calls to reset the keepalive timer. This patch changes the behavior so we set the keepalive timer for the keepalive idle time (TP_KEEPIDLE). When the keepalive timer fires, it will first check to see if the session has been idle for TP_KEEPIDLE ticks. If not, it will reschedule the keepalive timer for the time the session will have been idle for TP_KEEPIDLE ticks. For a session with regular communication, the keepalive timer should fire approximately once every TP_KEEPIDLE ticks. For sessions with irregular communication, the keepalive timer might fire more often. But, the disruption from a periodic keepalive timer should be less than the regular cost of resetting the keepalive timer on every packet. (FWIW, this change saved approximately 1.73% of the busy CPU cycles on a particular test system with a heavy TCP output load. Of course, the actual impact is very specific to the particular hardware and workload.) Reviewed by: gallatin, rrs MFC after: 2 weeks Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D8243 Modified: head/sys/netinet/tcp_input.c head/sys/netinet/tcp_stacks/fastpath.c head/sys/netinet/tcp_timer.c Modified: head/sys/netinet/tcp_input.c ============================================================================== --- head/sys/netinet/tcp_input.c Fri Oct 14 12:03:04 2016 (r307318) +++ head/sys/netinet/tcp_input.c Fri Oct 14 14:57:43 2016 (r307319) @@ -1565,8 +1565,6 @@ tcp_do_segment(struct mbuf *m, struct tc * validation to ignore broken/spoofed segs. */ tp->t_rcvtime = ticks; - if (TCPS_HAVEESTABLISHED(tp->t_state)) - tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); /* * Scale up the window into a 32-bit value. Modified: head/sys/netinet/tcp_stacks/fastpath.c ============================================================================== --- head/sys/netinet/tcp_stacks/fastpath.c Fri Oct 14 12:03:04 2016 (r307318) +++ head/sys/netinet/tcp_stacks/fastpath.c Fri Oct 14 14:57:43 2016 (r307319) @@ -1819,8 +1819,6 @@ tcp_do_segment_fastslow(struct mbuf *m, * validation to ignore broken/spoofed segs. */ tp->t_rcvtime = ticks; - if (TCPS_HAVEESTABLISHED(tp->t_state)) - tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); /* * Unscale the window into a 32-bit value. @@ -2266,8 +2264,6 @@ tcp_do_segment_fastack(struct mbuf *m, s * validation to ignore broken/spoofed segs. */ tp->t_rcvtime = ticks; - if (TCPS_HAVEESTABLISHED(tp->t_state)) - tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); /* * Unscale the window into a 32-bit value. Modified: head/sys/netinet/tcp_timer.c ============================================================================== --- head/sys/netinet/tcp_timer.c Fri Oct 14 12:03:04 2016 (r307318) +++ head/sys/netinet/tcp_timer.c Fri Oct 14 14:57:43 2016 (r307319) @@ -468,6 +468,26 @@ tcp_timer_keep(void *xtp) } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); + + /* + * Because we don't regularly reset the keepalive callout in + * the ESTABLISHED state, it may be that we don't actually need + * to send a keepalive yet. If that occurs, schedule another + * call for the next time the keepalive timer might expire. + */ + if (TCPS_HAVEESTABLISHED(tp->t_state)) { + u_int idletime; + + idletime = ticks - tp->t_rcvtime; + if (idletime < TP_KEEPIDLE(tp)) { + callout_reset(&tp->t_timers->tt_keep, + TP_KEEPIDLE(tp) - idletime, tcp_timer_keep, tp); + INP_WUNLOCK(inp); + CURVNET_RESTORE(); + return; + } + } + /* * Keep-alive timer went off; send something * or drop connection if idle for too long. _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"