kernel/net: scale the window before clamping it in tcp_respond
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 20s
Test PR / Build (en_US) (pull_request) Successful in 1m51s
Test PR / Build (es_ES) (pull_request) Successful in 1m56s
Test PR / Build (ru_RU) (pull_request) Successful in 2m0s
Build system / Build (en_US) (push) Successful in 2m7s
Build system / Build (es_ES) (push) Successful in 2m13s
Build system / Build (ru_RU) (push) Successful in 2m21s
Build system / Publish Images (push) Successful in 1m46s

Summary: tcp_respond clamped the free receive space to 65535 and only then
applied RCV_SCALE, so scaled ACKs and keepalives advertised a window far
smaller than the one actually available.

Подробно:
The window field of a TCP header is 16 bits wide and, when window scaling is
in effect, carries the free space shifted right by RCV_SCALE. The two
operations therefore have to happen in that order: shift first, then clamp
the result to TCP_max_win.

tcp_respond did the opposite. With a receive buffer larger than 64 KiB and
RCV_SCALE = 2, free space of 128 KiB was first cut down to 65535 and then
shifted to 16383, announcing 64 KiB instead of the full 128 KiB. The larger
the buffer and the scale factor, the worse the under-advertisement -- the
window only ever shrank, so the effect was lost throughput rather than
corruption, but it silently defeated window scaling on exactly the responses
that carry the window most often.

tcp_output already gets this right (it compares against TCP_max_win shl
RCV_SCALE before writing the field); tcp_respond now agrees with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit was merged in pull request #618.
This commit is contained in:
2026-07-31 17:45:52 +00:00
committed by Doczom
co-authored by Claude Opus 5
parent a020a2c434
commit 35f35b39e7
+3 -3
View File
@@ -320,12 +320,12 @@ tcp_respond:
stosb
mov eax, SOCKET_BUFFER_SIZE
sub eax, [esi + STREAM_SOCKET.rcv.size]
cmp eax, TCP_max_win
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
shr eax, cl ; scale first, then clamp to the
cmp eax, TCP_max_win ; 16-bit field maximum
jbe .lessthanmax
mov eax, TCP_max_win
.lessthanmax:
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
shr eax, cl
xchg al, ah
stosw ; window