Index: sys/netinet/cc/cc_newreno.c =================================================================== --- sys/netinet/cc/cc_newreno.c +++ sys/netinet/cc/cc_newreno.c @@ -48,6 +48,13 @@ * http://caia.swin.edu.au/urp/newtcp/ */ +/* + * Dec 2014 garmitage@swin.edu.au + * Borrowed code fragments from cc_cdg.c to add modifiable beta + * via sysctls. + * + */ + #include __FBSDID("$FreeBSD$"); @@ -68,11 +75,23 @@ #include #include +#define CAST_PTR_INT(X) (*((int*)(X))) + +#ifndef VIMAGE +#define vnet_sysctl_handle_uint(oidp, arg1, arg2, req) \ + sysctl_handle_int(oidp, arg1, arg2, req) +#endif + static void newreno_ack_received(struct cc_var *ccv, uint16_t type); static void newreno_after_idle(struct cc_var *ccv); static void newreno_cong_signal(struct cc_var *ccv, uint32_t type); static void newreno_post_recovery(struct cc_var *ccv); +static VNET_DEFINE(uint32_t, newreno_beta_loss) = 50; +static VNET_DEFINE(uint32_t, newreno_beta_ecn) = 80; +#define V_newreno_beta_loss VNET(newreno_beta_loss) +#define V_newreno_beta_ecn VNET(newreno_beta_ecn) + struct cc_algo newreno_cc_algo = { .name = "newreno", .ack_received = newreno_ack_received, @@ -195,10 +214,14 @@ KASSERT((type & CC_SIGPRIVMASK) == 0, ("%s: congestion signal type 0x%08x is private\n", __func__, type)); - cwin = max(cwin / 2 / mss, 2) * mss; switch (type) { case CC_NDUPACK: + if (V_tcp_do_abe) + cwin = max((cwin * V_newreno_beta_loss)/100 / mss, 2) * mss; + else + cwin = max(cwin / 2 / mss, 2) * mss; + if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { CCV(ccv, snd_ssthresh) = ssthresh_on_loss; @@ -208,6 +231,11 @@ } break; case CC_ECN: + if (V_tcp_do_abe) + cwin = max((cwin * V_newreno_beta_ecn)/100 / mss, 2) * mss; + else + cwin = max(cwin / 2 / mss, 2) * mss; + if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { CCV(ccv, snd_ssthresh) = ssthresh_on_loss; CCV(ccv, snd_cwnd) = cwin; @@ -252,5 +280,28 @@ } } +static int +newreno_beta_handler(SYSCTL_HANDLER_ARGS) +{ + if (req->newptr != NULL && + (CAST_PTR_INT(req->newptr) <= 0 || CAST_PTR_INT(req->newptr) > 100)) + return (EINVAL); + + return (vnet_sysctl_handle_uint(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"); + +SYSCTL_PROC(_net_inet_tcp_cc_newreno, OID_AUTO, beta_loss, + CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, + &VNET_NAME(newreno_beta_loss), 3, &newreno_beta_handler, "IU", + "newreno beta loss, specified as number between 0 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", + "newreno beta ecn, specified as number between 0 and 100"); DECLARE_CC_MODULE(newreno, &newreno_cc_algo); Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -181,6 +181,11 @@ &VNET_NAME(tcp_abc_l_var), 2, "Cap the max cwnd increment during slow-start to this number of segments"); +VNET_DEFINE(int, tcp_do_abe) = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, abe, CTLFLAG_VNET | CTLFLAG_RW, + &VNET_NAME(tcp_do_abe), 0, + "Enable ABE for NewReno (Alternative Backoff with ECN)"); + static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN"); VNET_DEFINE(int, tcp_do_ecn) = 2; Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -708,6 +708,7 @@ VNET_DECLARE(int, path_mtu_discovery); VNET_DECLARE(int, tcp_do_rfc3465); VNET_DECLARE(int, tcp_abc_l_var); +VNET_DECLARE(int, tcp_do_abe); #define V_tcb VNET(tcb) #define V_tcbinfo VNET(tcbinfo) #define V_tcp_mssdflt VNET(tcp_mssdflt) @@ -720,6 +721,7 @@ #define V_path_mtu_discovery VNET(path_mtu_discovery) #define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465) #define V_tcp_abc_l_var VNET(tcp_abc_l_var) +#define V_tcp_do_abe VNET(tcp_do_abe) VNET_DECLARE(int, tcp_do_sack); /* SACK enabled/disabled */ VNET_DECLARE(int, tcp_sc_rst_sock_fail); /* RST on sock alloc failure */