From owner-svn-src-head@freebsd.org Thu Apr 28 13:27:13 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D4248B1F265; Thu, 28 Apr 2016 13:27:13 +0000 (UTC) (envelope-from rrs@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8173B171B; Thu, 28 Apr 2016 13:27:13 +0000 (UTC) (envelope-from rrs@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u3SDRCDv035712; Thu, 28 Apr 2016 13:27:12 GMT (envelope-from rrs@FreeBSD.org) Received: (from rrs@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u3SDRCIa035707; Thu, 28 Apr 2016 13:27:12 GMT (envelope-from rrs@FreeBSD.org) Message-Id: <201604281327.u3SDRCIa035707@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rrs set sender to rrs@FreeBSD.org using -f From: Randall Stewart Date: Thu, 28 Apr 2016 13:27:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r298743 - in head/sys/netinet: . tcp_stacks X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Apr 2016 13:27:13 -0000 Author: rrs Date: Thu Apr 28 13:27:12 2016 New Revision: 298743 URL: https://svnweb.freebsd.org/changeset/base/298743 Log: This cleans up the timers code in TCP to start using the new async_drain functionality. This as been tested in NF as well as by Verisign. Still to do in here is to remove all the old flags. They are currently left being maintained but probably are no longer needed. Sponsored by: Netflix Inc. Differential Revision: http://reviews.freebsd.org/D5924 Modified: head/sys/netinet/tcp_stacks/fastpath.c head/sys/netinet/tcp_subr.c head/sys/netinet/tcp_timer.c head/sys/netinet/tcp_timer.h head/sys/netinet/tcp_var.h Modified: head/sys/netinet/tcp_stacks/fastpath.c ============================================================================== --- head/sys/netinet/tcp_stacks/fastpath.c Thu Apr 28 13:00:40 2016 (r298742) +++ head/sys/netinet/tcp_stacks/fastpath.c Thu Apr 28 13:27:12 2016 (r298743) @@ -2386,7 +2386,6 @@ struct tcp_function_block __tcp_fastslow NULL, NULL, NULL, - NULL, 0, 0 @@ -2403,7 +2402,6 @@ struct tcp_function_block __tcp_fastack NULL, NULL, NULL, - NULL, 0, 0 }; Modified: head/sys/netinet/tcp_subr.c ============================================================================== --- head/sys/netinet/tcp_subr.c Thu Apr 28 13:00:40 2016 (r298742) +++ head/sys/netinet/tcp_subr.c Thu Apr 28 13:27:12 2016 (r298743) @@ -244,7 +244,6 @@ static struct inpcb *tcp_mtudisc_notify( static void tcp_mtudisc(struct inpcb *, int); static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr, const void *ip6hdr); -static void tcp_timer_discard(struct tcpcb *, uint32_t); static struct tcp_function_block tcp_def_funcblk = { @@ -258,7 +257,6 @@ static struct tcp_function_block tcp_def NULL, NULL, NULL, - NULL, 0, 0 }; @@ -528,7 +526,6 @@ register_tcp_functions(struct tcp_functi return (EINVAL); } if (blk->tfb_tcp_timer_stop_all || - blk->tfb_tcp_timers_left || blk->tfb_tcp_timer_activate || blk->tfb_tcp_timer_active || blk->tfb_tcp_timer_stop) { @@ -537,7 +534,6 @@ register_tcp_functions(struct tcp_functi * must have them all. */ if ((blk->tfb_tcp_timer_stop_all == NULL) || - (blk->tfb_tcp_timers_left == NULL) || (blk->tfb_tcp_timer_activate == NULL) || (blk->tfb_tcp_timer_active == NULL) || (blk->tfb_tcp_timer_stop == NULL)) { @@ -1343,13 +1339,21 @@ tcp_discardcb(struct tcpcb *tp) * callout, and the last discard function called will take care of * deleting the tcpcb. */ + tp->t_timers->tt_draincnt = 0; tcp_timer_stop(tp, TT_REXMT); tcp_timer_stop(tp, TT_PERSIST); tcp_timer_stop(tp, TT_KEEP); tcp_timer_stop(tp, TT_2MSL); tcp_timer_stop(tp, TT_DELACK); if (tp->t_fb->tfb_tcp_timer_stop_all) { - /* Call the stop-all function of the methods */ + /* + * Call the stop-all function of the methods, + * this function should call the tcp_timer_stop() + * method with each of the function specific timeouts. + * That stop will be called via the tfb_tcp_timer_stop() + * which should use the async drain function of the + * callout system (see tcp_var.h). + */ tp->t_fb->tfb_tcp_timer_stop_all(tp); } @@ -1434,13 +1438,8 @@ tcp_discardcb(struct tcpcb *tp) CC_ALGO(tp) = NULL; inp->inp_ppcb = NULL; - if ((tp->t_timers->tt_flags & TT_MASK) == 0) { + if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on tcpcb, let's free it. */ - if ((tp->t_fb->tfb_tcp_timers_left) && - (tp->t_fb->tfb_tcp_timers_left(tp))) { - /* Some fb timers left running! */ - return; - } if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1453,45 +1452,12 @@ tcp_discardcb(struct tcpcb *tp) } void -tcp_timer_2msl_discard(void *xtp) -{ - - tcp_timer_discard((struct tcpcb *)xtp, TT_2MSL); -} - -void -tcp_timer_keep_discard(void *xtp) -{ - - tcp_timer_discard((struct tcpcb *)xtp, TT_KEEP); -} - -void -tcp_timer_persist_discard(void *xtp) -{ - - tcp_timer_discard((struct tcpcb *)xtp, TT_PERSIST); -} - -void -tcp_timer_rexmt_discard(void *xtp) -{ - - tcp_timer_discard((struct tcpcb *)xtp, TT_REXMT); -} - -void -tcp_timer_delack_discard(void *xtp) -{ - - tcp_timer_discard((struct tcpcb *)xtp, TT_DELACK); -} - -void -tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type) +tcp_timer_discard(void *ptp) { struct inpcb *inp; - + struct tcpcb *tp; + + tp = (struct tcpcb *)ptp; CURVNET_SET(tp->t_vnet); INP_INFO_RLOCK(&V_tcbinfo); inp = tp->t_inpcb; @@ -1500,16 +1466,9 @@ tcp_timer_discard(struct tcpcb *tp, uint INP_WLOCK(inp); KASSERT((tp->t_timers->tt_flags & TT_STOPPED) != 0, ("%s: tcpcb has to be stopped here", __func__)); - KASSERT((tp->t_timers->tt_flags & timer_type) != 0, - ("%s: discard callout should be running", __func__)); - tp->t_timers->tt_flags &= ~timer_type; - if ((tp->t_timers->tt_flags & TT_MASK) == 0) { + tp->t_timers->tt_draincnt--; + if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on this tcpcb, let's free it. */ - if ((tp->t_fb->tfb_tcp_timers_left) && - (tp->t_fb->tfb_tcp_timers_left(tp))) { - /* Some fb timers left running! */ - goto leave; - } if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1521,7 +1480,6 @@ tcp_timer_discard(struct tcpcb *tp, uint return; } } -leave: INP_WUNLOCK(inp); INP_INFO_RUNLOCK(&V_tcbinfo); CURVNET_RESTORE(); Modified: head/sys/netinet/tcp_timer.c ============================================================================== --- head/sys/netinet/tcp_timer.c Thu Apr 28 13:00:40 2016 (r298742) +++ head/sys/netinet/tcp_timer.c Thu Apr 28 13:27:12 2016 (r298743) @@ -927,7 +927,6 @@ void tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type) { struct callout *t_callout; - timeout_t *f_callout; uint32_t f_reset; tp->t_timers->tt_flags |= TT_STOPPED; @@ -935,27 +934,22 @@ tcp_timer_stop(struct tcpcb *tp, uint32_ switch (timer_type) { case TT_DELACK: t_callout = &tp->t_timers->tt_delack; - f_callout = tcp_timer_delack_discard; f_reset = TT_DELACK_RST; break; case TT_REXMT: t_callout = &tp->t_timers->tt_rexmt; - f_callout = tcp_timer_rexmt_discard; f_reset = TT_REXMT_RST; break; case TT_PERSIST: t_callout = &tp->t_timers->tt_persist; - f_callout = tcp_timer_persist_discard; f_reset = TT_PERSIST_RST; break; case TT_KEEP: t_callout = &tp->t_timers->tt_keep; - f_callout = tcp_timer_keep_discard; f_reset = TT_KEEP_RST; break; case TT_2MSL: t_callout = &tp->t_timers->tt_2msl; - f_callout = tcp_timer_2msl_discard; f_reset = TT_2MSL_RST; break; default: @@ -971,21 +965,13 @@ tcp_timer_stop(struct tcpcb *tp, uint32_ } if (tp->t_timers->tt_flags & timer_type) { - if ((callout_stop(t_callout) > 0) && - (tp->t_timers->tt_flags & f_reset)) { - tp->t_timers->tt_flags &= ~(timer_type | f_reset); - } else { + if (callout_async_drain(t_callout, tcp_timer_discard) == 0) { /* * Can't stop the callout, defer tcpcb actual deletion - * to the last tcp timer discard callout. - * The TT_STOPPED flag will ensure that no tcp timer - * callouts can be restarted on our behalf, and - * past this point currently running callouts waiting - * on inp lock will return right away after the - * classical check for callout reset/stop events: - * callout_pending() || !callout_active() + * to the last one. We do this using the async drain + * function and incrementing the count in */ - callout_reset(t_callout, 1, f_callout, tp); + tp->t_timers->tt_draincnt++; } } } Modified: head/sys/netinet/tcp_timer.h ============================================================================== --- head/sys/netinet/tcp_timer.h Thu Apr 28 13:00:40 2016 (r298742) +++ head/sys/netinet/tcp_timer.h Thu Apr 28 13:27:12 2016 (r298743) @@ -146,7 +146,7 @@ struct tcp_timer { struct callout tt_2msl; /* 2*msl TIME_WAIT timer */ struct callout tt_delack; /* delayed ACK timer */ uint32_t tt_flags; /* Timers flags */ - uint32_t tt_spare; /* TDB */ + uint32_t tt_draincnt; /* Count being drained */ }; /* @@ -193,17 +193,13 @@ extern int tcp_fast_finwait2_recycle; void tcp_timer_init(void); void tcp_timer_2msl(void *xtp); +void tcp_timer_discard(void *); struct tcptw * tcp_tw_2msl_scan(int reuse); /* XXX temporary? */ void tcp_timer_keep(void *xtp); void tcp_timer_persist(void *xtp); void tcp_timer_rexmt(void *xtp); void tcp_timer_delack(void *xtp); -void tcp_timer_2msl_discard(void *xtp); -void tcp_timer_keep_discard(void *xtp); -void tcp_timer_persist_discard(void *xtp); -void tcp_timer_rexmt_discard(void *xtp); -void tcp_timer_delack_discard(void *xtp); void tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer, struct xtcp_timer *xtimer); Modified: head/sys/netinet/tcp_var.h ============================================================================== --- head/sys/netinet/tcp_var.h Thu Apr 28 13:00:40 2016 (r298742) +++ head/sys/netinet/tcp_var.h Thu Apr 28 13:27:12 2016 (r298743) @@ -106,6 +106,17 @@ struct inpcb; struct sockopt; struct socket; +/* + * If defining the optional tcp_timers, in the + * tfb_tcp_timer_stop call you must use the + * callout_async_drain() function with the + * tcp_timer_discard callback. You should check + * the return of callout_async_drain() and if 0 + * increment tt_draincnt. Since the timer sub-system + * does not know your callbacks you must provide a + * stop_all function that loops through and calls + * tcp_timer_stop() with each of your defined timers. + */ struct tcp_function_block { char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX]; int (*tfb_tcp_output)(struct tcpcb *); @@ -120,7 +131,6 @@ struct tcp_function_block { void (*tfb_tcp_fb_fini)(struct tcpcb *); /* Optional timers, must define all if you define one */ int (*tfb_tcp_timer_stop_all)(struct tcpcb *); - int (*tfb_tcp_timers_left)(struct tcpcb *); void (*tfb_tcp_timer_activate)(struct tcpcb *, uint32_t, u_int); int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t);