if a TCP packet got partially acknowledged, how will the retransmission mechanism react?
Solution 1:
This is called selective acknowledgement, and is already included in the TCP specification defined in RFC 2018. This would allow the client to indeed resend just bytes 15001 to 20000 (since they are in different packets/segments if you had split them as you say), but more interestingly, it even allows out-of-order acknowledgements.
From RFC 2018:
When receiving an ACK containing a SACK option, the data sender SHOULD record the selective acknowledgment for future reference. The data sender is assumed to have a retransmission queue that contains the segments that have been transmitted but not yet acknowledged, in sequence-number order.
Supporting SACK
is not required by the TCP specification. If either the client or the server did not support selective acknowledgement, indeed all of the bytes 10000 to 20000 would have to be retransmitted.
In TCP stack implementation, is it the same as in the theory?
Usually SACK
is supported, as the performance, efficiency, and latency gains are significant - especially in a network like the internet.
Indeed however, these assumptions should hold true even if you manually manipulate the packets as you stated. As per RFC 793, at minimum, the entire data window will have to be retransmitted, but the reciever does know that the recieved data is at least valid. For implementation details, Section 3.3 - Sequence Numbers from RFC 793.
For an outline of the entire process both with and without selective acknowledge support, see this article (which includes some very useful diagrams).
Solution 2:
Segment sizes can (and do) change over the lifetime of a connection. Luckily, TCP has no need to record the segment size that individual packets were sent with previously. Therefore, it will do the following:
- Whenever an ACK arrives, advance the pointer to the first unacknowledged byte accordingly and discard any now-unneeded buffer.
- When the need arises for retransmission (Fast Retransmit or Timeout; NOT immediately after the receipt of the first ACK!), it will resend in the currently valid segment size starting from the pointer to the first unacknowledged byte.
Both operations are done independently of the segment size these bytes were originally sent in. So the theory should match most implementations.
Let me give some background to explain:
Does TCP use bytes or segments? To the application, TCP exposes a byte stream interface. Also, all the header fields and internal variables are in bytes. However, to transmit information, TCP chunks them up in segments, as sending bytes one-by-one would be pretty wasteful :-). Using byte counters everywhere has the advantage that the segment size does not need to remain constant over the lifetime of the connection:
- Options are being introduced, e.g. piggybacking a SACK on a retransmit (real implementations will encounter this rarely, if at all)
- The Path MTU changes, e.g. one link along the path changes to a lower MTU or the bottleneck MTU link is raised. This happens when tunnels are established (VPN, PPPoE) or the routing protocol selects a different-MTU link. This happens in IPv4 with Don't Fragment set (true for most modern TCPs); always in TCPv6).
BTW: SACK is not the answer here, as the receiver will (typically) only use SACK if it recognizes a hole in the byte stream (i.e., if a packet got lost but a following packet arrived).