Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Nov 2010 08:30:40 +0000 (UTC)
From:      Lawrence Stewart <lstewart@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r215392 - in head/sys/netinet: . cc
Message-ID:  <201011160830.oAG8Ue0I045747@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: lstewart
Date: Tue Nov 16 08:30:39 2010
New Revision: 215392
URL: http://svn.freebsd.org/changeset/base/215392

Log:
  Move protocol specific implementation detail out of the core CC framework.
  
  Sponsored by:	FreeBSD Foundation
  Tested by:	Mikolaj Golub <to.my.trociny at gmail com>
  MFC after:	11 weeks
  X-MFC with:	r215166

Modified:
  head/sys/netinet/cc/cc.c
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/tcp_var.h

Modified: head/sys/netinet/cc/cc.c
==============================================================================
--- head/sys/netinet/cc/cc.c	Tue Nov 16 07:57:56 2010	(r215391)
+++ head/sys/netinet/cc/cc.c	Tue Nov 16 08:30:39 2010	(r215392)
@@ -190,10 +190,7 @@ int
 cc_deregister_algo(struct cc_algo *remove_cc)
 {
 	struct cc_algo *funcs, *tmpfuncs;
-	struct tcpcb *tp;
-	struct inpcb *inp;
 	int err;
-	VNET_ITERATOR_DECL(vnet_iter);
 
 	err = ENOENT;
 
@@ -220,53 +217,14 @@ cc_deregister_algo(struct cc_algo *remov
 	}
 	CC_LIST_WUNLOCK();
 	
-	if (!err) {
+	if (!err)
 		/*
-		 * Check all active control blocks across all network stacks 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.
+		 * XXXLAS:
+		 * - We may need to handle non-zero return values in future.
+		 * - If we add CC framework support for protocols other than
+		 *   TCP, we may want a more generic way to handle this step.
 		 */
-		VNET_LIST_RLOCK();
-		VNET_FOREACH(vnet_iter) {
-			CURVNET_SET(vnet_iter);
-			INP_INFO_RLOCK(&V_tcbinfo);
-			LIST_FOREACH(inp, &V_tcb, inp_list) {
-				INP_WLOCK(inp);
-				/* Important to skip tcptw structs. */
-				if (!(inp->inp_flags & INP_TIMEWAIT) &&
-				    (tp = intotcpcb(inp)) != NULL) {
-					/*
-					 * By holding INP_WLOCK here, we are
-					 * assured that the connection is not
-					 * currently executing inside the CC
-					 * module's functions i.e. it is safe
-					 * to make the switch back to newreno.
-					 */
-					if (CC_ALGO(tp) == remove_cc) {
-						tmpfuncs = CC_ALGO(tp);
-						/*
-						 * Newreno does not
-						 * require any init.
-						 */
-						CC_ALGO(tp) = &newreno_cc_algo;
-						if (tmpfuncs->cb_destroy != NULL)
-							tmpfuncs->cb_destroy(tp->ccv);
-					}
-				}
-				INP_WUNLOCK(inp);
-			}
-			INP_INFO_RUNLOCK(&V_tcbinfo);
-			CURVNET_RESTORE();
-		}
-		VNET_LIST_RUNLOCK();
-	}
+		tcp_ccalgounload(remove_cc);
 
 	return (err);
 }

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c	Tue Nov 16 07:57:56 2010	(r215391)
+++ head/sys/netinet/tcp_subr.c	Tue Nov 16 08:30:39 2010	(r215392)
@@ -708,6 +708,69 @@ tcp_newtcpcb(struct inpcb *inp)
 }
 
 /*
+ * Switch the congestion control algorithm back to NewReno for any active
+ * control blocks using an algorithm which is about to go away.
+ * This ensures the CC framework can allow the unload to proceed without leaving
+ * any dangling pointers which would trigger a panic.
+ * Returning non-zero would inform the CC framework that something went wrong
+ * and it would be unsafe to allow the unload to proceed. However, there is no
+ * way for this to occur with this implementation so we always return zero.
+ */
+int
+tcp_ccalgounload(struct cc_algo *unload_algo)
+{
+	struct cc_algo *tmpalgo;
+	struct inpcb *inp;
+	struct tcpcb *tp;
+	VNET_ITERATOR_DECL(vnet_iter);
+
+	/*
+	 * Check all active control blocks across all network stacks and change
+	 * any that are using "unload_algo" back to NewReno. If "unload_algo"
+	 * requires cleanup code to be run, call it.
+	 */
+	VNET_LIST_RLOCK();
+	VNET_FOREACH(vnet_iter) {
+		CURVNET_SET(vnet_iter);
+		INP_INFO_RLOCK(&V_tcbinfo);
+		/*
+		 * 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.
+		 */
+		LIST_FOREACH(inp, &V_tcb, inp_list) {
+			INP_WLOCK(inp);
+			/* Important to skip tcptw structs. */
+			if (!(inp->inp_flags & INP_TIMEWAIT) &&
+			    (tp = intotcpcb(inp)) != NULL) {
+				/*
+				 * By holding INP_WLOCK here, we are assured
+				 * that the connection is not currently
+				 * executing inside the CC module's functions
+				 * i.e. it is safe to make the switch back to
+				 * NewReno.
+				 */
+				if (CC_ALGO(tp) == unload_algo) {
+					tmpalgo = CC_ALGO(tp);
+					/* NewReno does not require any init. */
+					CC_ALGO(tp) = &newreno_cc_algo;
+					if (tmpalgo->cb_destroy != NULL)
+						tmpalgo->cb_destroy(tp->ccv);
+				}
+			}
+			INP_WUNLOCK(inp);
+		}
+		INP_INFO_RUNLOCK(&V_tcbinfo);
+		CURVNET_RESTORE();
+	}
+	VNET_LIST_RUNLOCK();
+
+	return (0);
+}
+
+/*
  * Drop a TCP connection, reporting
  * the specified error.  If connection is synchronized,
  * then send a RST to peer.

Modified: head/sys/netinet/tcp_var.h
==============================================================================
--- head/sys/netinet/tcp_var.h	Tue Nov 16 07:57:56 2010	(r215391)
+++ head/sys/netinet/tcp_var.h	Tue Nov 16 08:30:39 2010	(r215392)
@@ -605,6 +605,7 @@ VNET_DECLARE(int, tcp_ecn_maxretries);
 #define	V_tcp_ecn_maxretries	VNET(tcp_ecn_maxretries)
 
 int	 tcp_addoptions(struct tcpopt *, u_char *);
+int	 tcp_ccalgounload(struct cc_algo *unload_algo);
 struct tcpcb *
 	 tcp_close(struct tcpcb *);
 void	 tcp_discardcb(struct tcpcb *);



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