Date: Thu, 25 Jun 2009 14:41:43 +0000 (UTC) From: Lawrence Stewart <lstewart@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r194961 - projects/tcp_cc_8.x/sys/netinet Message-ID: <200906251441.n5PEfh1u054292@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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@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@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@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@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906251441.n5PEfh1u054292>