aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyujiro Shibuya <ryujiro.shibuya@owmobility.com>2020-06-24 08:36:14 +0100
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-08-18 19:47:21 +0000
commit1ff8a6c32abdfb00d427e1ab408997fc0908f50b (patch)
treed54092dc158b07980ea6c90df4392571c4ee69c8
parent347a225866851b88ed595e5a7ecde01e9c0b3260 (diff)
tcp: avoid rcv wnd more than RX fifo can enqueue
Type: fix Signed-off-by: Ryujiro Shibuya <ryujiro.shibuya@owmobility.com> Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: Ie358b731f8ecb1fcaebd6e79f5ce5c10802c2814 (cherry picked from commit cc1085647b2ae36e6c086d65b4e81b9f1cf9fc9a)
-rw-r--r--src/vnet/tcp/tcp_output.c13
-rw-r--r--src/vppinfra/clib.h6
2 files changed, 12 insertions, 7 deletions
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index 464cf5255eb..f0f5e82177f 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -121,6 +121,11 @@ tcp_update_rcv_wnd (tcp_connection_t * tc)
* Figure out how much space we have available
*/
available_space = transport_max_rx_enqueue (&tc->connection);
+
+ /* Make sure we have a multiple of 1 << rcv_wscale. We round down to
+ * avoid advertising a window larger than what can be buffered */
+ available_space = round_down_pow2 (available_space, 1 << tc->rcv_wscale);
+
if (PREDICT_FALSE (available_space < tc->rcv_opts.mss))
{
tc->rcv_wnd = 0;
@@ -136,7 +141,7 @@ tcp_update_rcv_wnd (tcp_connection_t * tc)
/* Bad. Thou shalt not shrink */
if (PREDICT_FALSE ((i32) available_space < observed_wnd))
{
- wnd = clib_max (observed_wnd, 0);
+ wnd = round_pow2 (clib_max (observed_wnd, 0), 1 << tc->rcv_wscale);
TCP_EVT (TCP_EVT_RCV_WND_SHRUNK, tc, observed_wnd, available_space);
}
else
@@ -144,12 +149,6 @@ tcp_update_rcv_wnd (tcp_connection_t * tc)
wnd = available_space;
}
- /* Make sure we have a multiple of 1 << rcv_wscale. We round up to
- * avoid advertising a window less than mss which could happen if
- * 1 << rcv_wscale < mss */
- if (wnd && tc->rcv_wscale)
- wnd = round_pow2 (wnd, 1 << tc->rcv_wscale);
-
tc->rcv_wnd = clib_min (wnd, TCP_WND_MAX << tc->rcv_wscale);
}
diff --git a/src/vppinfra/clib.h b/src/vppinfra/clib.h
index 8aec1f16beb..5e62cc81819 100644
--- a/src/vppinfra/clib.h
+++ b/src/vppinfra/clib.h
@@ -238,6 +238,12 @@ is_pow2 (uword x)
}
always_inline uword
+round_down_pow2 (uword x, uword pow2)
+{
+ return (x) & ~(pow2 - 1);
+}
+
+always_inline uword
round_pow2 (uword x, uword pow2)
{
return (x + pow2 - 1) & ~(pow2 - 1);