Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Apr 2016 13:27:12 +0000 (UTC)
From:      Randall Stewart <rrs@FreeBSD.org>
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
Message-ID:  <201604281327.u3SDRCIa035707@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604281327.u3SDRCIa035707>