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

Lawrence Stewart lstewart at FreeBSD.org
Thu Jun 25 14:41:43 UTC 2009


Author: lstewart
Date: Thu Jun 25 14:41:42 2009
New Revision: 194961
URL: http://svn.freebsd.org/changeset/base/194961

Log:
  Major rototill in preparation for merging to 8. This is a checkpoint commit that
  has only been compile tested on AMD64 so far. Summary of changes as follows:
  
  - Split cc.h into cc.h and cc_module.h, to separate out KPI module plumbing
    (cc_module.h) from generic CC related code (cc.h). Only CC modules
    should include cc_module.h.
  
  - Implement new DECLARE_CC_MODULE() macro, modelled on similar MAC/VFS code,
    to hide most of the machinery of creating a CC kernel module. A CC module
    author can now simply put "DECLARE_CC_MODULE(<name>, &<name>_cc_algo);"
    (replacing <name> as appropriate) at the bottom of their algo's .c file and
    have the framework handle most of the heavy lifting.
  
  - Add new mod_init/mod_destroy function ptrs to struct cc_algo. This provides
    standardised hook functions for the framework to init/cleanup global CC module
    state on kldload/kldunload.
  
  - Rename init/deinit function ptrs to conn_init/conn_destroy for consistency
    with the above change and to distinguish per connection init/cleanup from
    global module init/cleanup.
  
  - Remove the global "cc_algorithm" string which was used to hold the name of the
    systemm default CC algorithm. Since switching to having the default algorithm
    always be at the head of the cc_list TAILQ, use of this string is redundant.
  
  - Catch up with vimage changes that require inclusion of <sys/vimage.h> in
    addition to <netinet/vinet.h>.
  
  - Simplify logic in the sysctl handlers.
  
  - Lots of minor cleanup work.
  
  - Update existing CC modules as required to work with new world order.

Added:
  projects/tcp_cc_8.x/sys/netinet/cc_module.h
Modified:
  projects/tcp_cc_8.x/sys/netinet/cc.c
  projects/tcp_cc_8.x/sys/netinet/cc.h
  projects/tcp_cc_8.x/sys/netinet/cc_cubic.c
  projects/tcp_cc_8.x/sys/netinet/cc_htcp.c
  projects/tcp_cc_8.x/sys/netinet/cc_newreno.c
  projects/tcp_cc_8.x/sys/netinet/tcp_input.c
  projects/tcp_cc_8.x/sys/netinet/tcp_subr.c
  projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c

Modified: projects/tcp_cc_8.x/sys/netinet/cc.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/cc.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2007-2009
  *	Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2009 Lawrence Stewart <lstewart at freebsd.org>
  * All rights reserved.
  *
  * This software was developed at the Centre for Advanced Internet
@@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/libkern.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
+#include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/queue.h>
 #include <sys/rwlock.h>
@@ -45,62 +47,82 @@ __FBSDID("$FreeBSD$");
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+#include <sys/vimage.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
 
 #include <netinet/cc.h>
+#include <netinet/cc_module.h>
 #include <netinet/vinet.h>
 
-/* list of available cc algorithms on the current system */
+/*
+ * List of available cc algorithms on the current system. First element
+ * is used as the system default CC algorithm.
+ */
 struct cc_head cc_list = STAILQ_HEAD_INITIALIZER(cc_list); 
 
+/* Protects the cc_list TAILQ */
 struct rwlock cc_list_lock;
 
-/* the system wide default cc algorithm */
-char cc_algorithm[TCP_CA_NAME_MAX];
+/*
+ * Set the default CC algorithm to new_default. The default is identified
+ * by being the first element in the cc_list TAILQ.
+ */
+static void
+cc_set_default(struct cc_algo *new_default)
+{
+	CC_LIST_WLOCK_ASSERT();
+
+	/*
+	 * Make the requested system default CC
+	 * algorithm the first element in the list
+	 * if it isn't already
+	 */
+	if (new_default != CC_DEFAULT()) {
+		STAILQ_REMOVE(&cc_list, new_default, cc_algo, entries);
+		STAILQ_INSERT_HEAD(&cc_list, new_default, entries);
+	}
+}
 
 /*
- * sysctl handler that allows the default cc algorithm for the system to be
- * viewed and changed
+ * Sysctl handler to show and change the default CC algorithm.
  */
 static int
-cc_default_algorithm(SYSCTL_HANDLER_ARGS)
+cc_default_algo(SYSCTL_HANDLER_ARGS)
 {
 	struct cc_algo *funcs;
+	int error = 0, found = 0;
 
-	if (req->newptr == NULL)
-		goto skip;
-
-	CC_LIST_RLOCK();
-	STAILQ_FOREACH(funcs, &cc_list, entries) {
-		if (strncmp((char *)req->newptr, funcs->name, TCP_CA_NAME_MAX) == 0)
-			goto reorder;
-	}
-	CC_LIST_RUNLOCK();
+	if (req->newptr == NULL) {
+		/* Just print the current default. */
+		char default_cc[TCP_CA_NAME_MAX];
+		CC_LIST_RLOCK();
+		strlcpy(default_cc, CC_DEFAULT()->name, TCP_CA_NAME_MAX);
+		CC_LIST_RUNLOCK();
+		error = sysctl_handle_string(oidp, default_cc, 1, req);
+	} else {
+		/* Find algo with specified name and set it to default */
+		CC_LIST_WLOCK();
+		STAILQ_FOREACH(funcs, &cc_list, entries) {
+			if (strncmp((char *)req->newptr, funcs->name, TCP_CA_NAME_MAX) == 0) {
+				found = 1;
+				cc_set_default(funcs);
+			}
+		}
+		CC_LIST_WUNLOCK();
 
-	return 1;
+		if (!found)
+			return (ESRCH);
 
-reorder:
-	/*
-	 * Make the selected system default cc algorithm
-	 * the first element in the list if it isn't already
-	 */
-	CC_LIST_RUNLOCK();
-	CC_LIST_WLOCK();
-	if (funcs != STAILQ_FIRST(&cc_list)) {
-		STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries);
-		STAILQ_INSERT_HEAD(&cc_list, funcs, entries);
+		error = sysctl_handle_string(oidp, arg1, arg2, req);
 	}
-	CC_LIST_WUNLOCK();
 
-skip:
-	return sysctl_handle_string(oidp, arg1, arg2, req);
+	return (error);
 }
 
 /*
- * sysctl handler that displays the available cc algorithms as a read
- * only value
+ * Sysctl handler to display the list of available CC algorithms.
  */
 static int
 cc_list_available(SYSCTL_HANDLER_ARGS)
@@ -127,83 +149,81 @@ cc_list_available(SYSCTL_HANDLER_ARGS)
 	}
 
 	sbuf_delete(s);
-	return error;
+	return (error);
 }
 
 /*
- * Initialise cc on system boot
+ * Initialise CC subsystem on system boot.
  */
 void 
 cc_init()
 {
-	/* initialise the lock that will protect read/write access to our linked list */
 	CC_LIST_LOCK_INIT();
-
-	/* initilize list of cc algorithms */
 	STAILQ_INIT(&cc_list);
-
-	/* add newreno to the list of available algorithms */
-	cc_register_algorithm(&newreno_cc_algo);
-
-	/* set newreno to the system default */
-	strlcpy(cc_algorithm, newreno_cc_algo.name, TCP_CA_NAME_MAX);
+	/* Newreno must always be available as an algorithm. */
+	cc_register_algo(&newreno_cc_algo);
 }
 
 /*
- * Returns 1 on success, 0 on failure
+ * Returns non-zero on success, 0 on failure.
  */
 int
-cc_deregister_algorithm(struct cc_algo *remove_cc)
+cc_deregister_algo(struct cc_algo *remove_cc)
 {
 	struct cc_algo *funcs, *tmpfuncs;
-	register struct tcpcb *tp = NULL;
-	register struct inpcb *inp = NULL;
-	int success = 0;
+	struct tcpcb *tp = NULL;
+	struct inpcb *inp = NULL;
+	int error = EPERM;
+
+	/* Never allow newreno to be deregistered. */
+	if (&newreno_cc_algo == remove_cc)
+		return error;
 
-	/* remove the algorithm from the list available to the system */
-	CC_LIST_RLOCK();
+	/* Remove algo from cc_list so that new connections can't use it. */
+	CC_LIST_WLOCK();
 	STAILQ_FOREACH_SAFE(funcs, &cc_list, entries, tmpfuncs) {
 		if (funcs == remove_cc) {
-			if (CC_LIST_TRY_WLOCK()) {
-				/* if this algorithm is the system default, reset the default to newreno */
-				if (strncmp(cc_algorithm, remove_cc->name, TCP_CA_NAME_MAX) == 0)
-					snprintf(cc_algorithm, TCP_CA_NAME_MAX, "%s", newreno_cc_algo.name);
-
-				STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries);
-				success = 1;
-				CC_LIST_W2RLOCK();
-			}
+			/*
+			 * If we're removing the current system default,
+			 * reset the default to newreno.
+			 */
+			if (strncmp(CC_DEFAULT()->name,
+			    remove_cc->name,
+			    TCP_CA_NAME_MAX) == 0)
+				cc_set_default(&newreno_cc_algo);
+
+			STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries);
+			error = 0;
 			break;
 		}
 	}
-	CC_LIST_RUNLOCK();
+	CC_LIST_WUNLOCK();
 
-	if (success) {
+	if (!error) {
 		/*
-		 * check all active control blocks and change any that are using this
-		 * algorithm back to newreno. If the algorithm that was in use requires
-		 * deinit code to be run, call it
+		 * 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.
 		 */
 		INP_INFO_RLOCK(&V_tcbinfo);
 		LIST_FOREACH(inp, &V_tcb, inp_list) {
-			/* skip tcptw structs */
-			if (inp->inp_flags & INP_TIMEWAIT)
-				continue;
 			INP_WLOCK(inp);
-			if ((tp = intotcpcb(inp)) != NULL) {
-				if (strncmp(CC_ALGO(tp)->name, remove_cc->name, TCP_CA_NAME_MAX) == 0 ) {
+			/* 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;
-					/*
-					 * XXX: We should stall here until
-					 * we're sure the tcb has stopped
-					 * using the deregistered algo's functions...
-					 * Not sure how to do that yet!
-					 */
-					if(CC_ALGO(tp)->init != NULL)
-						CC_ALGO(tp)->init(tp);
-					if (tmpfuncs->deinit != NULL)
-						tmpfuncs->deinit(tp);
+					if (tmpfuncs->conn_destroy != NULL)
+						tmpfuncs->conn_destroy(tp);
 				}
 			}
 			INP_WUNLOCK(inp);
@@ -211,26 +231,79 @@ cc_deregister_algorithm(struct cc_algo *
 		INP_INFO_RUNLOCK(&V_tcbinfo);
 	}
 
-	return success;
+	return (error);
 }
 
+/*
+ * Returns 0 on success, non-zero on failure.
+ */
 int
-cc_register_algorithm(struct cc_algo *add_cc)
+cc_register_algo(struct cc_algo *add_cc)
 {
+	struct cc_algo *funcs;
+	int error = 0;
+
+	/*
+	 * Iterate over list of registered CC algorithms and make sure
+	 * we're not trying to add a duplicate.
+	 */
 	CC_LIST_WLOCK();
-	STAILQ_INSERT_TAIL(&cc_list, add_cc, entries);
+	STAILQ_FOREACH(funcs, &cc_list, entries) {
+		if (funcs == add_cc ||
+		    strncmp(funcs->name, add_cc->name, TCP_CA_NAME_MAX) == 0)
+			error = EEXIST;
+	}
+
+	if (!error)
+		STAILQ_INSERT_TAIL(&cc_list, add_cc, entries);
+
 	CC_LIST_WUNLOCK();
-	return 1;
+
+	return (error);
+}
+
+/*
+ * Handles kld related events. Returns 0 on success, non-zero on failure.
+ */
+int
+cc_modevent(module_t mod, int event_type, void *data)
+{
+	int error = 0;
+	struct cc_algo *algo = (struct cc_algo *)data;
+
+	switch(event_type) {
+		case MOD_LOAD:
+			if (algo->mod_init != NULL)
+				error = algo->mod_init();
+			if (!error)
+				error = cc_register_algo(algo);
+			break;
+
+		case MOD_QUIESCE:
+			error = cc_deregister_algo(algo);
+			if (!error && algo->mod_destroy != NULL)
+				algo->mod_destroy();
+			break;
+
+		case MOD_SHUTDOWN:
+		case MOD_UNLOAD:
+			break;
+
+		default:
+			return EINVAL;
+			break;
+	}
+
+	return (error);
 }
 
 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW, NULL,
 	"congestion control related settings");
 
 SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLTYPE_STRING|CTLFLAG_RW,
-	&cc_algorithm, sizeof(cc_algorithm), cc_default_algorithm, "A",
+	NULL, 0, cc_default_algo, "A",
 	"default congestion control algorithm");
 
 SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, available, CTLTYPE_STRING|CTLFLAG_RD,
 	NULL, 0, cc_list_available, "A",
 	"list available congestion control algorithms");
-

Modified: projects/tcp_cc_8.x/sys/netinet/cc.h
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc.h	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/cc.h	Thu Jun 25 14:41:42 2009	(r194961)
@@ -1,5 +1,7 @@
 /*-
- * Copyright (c) 2008 Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2008-2009
+ * 	Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2009 Lawrence Stewart <lstewart at freebsd.org>
  * All rights reserved.
  *
  * This software was developed at the Centre for Advanced Internet
@@ -34,77 +36,78 @@
 #ifndef _NETINET_CC_H_
 #define _NETINET_CC_H_
 
-/* Needed for TCP_CA_NAME_MAX define which lives in tcp.h for compat reasons */
+/* Needed for TCP_CA_NAME_MAX define which lives in tcp.h for compat reasons. */
 #include <netinet/tcp.h>
 
 /*
- * Global CC vars
+ * Global CC vars.
  */
 extern	STAILQ_HEAD(cc_head, cc_algo) cc_list;
-extern	char cc_algorithm[];
 extern	const int tcprexmtthresh;
 extern	struct cc_algo newreno_cc_algo;
 
 /*
- * Define the new net.inet.tcp.cc sysctl tree
+ * Define the new net.inet.tcp.cc sysctl tree.
  */
 SYSCTL_DECL(_net_inet_tcp_cc);
 
 /*
- * CC housekeeping functions
+ * CC housekeeping functions.
  */
 void	cc_init(void);
-int	cc_register_algorithm(struct cc_algo *add_cc);
-int	cc_deregister_algorithm(struct cc_algo *remove_cc);
+int	cc_register_algo(struct cc_algo *add_cc);
+int	cc_deregister_algo(struct cc_algo *remove_cc);
 
 /*
- * NewReno CC functions
- */
-int	newreno_init(struct tcpcb *tp);
-void	newreno_cwnd_init(struct tcpcb *tp);
-void	newreno_ack_received(struct tcpcb *tp, struct tcphdr *th);
-void	newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th);
-void	newreno_post_fr(struct tcpcb *tp, struct tcphdr *th);
-void	newreno_after_idle(struct tcpcb *tp);
-void	newreno_after_timeout(struct tcpcb *tp);
-void	newreno_ssthresh_update(struct tcpcb *tp);
-
-/*
- * Structure to hold function pointers to the functions responsible
- * for congestion control. Based on similar structure in the SCTP stack
+ * Structure to hold data and function pointers that together represent
+ * a congestion control algorithm.
+ * Based on similar structure in the SCTP stack.
  */
 struct cc_algo {
 	char name[TCP_CA_NAME_MAX];
 
-	/* init the congestion algorithm for the specified control block */
-	int (*init) (struct tcpcb *tp);
+	/* Init global module state on kldload. */
+	int (*mod_init) (void);
+
+	/* Cleanup global module state on kldunload. */
+	int (*mod_destroy) (void);
 
-	/* deinit the congestion algorithm for the specified control block */
-	void (*deinit) (struct tcpcb *tp);
+	/* Init CC state for a new connection. */
+	int (*conn_init) (struct tcpcb *tp);
 
-	/* initilise cwnd at the start of a connection */
+	/* Cleanup CC state for a terminating connection. */
+	void (*conn_destroy) (struct tcpcb *tp);
+
+	/* Init cwnd for a new connection. */
+	/* XXXLS: could this be folded into conn_init? */
 	void (*cwnd_init) (struct tcpcb *tp);
 
-	/* called on the receipt of a valid ack */
+	/* Called on receipt of a regular, valid ack. */
 	void (*ack_received) (struct tcpcb *tp, struct tcphdr *th);
 
-	/* called before entering FR */
+	/* Called before entering FR. */
 	void (*pre_fr) (struct tcpcb *tp, struct tcphdr *th);
 
-	/*  after exiting FR */
+	/* Called after exiting FR. */
 	void (*post_fr) (struct tcpcb *tp, struct tcphdr *th);
 
-	/* perform tasks when data transfer resumes after an idle period */
+	/* Called when data transfer resumes after an idle period. */
 	void (*after_idle) (struct tcpcb *tp);
 
-	/* perform tasks when the connection's retransmit timer expires */
+	/* Called each time the connection's retransmit timer fires. */
 	void (*after_timeout) (struct tcpcb *tp);
 
 	STAILQ_ENTRY(cc_algo) entries;
 };
 
-#define CC_ALGO(tp) ((tp)->cc_algo)
-#define CC_DATA(tp) ((tp)->cc_data)
+/* Macro to obtain the CC algo's struct ptr. */
+#define CC_ALGO(tp)	((tp)->cc_algo)
+
+/* Macro to obtain the CC algo's data ptr. */
+#define CC_DATA(tp)	((tp)->cc_data)
+
+/* Macro to obtain the system default CC algo's struct ptr. */
+#define CC_DEFAULT()	STAILQ_FIRST(&cc_list)
 
 extern struct rwlock cc_list_lock;
 #define CC_LIST_LOCK_INIT() rw_init(&cc_list_lock, "cc_list")
@@ -113,7 +116,6 @@ extern struct rwlock cc_list_lock;
 #define CC_LIST_RUNLOCK() rw_runlock(&cc_list_lock)
 #define CC_LIST_WLOCK() rw_wlock(&cc_list_lock)
 #define CC_LIST_WUNLOCK() rw_wunlock(&cc_list_lock)
-#define CC_LIST_TRY_WLOCK() rw_try_upgrade(&cc_list_lock)
-#define CC_LIST_W2RLOCK() rw_downgrade(&cc_list_lock)
+#define CC_LIST_WLOCK_ASSERT() rw_assert(&cc_list_lock, RA_WLOCKED)
 
 #endif /* _NETINET_CC_H_ */

Modified: projects/tcp_cc_8.x/sys/netinet/cc_cubic.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc_cubic.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/cc_cubic.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -27,7 +27,6 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
 
 /*
@@ -41,6 +40,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/queue.h>
@@ -49,16 +49,21 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 #include <sys/time.h>
+#include <sys/vimage.h>
+
+#include <net/if.h>
 
 #include <netinet/cc.h>
 #include <netinet/cc_cubic.h>
+#include <netinet/cc_module.h>
 #include <netinet/tcp_seq.h>
 #include <netinet/tcp_timer.h>
 #include <netinet/tcp_var.h>
+#include <netinet/vinet.h>
 
 /* function prototypes */
-int cubic_init(struct tcpcb *tp);
-void cubic_deinit(struct tcpcb *tp);
+int cubic_conn_init(struct tcpcb *tp);
+void cubic_conn_destroy(struct tcpcb *tp);
 void cubic_pre_fr(struct tcpcb *tp, struct tcphdr *th);
 void cubic_post_fr(struct tcpcb *tp, struct tcphdr *th);
 void cubic_ack_received(struct tcpcb *tp, struct tcphdr *th);
@@ -88,8 +93,10 @@ MALLOC_DEFINE(M_CUBIC, "cubic data",
 /* function pointers for various hooks into the TCP stack */
 struct cc_algo cubic_cc_algo = {
 	.name = "cubic",
-	.init = cubic_init,
-	.deinit = cubic_deinit,
+	.mod_init = NULL,
+	.mod_destroy = NULL,
+	.conn_init = cubic_conn_init,
+	.conn_destroy = cubic_conn_destroy,
 	.cwnd_init = cubic_cwnd_init,
 	.ack_received = cubic_ack_received,
 	.pre_fr = cubic_pre_fr,
@@ -119,7 +126,7 @@ cubic_cwnd_init(struct tcpcb *tp)
  * in the control block
  */
 int
-cubic_init(struct tcpcb *tp)
+cubic_conn_init(struct tcpcb *tp)
 {
 	struct cubic *cubic_data;
 	
@@ -145,7 +152,7 @@ cubic_init(struct tcpcb *tp)
  * TCP control block.
  */
 void
-cubic_deinit(struct tcpcb *tp)
+cubic_conn_destroy(struct tcpcb *tp)
 {
 	if (CC_DATA(tp) != NULL)
 		free(CC_DATA(tp), M_CUBIC);
@@ -353,60 +360,4 @@ cubic_ssthresh_update(struct tcpcb *tp)
 		tp->snd_ssthresh = (tp->snd_cwnd * CUBIC_BETA) >> CUBIC_SHIFT;
 }
 
-/*
- * Init the HTCP module when it is first loaded into the kernel.
- * Calls the kernel function for registering a new congestion control
- * algorithm
- */
-static int
-init_module(void)
-{
-	cc_register_algorithm(&cubic_cc_algo);
-	return 0;
-}
-
-/*
- * Called when the module is unloaded from the kernel.
- */
-static int
-deinit_module(void)
-{
-	cc_deregister_algorithm(&cubic_cc_algo);
-	return 0;
-}
-
-/*
- * Tell the kernel which functions to use to init and de-init the module.
- */
-static int
-cubic_load_handler(module_t mod, int what, void *arg)
-{
-	switch(what) {
-		case MOD_LOAD:
-			return init_module();
-			break;
-	
-		case MOD_QUIESCE:
-		case MOD_SHUTDOWN:
-			return deinit_module();
-			break;
-	
-		case MOD_UNLOAD:
-			return 0;
-			break;
-	
-		default:
-			return EINVAL;
-			break;
-	}
-}
-
-/* a struct that holds basic data on the module */
-static moduledata_t cubic_mod =
-{
-	"cubic",            /* module's name */
-	cubic_load_handler, /* execution entry point for the module */
-	NULL
-};
-
-DECLARE_MODULE(cubic, cubic_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+DECLARE_CC_MODULE(cubic, &cubic_cc_algo);

Modified: projects/tcp_cc_8.x/sys/netinet/cc_htcp.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc_htcp.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/cc_htcp.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2007-2009
  * 	Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2009 Lawrence Stewart <lstewart at freebsd.org>
  * All rights reserved.
  *
  * This software was developed at the Centre for Advanced Internet
@@ -28,7 +29,6 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
  */
 
 /*
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/queue.h>
@@ -52,11 +53,16 @@ __FBSDID("$FreeBSD$");
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
+#include <sys/vimage.h>
+
+#include <net/if.h>
 
 #include <netinet/cc.h>
+#include <netinet/cc_module.h>
 #include <netinet/tcp_seq.h>
 #include <netinet/tcp_timer.h>
 #include <netinet/tcp_var.h>
+#include <netinet/vinet.h>
 
 /* useful defines */
 #define MODNAME "HTCP congestion control"
@@ -125,8 +131,9 @@ __FBSDID("$FreeBSD$");
 )
 
 /* function prototypes */
-int htcp_init(struct tcpcb *tp);
-void htcp_deinit(struct tcpcb *tp);
+int htcp_mod_init(void);
+int htcp_conn_init(struct tcpcb *tp);
+void htcp_conn_destroy(struct tcpcb *tp);
 void htcp_recalc_alpha(struct tcpcb *tp);
 void htcp_recalc_beta(struct tcpcb *tp);
 void htcp_pre_fr(struct tcpcb *tp, struct tcphdr *th);
@@ -162,8 +169,10 @@ MALLOC_DEFINE(M_HTCP, "htcp data", "Per 
 /* function pointers for various hooks into the TCP stack */
 struct cc_algo htcp_cc_algo = {
 	.name = "htcp",
-	.init = htcp_init,
-	.deinit = htcp_deinit,
+	.mod_init = htcp_mod_init,
+	.mod_destroy = NULL,
+	.conn_init = htcp_conn_init,
+	.conn_destroy = htcp_conn_destroy,
 	.cwnd_init = newreno_cwnd_init,
 	.ack_received = htcp_ack_received,
 	.pre_fr = htcp_pre_fr,
@@ -178,7 +187,7 @@ struct cc_algo htcp_cc_algo = {
  * in the control block
  */
 int
-htcp_init(struct tcpcb *tp)
+htcp_conn_init(struct tcpcb *tp)
 {
 	struct htcp *htcp_data;
 	
@@ -209,7 +218,7 @@ htcp_init(struct tcpcb *tp)
  * TCP control block.
  */
 void
-htcp_deinit(struct tcpcb *tp)
+htcp_conn_destroy(struct tcpcb *tp)
 {
 #ifdef HTCP_DEBUG
 	printf("deinitialising tcp connection with htcp congestion control\n");
@@ -533,13 +542,9 @@ skip:
 }
 #endif
 
-/*
- * Init the HTCP module when it is first loaded into the kernel.
- * Calls the kernel function for registering a new congestion control
- * algorithm
- */
-static int
-init_module(void)
+
+int
+htcp_mod_init(void)
 {
 	/*
 	 * the maximum time in ticks after a congestion event before alpha stops
@@ -560,64 +565,10 @@ init_module(void)
 	/* set the default debug interval to 1 second */
 	htcp_debug_ticks = hz;
 #endif
-	
-	/* add htcp to the list of available algorithms */
-	cc_register_algorithm(&htcp_cc_algo);
-
-	uprintf("Loaded: %s v%s\n", MODNAME, MODVERSION);
 
 	return 0;
 }
 
-/*
- * Called when the module is unloaded from the kernel.
- */
-static int
-deinit_module(void)
-{
-	cc_deregister_algorithm(&htcp_cc_algo);
-
-	uprintf("Unloaded: %s v%s\n", MODNAME, MODVERSION);
-
-	return 0;
-}
-
-/*
- * Tell the kernel which functions to use to init and de-init the module.
- */
-static int 
-htcp_load_handler(module_t mod, int what, void *arg)
-{
-	switch(what) {
-		case MOD_LOAD:
-			return init_module();
-			break;
-
-		case MOD_QUIESCE:
-		case MOD_SHUTDOWN:
-			return deinit_module();
-			break;
-
-		case MOD_UNLOAD:
-			return 0;
-			break;
-
-		default:
-			return EINVAL;
-			break;
-	}
-}
-
-/* a struct that holds basic data on the module */
-static moduledata_t htcp_mod =
-{
-	"htcp",            /* module's name */
-	htcp_load_handler, /* execution entry point for the module */
-	NULL
-};
-
-DECLARE_MODULE(htcp, htcp_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
-
 SYSCTL_DECL(_net_inet_tcp_cc_htcp);
 SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, htcp, CTLFLAG_RW, NULL, "H-TCP related settings");
 SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, rtt_scaling, CTLTYPE_UINT|CTLFLAG_RW, &htcp_rtt_scaling, 0, &htcp_rtt_scaling_handler, "IU", "switch H-TCP RTT scaling on/off");
@@ -626,3 +577,5 @@ SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AU
 #ifdef HTCP_DEBUG
 SYSCTL_OID(_net_inet_tcp_cc_htcp, OID_AUTO, debug_ticks, CTLTYPE_UINT|CTLFLAG_RW, &htcp_debug_ticks, 0, &htcp_debug_ticks_handler, "IU", "set the approximate number of ticks between printing debug messages to syslog");
 #endif
+
+DECLARE_CC_MODULE(htcp, &htcp_cc_algo);

Added: projects/tcp_cc_8.x/sys/netinet/cc_module.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/tcp_cc_8.x/sys/netinet/cc_module.h	Thu Jun 25 14:41:42 2009	(r194961)
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2008-2009
+ * 	Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2009 Lawrence Stewart <lstewart at freebsd.org>
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University, by Lawrence Stewart and James Healy,
+ * made possible in part by a grant from the Cisco University Research Program
+ * Fund at Community Foundation Silicon Valley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NETINET_CC_MODULE_H_
+#define _NETINET_CC_MODULE_H_
+
+/*
+ * NewReno CC functions
+ */
+int	newreno_conn_init(struct tcpcb *tp);
+void	newreno_cwnd_init(struct tcpcb *tp);
+void	newreno_ack_received(struct tcpcb *tp, struct tcphdr *th);
+void	newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th);
+void	newreno_post_fr(struct tcpcb *tp, struct tcphdr *th);
+void	newreno_after_idle(struct tcpcb *tp);
+void	newreno_after_timeout(struct tcpcb *tp);
+void	newreno_ssthresh_update(struct tcpcb *tp);
+
+#define	DECLARE_CC_MODULE(ccname, ccalgo) 				\
+	static moduledata_t cc_##ccname = {				\
+		#ccname,						\
+		cc_modevent,						\
+		ccalgo							\
+	};								\
+	DECLARE_MODULE(ccname, cc_##ccname, SI_SUB_PROTO_IFATTACHDOMAIN, \
+	    SI_ORDER_ANY)
+
+int	cc_modevent(module_t mod, int type, void *data);
+
+#endif /* _NETINET_CC_MODULE_H_ */

Modified: projects/tcp_cc_8.x/sys/netinet/cc_newreno.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/cc_newreno.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/cc_newreno.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -3,6 +3,7 @@
  *	The Regents of the University of California.
  * Copyright (c) 2007-2009
  *	Swinburne University of Technology, Melbourne, Australia
+ * Copyright (c) 2009 Lawrence Stewart <lstewart at freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,22 +32,28 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+#include <sys/vimage.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
 
 #include <netinet/cc.h>
+#include <netinet/cc_module.h>
 #include <netinet/tcp_seq.h>
 #include <netinet/vinet.h>
 
 /* newreno cc function pointers */
 struct cc_algo newreno_cc_algo = {
 	.name = "newreno",
-	.init = newreno_init,
-	.deinit = NULL,
+	.mod_init = NULL,
+	.mod_destroy = NULL,
+	.conn_init = newreno_conn_init,
+	.conn_destroy = NULL,
 	.cwnd_init = newreno_cwnd_init,
 	.ack_received = newreno_ack_received,
 	.pre_fr = newreno_pre_fr,
@@ -56,7 +63,7 @@ struct cc_algo newreno_cc_algo = {
 };
 
 int
-newreno_init(struct tcpcb *tp)
+newreno_conn_init(struct tcpcb *tp)
 {
 	return 0;
 }
@@ -255,3 +262,4 @@ newreno_after_timeout(struct tcpcb *tp)
 	tp->snd_cwnd = tp->t_maxseg;
 }
 
+DECLARE_CC_MODULE(newreno, &newreno_cc_algo);

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_input.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_input.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_input.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -3282,7 +3282,7 @@ tcp_mss(struct tcpcb *tp, int offer)
 	if (metrics.rmx_bandwidth)
 		tp->snd_bandwidth = metrics.rmx_bandwidth;
 
-	/* set the initial cwnd value */
+	/* Set the initial cwnd value. */
 	if (CC_ALGO(tp)->cwnd_init != NULL)
 		CC_ALGO(tp)->cwnd_init(tp);
 

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_subr.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_subr.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_subr.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -731,15 +731,14 @@ tcp_newtcpcb(struct inpcb *inp)
 	tp = &tm->tcb;
 
 	/*
-	 * use the current system default cc algorithm, which is always
-	 * the first algorithm in cc_list
+	 * Use the current system default CC algorithm.
 	 */
 	CC_LIST_RLOCK();
-	CC_ALGO(tp) = STAILQ_FIRST(&cc_list);
+	CC_ALGO(tp) = CC_DEFAULT();
 	CC_LIST_RUNLOCK();
 
-	/* if the cc module fails to init, stop building the control block */
-	if (CC_ALGO(tp)->init(tp) > 0) {
+	/* If the CC module fails to init, stop building the control block. */
+	if (CC_ALGO(tp)->conn_init(tp) > 0) {
 		uma_zfree(V_tcpcb_zone, tp);
 		return NULL;
 	}
@@ -911,9 +910,9 @@ tcp_discardcb(struct tcpcb *tp)
 	tcp_offload_detach(tp);
 	tcp_free_sackholes(tp);
 
-	/* Allow the cc algorithm in use for this cb to clean up after itself */
-	if (CC_ALGO(tp)->deinit != NULL)
-		CC_ALGO(tp)->deinit(tp);
+	/* Allow the CC algorithm to clean up after itself. */
+	if (CC_ALGO(tp)->conn_destroy != NULL)
+		CC_ALGO(tp)->conn_destroy(tp);
 
 	CC_ALGO(tp) = NULL;
 	inp->inp_ppcb = NULL;

Modified: projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c
==============================================================================
--- projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c	Thu Jun 25 14:15:45 2009	(r194960)
+++ projects/tcp_cc_8.x/sys/netinet/tcp_usrreq.c	Thu Jun 25 14:41:42 2009	(r194961)
@@ -1263,7 +1263,7 @@ tcp_ctloutput(struct socket *so, struct 
 	struct	tcpcb *tp;
 	struct	tcp_info ti;
 	char buf[TCP_CA_NAME_MAX];
-	struct cc_algo *cc_algo;
+	struct cc_algo *algo;
 
 	error = 0;
 	inp = sotoinpcb(so);
@@ -1387,9 +1387,9 @@ tcp_ctloutput(struct socket *so, struct 
 			 */
 			error = EINVAL;
 			CC_LIST_RLOCK();
-			STAILQ_FOREACH(cc_algo, &cc_list, entries) {
+			STAILQ_FOREACH(algo, &cc_list, entries) {
 				if (	strncmp(buf,
-					cc_algo->name,
+					algo->name,
 					TCP_CA_NAME_MAX) == 0) {
 					/*
 					 * we've found the requested algo,
@@ -1401,16 +1401,16 @@ tcp_ctloutput(struct socket *so, struct 
 					 * so it's safe to do these things
 					 * without ordering concerns
 					 */
-					if (CC_ALGO(tp)->deinit != NULL)
-						CC_ALGO(tp)->deinit(tp);
-					CC_ALGO(tp) = cc_algo;
+					if (CC_ALGO(tp)->conn_destroy != NULL)
+						CC_ALGO(tp)->conn_destroy(tp);
+					CC_ALGO(tp) = algo;
 					/*
 					 * if something goes pear shaped
 					 * initialising the new algo,
 					 * fall back to newreno (which
 					 * does not require initialisation)
 					 */
-					if (cc_algo->init(tp) > 0) {
+					if (algo->conn_init(tp) > 0) {
 						CC_ALGO(tp) = &newreno_cc_algo;
 						/*
 						 * the only reason init() should


More information about the svn-src-projects mailing list