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
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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user