[TCP]: Fix BIC max_cwnd calculation error.

Linux Kernel Mailing List <[email protected]> Tue, 22 Feb 2005 01:54:02 +0000
Newsgroups gmane.linux.kernel.commits.2-4
Message-ID <[email protected]>
ChangeSet 1.1537.1.43, 2005/02/21 17:54:02-08:00, [email protected]

	[TCP]: Fix BIC max_cwnd calculation error.
	
	The BIC TCP cwnd problem as identified by Yee-Ting Li and Doug Leith
	is that the computation is recalc_ssthresh is incorrect and
	BICTCP_1_OVER_BETA/2 should be BICTCP_1_OVER_BETA*2.
	
	My fix is to implement the code from BIC TCP 1.1 which uses a sysctl
	to set the beta.  There are a few variable name changes from the 1.1
	code, and made the scaling factor a #define instead of hardcoded.
	
	I validated this using netem and kprobes, for more details see
	http://developer.osdl.org/shemminger/bic-beta-patch.pdf
	
	Signed-off-by: Stephen Hemminger <[email protected]>
	Signed-off-by: David S. Miller <[email protected]>



 include/linux/sysctl.h     |    1 +
 include/net/tcp.h          |   17 +++++++++--------
 net/ipv4/sysctl_net_ipv4.c |    3 +++
 net/ipv4/tcp_input.c       |    1 +
 4 files changed, 14 insertions(+), 8 deletions(-)


diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	2005-02-23 10:06:39 -08:00
+++ b/include/linux/sysctl.h	2005-02-23 10:06:39 -08:00
@@ -326,6 +326,7 @@
 	NET_TCP_BIC_LOW_WINDOW=104,
 	NET_TCP_DEFAULT_WIN_SCALE=105,
 	NET_TCP_MODERATE_RCVBUF=106,
+	NET_TCP_BIC_BETA=108,
 };
 
 enum {
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	2005-02-23 10:06:39 -08:00
+++ b/include/net/tcp.h	2005-02-23 10:06:39 -08:00
@@ -395,9 +395,8 @@
 # define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #endif
 
-#define BICTCP_1_OVER_BETA	8	/*
-					 * Fast recovery
-					 * multiplicative decrease factor
+#define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
+					 * max_cwnd = snd_cwnd * beta
 					 */
 #define BICTCP_MAX_INCREMENT 32		/*
 					 * Limit on the amount of
@@ -491,6 +490,7 @@
 extern int sysctl_tcp_bic;
 extern int sysctl_tcp_bic_fast_convergence;
 extern int sysctl_tcp_bic_low_window;
+extern int sysctl_tcp_bic_beta;
 extern int sysctl_tcp_default_win_scale;
 extern int sysctl_tcp_moderate_rcvbuf;
 
@@ -1132,15 +1132,16 @@
 	if (tcp_is_bic(tp)) {
 		if (sysctl_tcp_bic_fast_convergence &&
 		    tp->snd_cwnd < tp->bictcp.last_max_cwnd)
-			tp->bictcp.last_max_cwnd
-				= (tp->snd_cwnd * (2*BICTCP_1_OVER_BETA-1))
-				/ (BICTCP_1_OVER_BETA/2);
+			tp->bictcp.last_max_cwnd = (tp->snd_cwnd * 
+						    (BICTCP_BETA_SCALE
+						     + sysctl_tcp_bic_beta))
+				/ (2 * BICTCP_BETA_SCALE);
 		else
 			tp->bictcp.last_max_cwnd = tp->snd_cwnd;
 
 		if (tp->snd_cwnd > sysctl_tcp_bic_low_window)
-			return max(tp->snd_cwnd - (tp->snd_cwnd/BICTCP_1_OVER_BETA),
-				   2U);
+			return max((tp->snd_cwnd * sysctl_tcp_bic_beta)
+				   / BICTCP_BETA_SCALE, 2U);
 	}
 
 	return max(tp->snd_cwnd >> 1U, 2U);
diff -Nru a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
--- a/net/ipv4/sysctl_net_ipv4.c	2005-02-23 10:06:39 -08:00
+++ b/net/ipv4/sysctl_net_ipv4.c	2005-02-23 10:06:39 -08:00
@@ -268,6 +268,9 @@
  	{NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf",
 	 &sysctl_tcp_moderate_rcvbuf, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
+	{NET_TCP_BIC_BETA, "tcp_bic_beta",
+	 &sysctl_tcp_bic_beta, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
 	{0}
 };
 
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	2005-02-23 10:06:39 -08:00
+++ b/net/ipv4/tcp_input.c	2005-02-23 10:06:39 -08:00
@@ -107,6 +107,7 @@
 int sysctl_tcp_bic;
 int sysctl_tcp_bic_fast_convergence = 1;
 int sysctl_tcp_bic_low_window = 14;
+int sysctl_tcp_bic_beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
 
 #define FLAG_DATA		0x01 /* Incoming frame contained data.		*/
 #define FLAG_WIN_UPDATE		0x02 /* Incoming ACK was a window update.	*/