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