svn commit: r195239 - projects/tcp_cc_8.x/sys/netinet

Lawrence Stewart lstewart at FreeBSD.org
Wed Jul 1 13:30:02 UTC 2009


Author: lstewart
Date: Wed Jul  1 13:30:01 2009
New Revision: 195239
URL: http://svn.freebsd.org/changeset/base/195239

Log:
  Create a set of CC related hook function wrappers around the algorithm specific
  hook function calls. These wrappers provide a place to do various asserts and
  place code that is algorithm agnostic. There is scope to move more code into
  some of these wrappers than has been done so far. It may also be beneficial to
  optimise for the case where the system default algorithm is in use for the
  connection and there are no other algorithms available e.g. don't indirect
  through the tcpcb and call the default algorithm's function directly. Not sure
  what savings could be made if any, but probably worth exploring.

Modified:
  projects/tcp_cc_8.x/sys/netinet/cc.c
  projects/tcp_cc_8.x/sys/netinet/tcp_input.c
  projects/tcp_cc_8.x/sys/netinet/tcp_output.c
  projects/tcp_cc_8.x/sys/netinet/tcp_timer.c

Modified: projects/tcp_cc_8.x/sys/netinet/cc.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc.c	Wed Jul  1 13:22:08 2009	(r195238)
+++ projects/tcp_cc_8.x/sys/netinet/cc.c	Wed Jul  1 13:30:01 2009	(r195239)
@@ -204,6 +204,12 @@ cc_deregister_algo(struct cc_algo *remov
 		 * Check all active control blocks and change any that are
 		 * using this algorithm back to newreno. If the algorithm that
 		 * was in use requires cleanup code to be run, call it.
+		 *
+		 * New connections already part way through being initialised
+		 * with the CC algo we're removing will not race with this code
+		 * because the INP_INFO_WLOCK is held during initialisation.
+		 * We therefore don't enter the loop below until the connection
+		 * list has stabilised.
 		 */
 		INP_INFO_RLOCK(&V_tcbinfo);
 		LIST_FOREACH(inp, &V_tcb, inp_list) {

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_input.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_input.c	Wed Jul  1 13:22:08 2009	(r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_input.c	Wed Jul  1 13:30:01 2009	(r195239)
@@ -214,6 +214,59 @@ static void	 tcp_pulloutofband(struct so
 		     struct tcphdr *, struct mbuf *, int);
 static void	 tcp_xmit_timer(struct tcpcb *, int);
 static void	 tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
+static void inline	cc_ack_received(struct tcpcb *tp, struct tcphdr *th);
+static void inline	cc_cwnd_init(struct tcpcb *tp);
+static void inline	cc_pre_fr(struct tcpcb *tp, struct tcphdr *th);
+static void inline	cc_post_fr(struct tcpcb *tp, struct tcphdr *th);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_ack_received(struct tcpcb *tp, struct tcphdr *th)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	if (!IN_FASTRECOVERY(tp) && CC_ALGO(tp)->ack_received != NULL)
+		CC_ALGO(tp)->ack_received(tp, th);
+}
+
+static void inline
+cc_cwnd_init(struct tcpcb *tp)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	/*
+	 * XXXLS: Should rename this hook and do
+	 * ssthresh init in there as well
+	 */
+
+	if (CC_ALGO(tp)->cwnd_init != NULL)
+		CC_ALGO(tp)->cwnd_init(tp);
+}
+
+static void inline
+cc_pre_fr(struct tcpcb *tp, struct tcphdr *th)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	if (CC_ALGO(tp)->pre_fr != NULL)
+		CC_ALGO(tp)->pre_fr(tp, th);
+
+	ENTER_FASTRECOVERY(tp);
+	tp->snd_recover = tp->snd_max;
+	if (tp->t_flags & TF_ECN_PERMIT)
+		tp->t_flags |= TF_ECN_SND_CWR;
+}
+
+static void inline
+cc_post_fr(struct tcpcb *tp, struct tcphdr *th)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	if (CC_ALGO(tp)->post_fr != NULL)
+		CC_ALGO(tp)->post_fr(tp, th);
+}
 
 /* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */
 #ifdef INET6
@@ -1160,17 +1213,7 @@ tcp_do_segment(struct mbuf *m, struct tc
 		if ((thflags & TH_ECE) &&
 		    SEQ_LEQ(th->th_ack, tp->snd_recover)) {
 			TCPSTAT_INC(tcps_ecn_rcwnd);
-			/*
-			 * If the current CC algo has
-			 * defined a hook for tasks to run
-			 * before entering FR, call it.
-			 */
-			if (CC_ALGO(tp)->pre_fr != NULL)
-				CC_ALGO(tp)->pre_fr(tp, th);
-			ENTER_FASTRECOVERY(tp);
-			tp->snd_recover = tp->snd_max;
-			if (tp->t_flags & TF_ECN_PERMIT)
-				tp->t_flags |= TF_ECN_SND_CWR;
+			cc_pre_fr(tp, th);
 		}
 	}
 
@@ -2105,17 +2148,7 @@ tcp_do_segment(struct mbuf *m, struct tc
 						}
 					}
 
-					/*
-					 * If the current CC algo has
-					 * defined a hook for tasks to run
-					 * before entering FR, call it.
-					 */
-					if (CC_ALGO(tp)->pre_fr != NULL)
-						CC_ALGO(tp)->pre_fr(tp, th);
-					ENTER_FASTRECOVERY(tp);
-					tp->snd_recover = tp->snd_max;
-					if (tp->t_flags & TF_ECN_PERMIT)
-						tp->t_flags |= TF_ECN_SND_CWR;
+					cc_pre_fr(tp, th);
 					tcp_timer_activate(tp, TT_REXMT, 0);
 					tp->t_rtttime = 0;
 					if (tp->t_flags & TF_SACK_PERMIT) {
@@ -2186,10 +2219,8 @@ tcp_do_segment(struct mbuf *m, struct tc
 					tcp_sack_partialack(tp, th);
 				else
 					tcp_newreno_partial_ack(tp, th);
-			} else {
-				if (CC_ALGO(tp)->post_fr != NULL)
-					CC_ALGO(tp)->post_fr(tp, th);
-			}
+			} else
+				cc_post_fr(tp, th);
 		}
 		tp->t_dupacks = 0;
 		/*
@@ -2292,10 +2323,8 @@ process_ACK:
 		 * The specifics of how this is achieved are up to the
 		 * congestion control algorithm in use for this connection.
 		 */
-		if (!IN_FASTRECOVERY(tp)) {
-			if (CC_ALGO(tp)->ack_received != NULL)
-				CC_ALGO(tp)->ack_received(tp, th);
-		}
+		cc_ack_received(tp, th);
+
 		SOCKBUF_LOCK(&so->so_snd);
 		if (acked > so->so_snd.sb_cc) {
 			tp->snd_wnd -= so->so_snd.sb_cc;
@@ -3274,9 +3303,7 @@ tcp_mss(struct tcpcb *tp, int offer)
 	if (metrics.rmx_bandwidth)
 		tp->snd_bandwidth = metrics.rmx_bandwidth;
 
-	/* Set the initial cwnd value. */
-	if (CC_ALGO(tp)->cwnd_init != NULL)
-		CC_ALGO(tp)->cwnd_init(tp);
+	cc_cwnd_init(tp);
 
 	/* Check the interface for TSO capabilities. */
 	if (mtuflags & CSUM_TSO)

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_output.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_output.c	Wed Jul  1 13:22:08 2009	(r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_output.c	Wed Jul  1 13:30:01 2009	(r195239)
@@ -125,6 +125,19 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_inet
 	CTLFLAG_RW, tcp_autosndbuf_max, 0,
 	"Max size of automatic send buffer");
 
+static void inline	cc_after_idle(struct tcpcb *tp);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_after_idle(struct tcpcb *tp)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	if (CC_ALGO(tp)->after_idle != NULL)
+		CC_ALGO(tp)->after_idle(tp);
+}
 
 /*
  * Tcp output routine: figure out what should be sent and send it.
@@ -169,11 +182,8 @@ tcp_output(struct tcpcb *tp)
 	 * to send, then transmit; otherwise, investigate further.
 	 */
 	idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
-	if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur) {
-		/* reset cwnd after a period of idleness */
-		if (CC_ALGO(tp)->after_idle != NULL)
-			CC_ALGO(tp)->after_idle(tp);
-	}
+	if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur)
+		cc_after_idle(tp);
 	tp->t_flags &= ~TF_LASTIDLE;
 	if (idle) {
 		if (tp->t_flags & TF_MORETOCOME) {

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_timer.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_timer.c	Wed Jul  1 13:22:08 2009	(r195238)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_timer.c	Wed Jul  1 13:30:01 2009	(r195239)
@@ -118,6 +118,24 @@ int	tcp_maxpersistidle;
 	/* max idle time in persist */
 int	tcp_maxidle;
 
+static void inline	cc_after_timeout(struct tcpcb *tp);
+
+/*
+ * CC wrapper hook functions
+ */
+static void inline
+cc_after_timeout(struct tcpcb *tp)
+{
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	if (CC_ALGO(tp)->after_timeout != NULL)
+		CC_ALGO(tp)->after_timeout(tp);
+
+	tp->t_dupacks = 0;
+	EXIT_FASTRECOVERY(tp);
+	tp->t_bytes_acked = 0;
+}
+
 /*
  * Tcp protocol timeout routine called every 500 ms.
  * Updates timestamps used for TCP
@@ -555,12 +573,8 @@ tcp_timer_rexmt(void * xtp)
 	 */
 	tp->t_rtttime = 0;
 
-	if (CC_ALGO(tp)->after_timeout != NULL)
-		CC_ALGO(tp)->after_timeout(tp);
+	cc_after_timeout(tp);
 
-	tp->t_dupacks = 0;
-	EXIT_FASTRECOVERY(tp);
-	tp->t_bytes_acked = 0;
 	(void) tcp_output(tp);
 
 out:


More information about the svn-src-projects mailing list