svn commit: r354774 - head/sys/netinet/cc

Michael Tuexen tuexen at FreeBSD.org
Sat Nov 16 12:00:24 UTC 2019


Author: tuexen
Date: Sat Nov 16 12:00:22 2019
New Revision: 354774
URL: https://svnweb.freebsd.org/changeset/base/354774

Log:
  Add boundary and overflow checks to the formulas used in the TCP CUBIC
  congestion control module.
  
  Submitted by:		Richard Scheffenegger
  Reviewed by:		rgrimes@
  Differential Revision:	https://reviews.freebsd.org/D19118

Modified:
  head/sys/netinet/cc/cc_cubic.c
  head/sys/netinet/cc/cc_cubic.h

Modified: head/sys/netinet/cc/cc_cubic.c
==============================================================================
--- head/sys/netinet/cc/cc_cubic.c	Sat Nov 16 11:57:12 2019	(r354773)
+++ head/sys/netinet/cc/cc_cubic.c	Sat Nov 16 12:00:22 2019	(r354774)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/limits.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/socket.h>
@@ -140,7 +141,14 @@ cubic_ack_received(struct cc_var *ccv, uint16_t type)
 		    cubic_data->min_rtt_ticks == TCPTV_SRTTBASE)
 			newreno_cc_algo.ack_received(ccv, type);
 		else {
-			ticks_since_cong = ticks - cubic_data->t_last_cong;
+			if ((ticks_since_cong =
+			    ticks - cubic_data->t_last_cong) < 0) {
+				/*
+				 * dragging t_last_cong along
+				 */
+				ticks_since_cong = INT_MAX;
+				cubic_data->t_last_cong = ticks - INT_MAX;
+			}
 
 			/*
 			 * The mean RTT is used to best reflect the equations in
@@ -159,12 +167,14 @@ cubic_ack_received(struct cc_var *ccv, uint16_t type)
 
 			ccv->flags &= ~CCF_ABC_SENTAWND;
 
-			if (w_cubic_next < w_tf)
+			if (w_cubic_next < w_tf) {
 				/*
 				 * TCP-friendly region, follow tf
 				 * cwnd growth.
 				 */
-				CCV(ccv, snd_cwnd) = w_tf;
+				if (CCV(ccv, snd_cwnd) < w_tf)
+					CCV(ccv, snd_cwnd) = ulmin(w_tf, INT_MAX);
+			}
 
 			else if (CCV(ccv, snd_cwnd) < w_cubic_next) {
 				/*
@@ -172,12 +182,14 @@ cubic_ack_received(struct cc_var *ccv, uint16_t type)
 				 * cwnd growth.
 				 */
 				if (V_tcp_do_rfc3465)
-					CCV(ccv, snd_cwnd) = w_cubic_next;
+					CCV(ccv, snd_cwnd) = ulmin(w_cubic_next,
+					    INT_MAX);
 				else
-					CCV(ccv, snd_cwnd) += ((w_cubic_next -
+					CCV(ccv, snd_cwnd) += ulmax(1,
+					    ((ulmin(w_cubic_next, INT_MAX) -
 					    CCV(ccv, snd_cwnd)) *
 					    CCV(ccv, t_maxseg)) /
-					    CCV(ccv, snd_cwnd);
+					    CCV(ccv, snd_cwnd));
 			}
 
 			/*

Modified: head/sys/netinet/cc/cc_cubic.h
==============================================================================
--- head/sys/netinet/cc/cc_cubic.h	Sat Nov 16 11:57:12 2019	(r354773)
+++ head/sys/netinet/cc/cc_cubic.h	Sat Nov 16 12:00:22 2019	(r354774)
@@ -41,6 +41,8 @@
 #ifndef _NETINET_CC_CUBIC_H_
 #define _NETINET_CC_CUBIC_H_
 
+#include <sys/limits.h>
+
 /* Number of bits of precision for fixed point math calcs. */
 #define	CUBIC_SHIFT		8
 
@@ -70,6 +72,12 @@
 /* Don't trust s_rtt until this many rtt samples have been taken. */
 #define	CUBIC_MIN_RTT_SAMPLES	8
 
+/*
+ * (2^21)^3 is long max. Dividing (2^63) by Cubic_C_factor
+ * and taking cube-root yields 448845 as the effective useful limit
+ */
+#define	CUBED_ROOT_MAX_ULONG	448845
+
 /* Userland only bits. */
 #ifndef _KERNEL
 
@@ -172,8 +180,13 @@ cubic_cwnd(int ticks_since_cong, unsigned long wmax, u
 	/* K is in fixed point form with CUBIC_SHIFT worth of precision. */
 
 	/* t - K, with CUBIC_SHIFT worth of precision. */
-	cwnd = ((int64_t)(ticks_since_cong << CUBIC_SHIFT) - (K * hz)) / hz;
+	cwnd = (((int64_t)ticks_since_cong << CUBIC_SHIFT) - (K * hz)) / hz;
 
+	if (cwnd > CUBED_ROOT_MAX_ULONG)
+		return INT_MAX;
+	if (cwnd < -CUBED_ROOT_MAX_ULONG)
+		return 0;
+
 	/* (t - K)^3, with CUBIC_SHIFT^3 worth of precision. */
 	cwnd *= (cwnd * cwnd);
 
@@ -183,9 +196,13 @@ cubic_cwnd(int ticks_since_cong, unsigned long wmax, u
 	 * CUBIC_SHIFT included in the value. 3 from the cubing of cwnd above,
 	 * and an extra from multiplying through by CUBIC_C_FACTOR.
 	 */
-	cwnd = ((cwnd * CUBIC_C_FACTOR * smss) >> CUBIC_SHIFT_4) + wmax;
 
-	return ((unsigned long)cwnd);
+	cwnd = ((cwnd * CUBIC_C_FACTOR) >> CUBIC_SHIFT_4) * smss + wmax;
+
+	/*
+	 * for negative cwnd, limiting to zero as lower bound
+	 */
+	return (lmax(0,cwnd));
 }
 
 /*
@@ -223,8 +240,10 @@ tf_cwnd(int ticks_since_cong, int rtt_ticks, unsigned 
 {
 
 	/* Equation 4 of I-D. */
-	return (((wmax * CUBIC_BETA) + (((THREE_X_PT3 * ticks_since_cong *
-	    smss) << CUBIC_SHIFT) / TWO_SUB_PT3 / rtt_ticks)) >> CUBIC_SHIFT);
+	return (((wmax * CUBIC_BETA) +
+	    (((THREE_X_PT3 * (unsigned long)ticks_since_cong *
+	    (unsigned long)smss) << CUBIC_SHIFT) / (TWO_SUB_PT3 * rtt_ticks)))
+	    >> CUBIC_SHIFT);
 }
 
 #endif /* _NETINET_CC_CUBIC_H_ */


More information about the svn-src-head mailing list