Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/cc/cc_newreno.c
Context not available. | |||||
* University Research Program Fund at Community Foundation Silicon Valley. | * University Research Program Fund at Community Foundation Silicon Valley. | ||||
* More details are available at: | * More details are available at: | ||||
* http://caia.swin.edu.au/urp/newtcp/ | * http://caia.swin.edu.au/urp/newtcp/ | ||||
* | |||||
* Dec 2014 garmitage@swin.edu.au | |||||
lstewart: If this is supposed to be an actual copyright attribution, you should add the appropriate year… | |||||
* Borrowed code fragments from cc_cdg.c to add modifiable beta | |||||
* via sysctls. | |||||
* | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
Context not available. | |||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#include <netinet/cc/cc.h> | #include <netinet/cc/cc.h> | ||||
#include <netinet/cc/cc_module.h> | #include <netinet/cc/cc_module.h> | ||||
#include <netinet/cc/cc_newreno.h> | |||||
static MALLOC_DEFINE(M_NEWRENO, "newreno data", | |||||
"newreno beta values"); | |||||
Done Inline ActionsThis #ifndef block is not needed lstewart: This #ifndef block is not needed | |||||
#define CAST_PTR_INT(X) (*((int*)(X))) | |||||
static int newreno_cb_init(struct cc_var *ccv); | |||||
static void newreno_cb_destroy(struct cc_var *ccv); | |||||
static void newreno_ack_received(struct cc_var *ccv, uint16_t type); | static void newreno_ack_received(struct cc_var *ccv, uint16_t type); | ||||
static void newreno_after_idle(struct cc_var *ccv); | static void newreno_after_idle(struct cc_var *ccv); | ||||
static void newreno_cong_signal(struct cc_var *ccv, uint32_t type); | static void newreno_cong_signal(struct cc_var *ccv, uint32_t type); | ||||
static void newreno_post_recovery(struct cc_var *ccv); | static void newreno_post_recovery(struct cc_var *ccv); | ||||
static int newreno_ctl_output(struct cc_var *ccv, struct sockopt *sopt, void *buf); | |||||
Not Done Inline ActionsWhat about treating these as permanently defined variables which default to non-ABE behaviour i.e. 50 and 50, and toggling ABE simply explicitly sets them to draft-specified values? Perhaps renaming newreno_beta_loss to newreno_beta would also make sense, which specifies the default beta that gets overridden by other variables on a case by case basis. lstewart: What about treating these as permanently defined variables which default to non-ABE behaviour i. | |||||
static VNET_DEFINE(uint32_t, newreno_beta) = 50; | |||||
static VNET_DEFINE(uint32_t, newreno_beta_ecn) = 80; | |||||
#define V_newreno_beta VNET(newreno_beta) | |||||
#define V_newreno_beta_ecn VNET(newreno_beta_ecn) | |||||
struct cc_algo newreno_cc_algo = { | struct cc_algo newreno_cc_algo = { | ||||
.name = "newreno", | .name = "newreno", | ||||
.cb_init = newreno_cb_init, | |||||
.cb_destroy = newreno_cb_destroy, | |||||
.ack_received = newreno_ack_received, | .ack_received = newreno_ack_received, | ||||
.after_idle = newreno_after_idle, | .after_idle = newreno_after_idle, | ||||
.cong_signal = newreno_cong_signal, | .cong_signal = newreno_cong_signal, | ||||
.post_recovery = newreno_post_recovery, | .post_recovery = newreno_post_recovery, | ||||
.ctl_output = newreno_ctl_output, | |||||
}; | }; | ||||
struct newreno { | |||||
uint32_t beta; | |||||
uint32_t beta_ecn; | |||||
}; | |||||
int | |||||
newreno_cb_init(struct cc_var *ccv) | |||||
{ | |||||
struct newreno *nreno; | |||||
nreno = malloc(sizeof(struct newreno), M_NEWRENO, M_NOWAIT|M_ZERO); | |||||
if (nreno != NULL) { | |||||
nreno->beta = V_newreno_beta; | |||||
nreno->beta_ecn = V_newreno_beta_ecn; | |||||
} | |||||
ccv->cc_data = nreno; | |||||
return (0); | |||||
} | |||||
void | |||||
newreno_cb_destroy(struct cc_var *ccv) | |||||
{ | |||||
if (ccv->cc_data != NULL) { | |||||
free(ccv->cc_data, M_NEWRENO); | |||||
ccv->cc_data = NULL; | |||||
} | |||||
} | |||||
static void | static void | ||||
newreno_ack_received(struct cc_var *ccv, uint16_t type) | newreno_ack_received(struct cc_var *ccv, uint16_t type) | ||||
{ | { | ||||
Context not available. | |||||
static void | static void | ||||
newreno_cong_signal(struct cc_var *ccv, uint32_t type) | newreno_cong_signal(struct cc_var *ccv, uint32_t type) | ||||
{ | { | ||||
u_int win; | struct newreno *nreno; | ||||
uint32_t cwin, factor; | |||||
u_int mss; | |||||
factor = V_newreno_beta; | |||||
nreno = ccv->cc_data; | |||||
if (nreno != NULL) { | |||||
if (V_tcp_do_abe) | |||||
factor = (type == CC_ECN ? nreno->beta_ecn: nreno->beta); | |||||
else | |||||
factor = nreno->beta; | |||||
} | |||||
cwin = CCV(ccv, snd_cwnd); | |||||
mss = CCV(ccv, t_maxseg); | |||||
/* Catch algos which mistakenly leak private signal types. */ | /* Catch algos which mistakenly leak private signal types. */ | ||||
KASSERT((type & CC_SIGPRIVMASK) == 0, | KASSERT((type & CC_SIGPRIVMASK) == 0, | ||||
("%s: congestion signal type 0x%08x is private\n", __func__, type)); | ("%s: congestion signal type 0x%08x is private\n", __func__, type)); | ||||
win = max(CCV(ccv, snd_cwnd) / 2 / CCV(ccv, t_maxseg), 2) * | cwin = max(((uint64_t)cwin * (uint64_t)factor) / (100ULL * (uint64_t)mss), | ||||
CCV(ccv, t_maxseg); | 2) * mss; | ||||
switch (type) { | switch (type) { | ||||
case CC_NDUPACK: | case CC_NDUPACK: | ||||
if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { | if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { | ||||
Done Inline ActionsLet's avoid gratuitous code duplication, and perhaps reinstate this line as something like: factor = (type == CC_ECN ? V_newreno_beta_ecn : V_newreno_beta_loss); lstewart: Let's avoid gratuitous code duplication, and perhaps reinstate this line as something like… | |||||
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) | if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) | ||||
CCV(ccv, snd_ssthresh) = win; | CCV(ccv, snd_ssthresh) = cwin; | ||||
ENTER_RECOVERY(CCV(ccv, t_flags)); | ENTER_RECOVERY(CCV(ccv, t_flags)); | ||||
} | } | ||||
break; | break; | ||||
case CC_ECN: | case CC_ECN: | ||||
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { | ||||
CCV(ccv, snd_ssthresh) = win; | CCV(ccv, snd_ssthresh) = cwin; | ||||
CCV(ccv, snd_cwnd) = win; | CCV(ccv, snd_cwnd) = cwin; | ||||
ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ENTER_CONGRECOVERY(CCV(ccv, t_flags)); | ||||
} | } | ||||
break; | break; | ||||
Done Inline ActionsThis can change to sysctl_handle_int() lstewart: This can change to sysctl_handle_int() | |||||
Context not available. | |||||
} | } | ||||
} | } | ||||
int | |||||
newreno_ctl_output(struct cc_var *ccv, struct sockopt *sopt, void *buf) | |||||
{ | |||||
struct newreno *nreno; | |||||
struct cc_newreno_opts *opt; | |||||
if (sopt->sopt_valsize != sizeof(struct cc_newreno_opts)) | |||||
return (EMSGSIZE); | |||||
nreno = ccv->cc_data; | |||||
if (nreno == NULL) | |||||
return (ENOPROTOOPT); | |||||
opt = buf; | |||||
switch (sopt->sopt_dir) { | |||||
case SOPT_SET: | |||||
switch (opt->name) { | |||||
case CC_NEWRENO_BETA: | |||||
nreno->beta = opt->val; | |||||
break; | |||||
case CC_NEWRENO_BETA_ECN: | |||||
if (!V_tcp_do_abe) | |||||
return (EACCES); | |||||
nreno->beta_ecn = opt->val; | |||||
break; | |||||
default: | |||||
return (ENOPROTOOPT); | |||||
} | |||||
break; | |||||
case SOPT_GET: | |||||
switch (opt->name) { | |||||
case CC_NEWRENO_BETA: | |||||
opt->val = nreno->beta; | |||||
break; | |||||
case CC_NEWRENO_BETA_ECN: | |||||
opt->val = nreno->beta_ecn; | |||||
break; | |||||
default: | |||||
return (ENOPROTOOPT); | |||||
} | |||||
break; | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
newreno_beta_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
if (req->newptr != NULL ) { | |||||
if (arg1 == &VNET_NAME(newreno_beta_ecn) && !V_tcp_do_abe) | |||||
return (EACCES); | |||||
if (CAST_PTR_INT(req->newptr) <= 0 || CAST_PTR_INT(req->newptr) > 100) | |||||
return (EINVAL); | |||||
} | |||||
return (sysctl_handle_int(oidp, arg1, arg2, req)); | |||||
} | |||||
SYSCTL_DECL(_net_inet_tcp_cc_newreno); | |||||
SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, newreno, CTLFLAG_RW, NULL, | |||||
"New Reno related settings"); | |||||
Done Inline ActionsPlease note in the sysctl description that net.inet.tcp.abe must be 1 for this variable to be settable. lstewart: Please note in the sysctl description that net.inet.tcp.abe must be 1 for this variable to be… | |||||
SYSCTL_PROC(_net_inet_tcp_cc_newreno, OID_AUTO, beta, | |||||
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, | |||||
&VNET_NAME(newreno_beta), 3, &newreno_beta_handler, "IU", | |||||
"New Reno beta, specified as number between 1 and 100"); | |||||
SYSCTL_PROC(_net_inet_tcp_cc_newreno, OID_AUTO, beta_ecn, | |||||
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, | |||||
&VNET_NAME(newreno_beta_ecn), 3, &newreno_beta_handler, "IU", | |||||
"New Reno beta ecn, specified as number between 1 and 100"); | |||||
DECLARE_CC_MODULE(newreno, &newreno_cc_algo); | DECLARE_CC_MODULE(newreno, &newreno_cc_algo); | ||||
Context not available. |
If this is supposed to be an actual copyright attribution, you should add the appropriate year to the existing set attributed to Swinburne University in the main copyright block, and then extend the second informative comment block with these additional author attribution details.
That being said, given the size of the change it probably doesn't warrant copyright changes, so merging this in to the informative comment block is probably all that's needed.