From 1ff8a6c32abdfb00d427e1ab408997fc0908f50b Mon Sep 17 00:00:00 2001 From: Ryujiro Shibuya Date: Wed, 24 Jun 2020 08:36:14 +0100 Subject: tcp: avoid rcv wnd more than RX fifo can enqueue Type: fix Signed-off-by: Ryujiro Shibuya Signed-off-by: Florin Coras Change-Id: Ie358b731f8ecb1fcaebd6e79f5ce5c10802c2814 (cherry picked from commit cc1085647b2ae36e6c086d65b4e81b9f1cf9fc9a) --- src/vnet/tcp/tcp_output.c | 13 ++++++------- src/vppinfra/clib.h | 6 ++++++ 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 @@ -237,6 +237,12 @@ is_pow2 (uword x) return 0 == (x & (x - 1)); } +always_inline uword +round_down_pow2 (uword x, uword pow2) +{ + return (x) & ~(pow2 - 1); +} + always_inline uword round_pow2 (uword x, uword pow2) { -- cgit 1.2.3-korg