hiren created this revision.
hiren added a reviewer: lstewart.
hiren added a subscriber: transport.
Herald added a subscriber: imp.
Herald added a reviewer: transport.
REVISION SUMMARY
Rework initial congestion window calculation.
The patch is my first (barely compiling) attempt at:
1. add ability to specify initcwnd in number of bytes
2. move entire calculation into a separate function
3. add a new sysctl to enable RFC6928 which is ON by default
4. https://reviews.freebsd.org/D5124's fix included.
Approach here is, user can specify initcwnd of choice in number of segments
or bytes. If none is present, we default to RFC6928 and have initcwnd as 10
segments.
AFAIK, this is not changing the default behavior of what we have in
FreeBSD-head right now. OR at least, that is the plan.
This change also makes enabling RFC3390 (to get initcwnd at 4 segments) more
obvious/easier. (You just have to disable RFC6928.)
Suggestions?
(I need to remember to do any manpage updates with this.)
TEST PLAN
I'll work on it once we have a general consensus on the approach.
REPOSITORY
rS FreeBSD src repository
BRANCH
rework_initcwnd
REVISION DETAIL
https://reviews.freebsd.org/D5173
AFFECTED FILES
sys/netinet/cc/cc_newreno.c
sys/netinet/tcp_input.c
sys/netinet/tcp_var.h
EMAIL PREFERENCES
https://reviews.freebsd.org/settings/panel/emailpreferences/
To: hiren, lstewart, transport
Cc: imp, transport
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -693,7 +693,9 @@
VNET_DECLARE(int, tcp_minmss);
VNET_DECLARE(int, tcp_delack_enabled);
VNET_DECLARE(int, tcp_do_rfc3390);
+VNET_DECLARE(int, tcp_do_rfc6928);
VNET_DECLARE(int, tcp_initcwnd_segments);
+VNET_DECLARE(int, tcp_initcwnd_bytes);
VNET_DECLARE(int, tcp_sendspace);
VNET_DECLARE(int, tcp_recvspace);
VNET_DECLARE(int, path_mtu_discovery);
@@ -705,7 +707,9 @@
#define V_tcp_minmss VNET(tcp_minmss)
#define V_tcp_delack_enabled VNET(tcp_delack_enabled)
#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390)
+#define V_tcp_do_rfc6928 VNET(tcp_do_rfc6928)
#define V_tcp_initcwnd_segments VNET(tcp_initcwnd_segments)
+#define V_tcp_initcwnd_bytes VNET(tcp_initcwnd_bytes)
#define V_tcp_sendspace VNET(tcp_sendspace)
#define V_tcp_recvspace VNET(tcp_recvspace)
#define V_path_mtu_discovery VNET(path_mtu_discovery)
@@ -845,6 +849,7 @@
int tcp_newreno(struct tcpcb *, struct tcphdr *);
u_long tcp_seq_subtract(u_long, u_long );
int tcp_compute_pipe(struct tcpcb *);
+u_long tcp_initcwnd(struct tcpcb *, u_int);
static inline void
tcp_fields_to_host(struct tcphdr *th)
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -168,11 +168,21 @@
&VNET_NAME(tcp_do_rfc3390), 0,
"Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
-VNET_DEFINE(int, tcp_initcwnd_segments) = 10;
+VNET_DEFINE(int, tcp_do_rfc6928) = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc6928, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(tcp_do_rfc6928), 0,
+ "Enable RFC 6928 (Increasing TCP's Initial Congestion Window)");
+
+VNET_DEFINE(int, tcp_initcwnd_segments) = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, initcwnd_segments,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_initcwnd_segments), 0,
"Slow-start flight size (initial congestion window) in number of segments");
+VNET_DEFINE(int, tcp_initcwnd_bytes) = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, initcwnd_bytes,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_initcwnd_bytes), 0,
+ "Slow-start flight size (initial congestion window) in number of bytes");
+
VNET_DEFINE(int, tcp_do_rfc3465) = 1;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3465), 0,
@@ -349,34 +359,8 @@
TCPSTAT_INC(tcps_usedssthresh);
}
- /*
- * Set the initial slow-start flight size.
- *
- * RFC5681 Section 3.1 specifies the default conservative values.
- * RFC3390 specifies slightly more aggressive values.
- * RFC6928 increases it to ten segments.
- * Support for user specified value for initial flight size.
- *
- * If a SYN or SYN/ACK was lost and retransmitted, we have to
- * reduce the initial CWND to one segment as congestion is likely
- * requiring us to be cautious.
- */
- if (tp->snd_cwnd == 1)
- tp->snd_cwnd = maxseg; /* SYN(-ACK) lost */
- else if (V_tcp_initcwnd_segments)
- tp->snd_cwnd = min(V_tcp_initcwnd_segments * maxseg,
- max(2 * maxseg, V_tcp_initcwnd_segments * 1460));
- else if (V_tcp_do_rfc3390)
- tp->snd_cwnd = min(4 * maxseg, max(2 * maxseg, 4380));
- else {
- /* Per RFC5681 Section 3.1 */
- if (maxseg > 2190)
- tp->snd_cwnd = 2 * maxseg;
- else if (maxseg > 1095)
- tp->snd_cwnd = 3 * maxseg;
- else
- tp->snd_cwnd = 4 * maxseg;
- }
+ /* Determine the initial congestion window */
+ tp->snd_cwnd = tcp_initcwnd(tp, maxseg);
if (CC_ALGO(tp)->conn_init != NULL)
CC_ALGO(tp)->conn_init(tp->ccv);
@@ -3826,3 +3810,51 @@
tp->sackhint.sack_bytes_rexmit -
tp->sackhint.sacked_bytes);
}
+
+/*
+ * Set the initial slow-start flight size.
+ *
+ * Support for user specified value for initial flight size.
+ * RFC6928 increases it to ten segments.
+ * RFC3390 specifies slightly more aggressive values.
+ * RFC5681 Section 3.1 specifies the default conservative values.
+ *
+ * If a SYN or SYN/ACK was lost and retransmitted, we have to
+ * reduce the initial CWND to one segment as congestion is likely
+ * requiring us to be cautious.
+ *
+ * Note: The "magic" numbers below are directly derived from the
+ * referenced RFCs and are kept as such for better readability.
+ */
+u_long
+tcp_initcwnd(struct tcpcb *tp, u_int maxseg)
+{
+ u_long initcwnd;
+ if (tp->snd_cwnd == 1)
+ initcwnd = maxseg; /* SYN(-ACK) lost */
+ else if (V_tcp_initcwnd_segments && V_tcp_initcwnd_bytes)
+ initcwnd = max(V_tcp_initcwnd_bytes,
+ min(V_tcp_initcwnd_segments * maxseg,
+ max(2 * maxseg, V_tcp_initcwnd_segments * 1460)));
+ else if (V_tcp_initcwnd_segments && !V_tcp_initcwnd_bytes)
+ initcwnd = min(V_tcp_initcwnd_segments * maxseg,
+ max(2 * maxseg, V_tcp_initcwnd_segments * 1460));
+ else if (V_tcp_initcwnd_bytes, !V_tcp_initcwnd_segments)
+ initcwnd = min(V_tcp_initcwnd_bytes,
+ max(2 * maxseg, V_tcp_initcwnd_bytes));
+ else if (V_tcp_do_rfc6928)
+ initcwnd = min(10 * maxseg, max(2 * maxseg, 14600));
+ else if (V_tcp_do_rfc3390)
+ initcwnd = min(4 * maxseg, max(2 * maxseg, 4380));
+ else {
+ /* Per RFC5681 Section 3.1 */
+ if (maxseg > 2190)
+ initcwnd = 2 * maxseg;
+ else if (maxseg > 1095)
+ initcwnd = 3 * maxseg;
+ else
+ initcwnd = 4 * maxseg;
+ }
+
+ return (initcwnd);
+}
diff --git a/sys/netinet/cc/cc_newreno.c b/sys/netinet/cc/cc_newreno.c
--- a/sys/netinet/cc/cc_newreno.c
+++ b/sys/netinet/cc/cc_newreno.c
@@ -151,7 +151,7 @@
static void
newreno_after_idle(struct cc_var *ccv)
{
- int rw;
+ u_long rw;
/*
* If we've been idle for more than one retransmit timeout the old
@@ -166,11 +166,7 @@
*
* See RFC5681 Section 4.1. "Restarting Idle Connections".
*/
- if (V_tcp_do_rfc3390)
- rw = min(4 * CCV(ccv, t_maxseg),
- max(2 * CCV(ccv, t_maxseg), 4380));
- else
- rw = CCV(ccv, t_maxseg) * 2;
+ rw = tcp_initcwnd(ccv->ccvc.tcp, CCV(ccv, t_maxseg));
CCV(ccv, snd_cwnd) = min(rw, CCV(ccv, snd_cwnd));
}
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-transport
To unsubscribe, send any mail to "[email protected]"