# HG changeset patch # Parent 2b91a85590f2846e352b51c6276fbb10203411f0 diff -r 2b91a85590f2 sys/netinet/cc.h --- a/sys/netinet/cc.h Mon Nov 15 11:36:36 2010 +1100 +++ b/sys/netinet/cc.h Tue Nov 16 01:19:20 2010 +1100 @@ -58,6 +58,10 @@ extern const int tcprexmtthresh; extern struct cc_algo newreno_cc_algo; +/* Per-netstack bits. */ +VNET_DECLARE(struct cc_algo *, default_cc_ptr); +#define V_default_cc_ptr VNET(default_cc_ptr) + /* Define the new net.inet.tcp.cc sysctl tree. */ SYSCTL_DECL(_net_inet_tcp_cc); @@ -146,7 +150,7 @@ #define CC_DATA(tp) ((tp)->ccv->cc_data) /* Macro to obtain the system default CC algo's struct ptr. */ -#define CC_DEFAULT() STAILQ_FIRST(&cc_list) +#define CC_DEFAULT() V_default_cc_ptr extern struct rwlock cc_list_lock; #define CC_LIST_LOCK_INIT() rw_init(&cc_list_lock, "cc_list") @@ -155,6 +159,6 @@ #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_WLOCK_ASSERT() rw_assert(&cc_list_lock, RA_WLOCKED) +#define CC_LIST_LOCK_ASSERT() rw_assert(&cc_list_lock, RA_LOCKED) #endif /* _NETINET_CC_H_ */ diff -r 2b91a85590f2 sys/netinet/cc/cc.c --- a/sys/netinet/cc/cc.c Mon Nov 15 11:36:36 2010 +1100 +++ b/sys/netinet/cc/cc.c Tue Nov 16 01:19:20 2010 +1100 @@ -81,24 +81,7 @@ /* Protects the cc_list TAILQ. */ struct rwlock cc_list_lock; -/* - * 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); - } -} +VNET_DEFINE(struct cc_algo *, default_cc_ptr) = &newreno_cc_algo; /* * Sysctl handler to show and change the default CC algorithm. @@ -106,14 +89,13 @@ static int cc_default_algo(SYSCTL_HANDLER_ARGS) { + char default_cc[TCP_CA_NAME_MAX]; struct cc_algo *funcs; int err, found; err = found = 0; if (req->newptr == NULL) { - char default_cc[TCP_CA_NAME_MAX]; - /* Just print the current default. */ CC_LIST_RLOCK(); strlcpy(default_cc, CC_DEFAULT()->name, TCP_CA_NAME_MAX); @@ -121,15 +103,15 @@ err = sysctl_handle_string(oidp, default_cc, 1, req); } else { /* Find algo with specified name and set it to default. */ - CC_LIST_WLOCK(); + CC_LIST_RLOCK(); 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_DEFAULT() = funcs; } } - CC_LIST_WUNLOCK(); + CC_LIST_RUNLOCK(); if (!found) err = ESRCH; @@ -173,6 +155,28 @@ return (err); } +static void +cc_checkreset_default(struct cc_algo *remove_cc) +{ + VNET_ITERATOR_DECL(vnet_iter); + + CC_LIST_LOCK_ASSERT(); + + /* + * Check the default CC algo for each vnet and reset to NewReno if the + * vnet is using the algo that is about to go away. + */ + VNET_LIST_RLOCK_NOSLEEP(); + VNET_FOREACH(vnet_iter) { + CURVNET_SET(vnet_iter); + if (strncmp(CC_DEFAULT()->name, remove_cc->name, + TCP_CA_NAME_MAX) == 0) + CC_DEFAULT() = &newreno_cc_algo; + CURVNET_RESTORE(); + } + VNET_LIST_RUNLOCK_NOSLEEP(); +} + /* * Initialise CC subsystem on system boot. */ @@ -202,14 +206,7 @@ CC_LIST_WLOCK(); STAILQ_FOREACH_SAFE(funcs, &cc_list, entries, tmpfuncs) { if (funcs == remove_cc) { - /* - * 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); - + cc_checkreset_default(remove_cc); STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries); err = 0; break; @@ -303,7 +300,7 @@ 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, +SYSCTL_VNET_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLTYPE_STRING|CTLFLAG_RW, NULL, 0, cc_default_algo, "A", "default congestion control algorithm"); SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, available, CTLTYPE_STRING|CTLFLAG_RD,