During the 3-way handshake, sender (10.16.0.128) and recipient (10.16.0.5) advertised their window size of 42340 and 65535 respectively.
From the 3rd packet (syn+ack+ack) onwards sender again advertised widow size as 166, while receiver advertised 512.
Can you please let me know why the window size was reduced without sending any segment? Does it keep changing on every ack? Why they didn't commit window size during negotiations.
10.16.0.128.59570 > 10.16.0.5.22: Flags [S], cksum 0x7da0 (incorrect -> 0xf0a5), seq 2355031382, win 42340, options [mss 1460,sackOK,TS val 4284732064 ecr 0,nop,wscale 8], length 0
09:50:58.661172 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
10.16.0.5.22 > 10.16.0.128.59570: Flags [S.], cksum 0x2d67 (correct), seq 1148159519, ack 2355031383, win 65535, options [mss 1460,sackOK,TS val 216174882 ecr 4284732064,nop,wscale 7], length 0
09:50:58.661229 IP (tos 0x0, ttl 64, id 49621, offset 0, flags [DF], proto TCP (6), length 52)
10.16.0.128.59570 > 10.16.0.5.22: Flags [.], cksum 0x7d98 (incorrect -> 0x5b8c), seq 1, ack 1, win 166, options [nop,nop,TS val 4284732065 ecr 216174882], length 0
09:50:58.661455 IP (tos 0x0, ttl 64, id 49622, offset 0, flags [DF], proto TCP (6), length 98)
10.16.0.128.59570 > 10.16.0.5.22: Flags [P.], cksum 0x7dc6 (incorrect -> 0x5b5f), seq 1:47, ack 1, win 166, options [nop,nop,TS val 4284732065 ecr 216174882], length 46
09:50:58.661543 IP (tos 0x0, ttl 64, id 8746, offset 0, flags [DF], proto TCP (6), length 52)
10.16.0.5.22 > 10.16.0.128.59570: Flags [.], cksum 0x5a03 (correct), seq 1, ack 47, win 512, options [nop,nop,TS val 216174883 ecr 4284732065], length 0
09:50:58.661543 IP (tos 0x0, ttl 64, id 8746, offset 0, flags [DF], proto TCP (6), length 52)
10.16.0.5.22 > 10.16.0.128.59570: Flags [.], cksum 0x5a03 (correct), seq 1, ack 47, win 512, options [nop,nop,TS val 216174883 ecr 4284732065], length 0```
During SYN/SYN+ACK, a window size is provided. In addition, the window scaling factor (aka window scale, that's the
wscale
in OP's capture) is transmitted for the whole TCP instance, as a TCP option valid only for SYN packets (SYN or SYN/ACK) as written in RFC 7323:The window scale is the only part that will be fixed (one value in each direction) later, if actually negotiated, since it's an option. As initially the system cannot know if such negotiation will succeed, ie: if the peer side does support window scaling and will also send this option in its SYN/ACK, it will send a "normal" tentative window size. Once negotiation happened, the initial window size will typically be divided by the scaling factor if it's to remain about the same.
So sender tells initially that it can support up to 42340 bytes and if negotiation succeeds that later this window size will be provided as chunks of 2^8 = 256. Note how roundup(42340 / 2^8) = 166: the next visible value.
The responder tells that it can support up to 65535 (the maximum without window scaling) and if negotiated will use later chunks of 2^7 = 128 bytes. Note again how roundup(65535 / 2^7) = 512, again the next visible value.
The window size wasn't really changed. It might still change later because of other factors, such as the willingness for an application to accept further data, but that wasn't what happened here. Here the size almost didn't change, it was just sent "rescaled" by the use of the window scale.
To clarify this case and address the additional comment:
For each subsequent TCP segments, the window value in the segment has to be multiplied by 2^wscale to get the actual window value. In this TCP connection, the sender peer uses wscale=8 and the responder peer uses wscale=7 (these two values won't change during the life of this connection).
If the responder were then to use win 599, that would mean accepting a actual window size of 599*2^7=76672.