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]"

Reply via email to