From d65f0b89c2cb8685a1ebfb728dc45736bda038ed Mon Sep 17 00:00:00 2001 From: "He.kai Zhang.zihan" Date: Wed, 19 Nov 2025 21:11:26 +0800 Subject: [PATCH] tcp:provide 2 options for MSS/TSO window size: half the window or full window. In high-latency scenarios, limiting MSS/TSO to half the receive window size is appropriate.In low-latency scenarios,utilizing the full window size is optional. For example, in low-latency environments, when an embedded device has a receive window of one MSS size (e.g., 1460 bytes),Linux can transmit a full MSS to the device in a single segment,rather than splitting it into two separate transmissions. In fact, Linux can't but Win10 can. So provide a configuration optionto fix it. Signed-off-by: He.kai Zhang.zihan --- include/net/tcp.h | 31 +++++++++++++++++++++++++++++++ net/ipv4/Kconfig | 9 +++++++++ net/ipv4/tcp.c | 2 +- net/ipv4/tcp_output.c | 2 +- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 526a26e7a..9da7f5287 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -777,6 +777,37 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) return pktsize; } + +/* Bound MSS / TSO packet size with the max of the window */ +static inline int tcp_bound_to_max_wnd(struct tcp_sock *tp, int pktsize) +{ + int tmp; + + tmp = tp->max_window; + + if (tmp && pktsize > tmp) + return max_t(int, tmp, 68U - tp->tcp_header_len); + else + return pktsize; +} + + +#ifdef CONFIG_TCP_BOUND_HALF_WINDOW + +static inline int tcp_bound_to_wnd(struct tcp_sock *tp, int pktsize) +{ + return tcp_bound_to_half_wnd(tp, pktsize); +} + +#else + +static inline int tcp_bound_to_wnd(struct tcp_sock *tp, int pktsize) +{ + return tcp_bound_to_max_wnd(tp, pktsize); +} + +#endif + /* tcp.c */ void tcp_get_info(struct sock *, struct tcp_info *); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 12850a277..4365e31e8 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -679,6 +679,15 @@ config TCP_CONG_BBR AQM schemes that do not provide a delay signal. It requires the fq ("Fair Queue") pacing packet scheduler. +config TCP_BOUND_HALF_WINDOW + bool "Bound MSS / TSO packet size with the half of the window" + default y + help + Use the default half-window bounding for MSS / TSO packet. + In high-latency scenarios, limiting MSS/TSO to half the receive + window size is appropriate.In low-latency scenarios,utilizing + the full window size is optional. + choice prompt "Default TCP congestion control" default DEFAULT_CUBIC diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ba36f558f..bec8501c4 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -924,7 +924,7 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, return mss_now; /* Note : tcp_tso_autosize() will eventually split this later */ - new_size_goal = tcp_bound_to_half_wnd(tp, sk->sk_gso_max_size); + new_size_goal = tcp_bound_to_wnd(tp, sk->sk_gso_max_size); /* We try hard to avoid divides here */ size_goal = tp->gso_segs * mss_now; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 16251d8e1..1773075b9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1849,7 +1849,7 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu) icsk->icsk_mtup.search_high = pmtu; mss_now = tcp_mtu_to_mss(sk, pmtu); - mss_now = tcp_bound_to_half_wnd(tp, mss_now); + mss_now = tcp_bound_to_wnd(tp, mss_now); /* And store cached results */ icsk->icsk_pmtu_cookie = pmtu; -- 2.34.1