I've learned that after three duplicate ACKs (so a total of 4 ACKs with the same value), the sender assumes that a packet was lost and sends the packet with that value again.
Here's a graph from the book I'm reading:
In this case, what does the receiver respond? ACK 120, or ACK 157?
This really depends whether or not SACK (Selective ACK) has been negotiated. If it has:
Each retransmission of ACK 100 will include a TCP SACK option indicating the aggregate of bytes that have been received after the missing segment that are pending if the gap is filled
Given what you show you should see SACK indicating that offsets 120-135, then 120-141, then 120-157.
When the missing 20 bytes are transmitted, you will see ACK 157
If SACK has not been negotiated:
You will see ACK 100 indicating the missing segment for every segment after that
When the missing segment is sent, if it contains only the original 20 bytes, the ACK will be for 120 and all subsequent segments must be retransmitted as well.
Related
TCP fast recovery algorithm is described as follows(from TCP illustrated vol. 1). What I can't understand is in step 1, why there's a CWD window inflation by three times the segment size?
When the third duplicate ACK is received, set ssthresh to one-half the current congestion window, cwnd. Retransmit the missing segment.
Set cwnd to ssthresh plus 3 times the segment size.
Each time another duplicate ACK arrives, increment cwnd by the segment size and transmit a packet (if allowed by the new value of
cwnd).
When the next ACK arrives that acknowledges new data, set cwnd to ssthresh. This should be the ACK of the retransmission from step 1,
one round-trip time after the retransmission. Additionally, this ACK
should acknowledge all the intermediate segments sent between the lost
packet and the receipt of the first duplicate ACK. This step is
congestion avoidance, since we're slowing down to one-half the rate we
were at when the packet was lost.
From [RFC 2001][1]
When the third duplicate ACK in a row is received, set ssthresh
to one-half the current congestion window, cwnd, but no less
than two segments. Retransmit the missing segment. Set cwnd to
ssthresh plus 3 times the segment size. This inflates the
congestion window by the number of segments that have left the
network and which the other end has cached
So, when you receive 3 duplicate ACKs in a row you cut cwnd to half and perform a fast retransmit, from now on you're trying to not just idle while waiting for the next new ACK (1 RTT at best). Once you enter fast recovery, you send new data with
cwnd= original cwnd + # of duplicate ACKs received
until either you receive the ACK you were waiting for or the timer for that ACK expires.
Basically, that "+3" takes account for those 3 acks received that made you enter fast recovery in the first place so that you transmit a number of new bytes equal to the lost bytes + the ones that got to the receiver but were discarded.
[1]: https://www.rfc-editor.org/rfc/rfc2001
I've learned that after three duplicate ACKs (so a total of 4 ACKs with the same value), the sender assumes that a packet was lost and sends the packet with that value again.
Here's a graph from the book I'm reading:
In this case, what does the receiver respond? ACK 120, or ACK 157?
This really depends whether or not SACK (Selective ACK) has been negotiated. If it has:
Each retransmission of ACK 100 will include a TCP SACK option indicating the aggregate of bytes that have been received after the missing segment that are pending if the gap is filled
Given what you show you should see SACK indicating that offsets 120-135, then 120-141, then 120-157.
When the missing 20 bytes are transmitted, you will see ACK 157
If SACK has not been negotiated:
You will see ACK 100 indicating the missing segment for every segment after that
When the missing segment is sent, if it contains only the original 20 bytes, the ACK will be for 120 and all subsequent segments must be retransmitted as well.
Let's say we have a host A and a host B
I send 5 segment from A to B, with sequence number starting from 100 and each segment is 20 bytes long
If there were no packet lost, then I should expect ACK = 200 from B
but there was a packet lost, B got all segment except the 2nd one
I should get 4 ACK of 120 from B, indicating a lost of 2nd segment
After I resend 2nd segment, what will be the ACK from B, is it gonna be 140 or 200?
If it is 140, then it means B didn't buffer 3rd 4th and 5th segment
If it is 200, then it means B only needs the 2nd segment
which one is the true answer?
The buffering technique of out-of-order packets is not the part of the TCP protocol. So it depends on the receiver's TCP implementation.
In both options, TCP sender will correctly handle the situation.
The technique to deal with out of order packets in Linux TCP is well described here:
Johannessen, Mads. Investigate reordering in Linux TCP. MS thesis. 2015.
https://www.duo.uio.no/bitstream/handle/10852/47651/1/thesis-madsjoh.pdf
According to this research, Linux TCP will probably buffer 3rd, 4th and 5th segments (if there is enough space for it) and reply to retransmission with the ACK = 200.
In a situation where both client and server sets their respective sequence number to 0, I read that the following is true:
C-->S: SYN=1, SEQ=0 (No data bytes)
C<--S: SYN=1, SEQ=0, ACK=1 (No data bytes)
C-->S: SEQ=1, ACK=1 (Data bytes optional)
In the third part, I understand the server is expecting the next sequence number to be 1, but aren't sequence numbers supposed to be set to initial_seq_num + sent_data_bytes_num? Since there was no data bytes sent in the first part of the handshake shouldn't the seq # be 0?
Is this just an exception during the handshake or are segments sent to with no data bytes supposed to increment the sequence number by 1 if they can be sent at all?
(There is a similar Q & A but the answer doesn't explain if this is an exception during the handshake phase OR if this happens after a TCP connection has been establish. I'm not even sure if a segment with no data bytes can even be sent. I'm assuming you can't)
ADDED It seems TCP keep-alive packets have no payload either. RFC 1122 says in these packets, SEG.SEQ = SND.NXT-1, and because this sequence number will be an already ACKed number, and a duplicate ACK will be sent, so as to keep the sequence number of the server the same.
Otherwise, I couldn't find any indications of what needs to be done when the sequence number is correct but there is no payload. I might be wrong since I only briefly scanned the document, but there is also no statement of rules of sequence numbering during the handshake except for examples.
In RFC 1122, it says
Unfortunately, some misbehaved TCP implementations fail to respond to a segment with SEG.SEQ = SND.NXT-1 unless the segment contains data.
So I'm assuming it depends on each implementation, but if there is any statement of a) the sequence numbering during handshake, and b) how to behave when the sequence # is correct but there is no payload, I would really appreciate it if someone could point me to that part.
Thanks!
The first ACK (that occurs as part of Handshake) acknowledges the reception of SYN from the other end. The SYN segment does not carry any data. But to allow the provision for acknowledging the reception of SYN, the first ACK is incremented though no payload is present.
The 32-bit acknowledgement field, say x, on the TCP header
tells the other host that "I received all the bytes up until and including x-1,
now expecting
the bytes from x and on". In this case, the receiver may have received some
further bytes, say x+100 through x+180,
but it hasn't yet received x-th byte yet.
Is there a case that, although the receiver hasn't received
x through x+100 bytes but received the bytes say x+100 through x+180,
the receiver is acknowledging that it received x+180?
One resource I read indicates the acknowledgement of bytes received despite a gap in the earlier bytes.
However, every other source tells
"acknowledgement of x tells all bytes up until x-1 are received".
Are there any exceptional cases? I'm looking to verify this.
TIA.
This can be achieved by TCP option called SACK.
Here, client can say through a duplicate ACK that it has only up to particular packet number 2 (sequence number of packet) in order and append SACK(Selective Acknowledgement) option for the range of contiguous packets received like packets numbered 4 to 5 (sequence number). This in turn shall enable the server to retransmit only the packets(3 sequence number) that were not received by the client.
Provided below an extract from RFC 2018 : TCP Selective Acknowledgement Options
The SACK option is to be sent by a data receiver to inform the data
sender of non-contiguous blocks of data that have been received and
queued. The data receiver awaits the receipt of data (perhaps by
means of retransmissions) to fill the gaps in sequence space between
received blocks. When missing segments are received, the data
receiver acknowledges the data normally by advancing the left window
edge in the Acknowledgement Number Field of the TCP header. The SACK
option does not change the meaning of the Acknowledgement Number
field.
From the TCP RFC at https://www.rfc-editor.org/rfc/rfc793.txt:
3.3. Sequence Numbers
A fundamental notion in the design is that every octet of data sent
over a TCP connection has a sequence number. Since every octet is
sequenced, each of them can be acknowledged. The acknowledgment
mechanism employed is cumulative so that an acknowledgment of sequence
number X indicates that all octets up to but not including X have been
received.
That seems pretty clear to me, the sequence number stops at the first missing data.