Search code examples
tcpincrementseq

In TCP, is the SEQ number/SND.NXT incremented when sending pure ACKs


So I understand, for the most part, how SEQ and ACK numbers are determined (SEQ = SND.NXT = ISN + bytes sent, ACK = RCV.NXT = SEQ expected from the next received packet). What I'm wondering is how the SEQ increment (along with SND.NXT and SND.UNA) when sending a pure ACK packet.

ex: (I'm giving the Client A an ISN = 1, and the Server B ISN = 100)

A -> (SEQ = 1, ACK = 100, LEN = 412 bytes)
(A) RCV.NXT = 100, SND.NXT = 413, SND.UNA = 1
(B) RCV.NXT = 413, SND.NXT = 100, SND.UNA = 100

A <- (SEQ = 100, ACK = 413, LEN = 0)
(A) RCV.NXT = 101, SND.NXT = 413, SND.UNA = 413
(B) RCV.NXT = 413, SND.NXT = 101, SND.UNA = 101 **(or 101?)**

A <- (SEQ = 101, ACK = 413, LEN = 1448)
(A) RCV.NXT = 101, SND.NXT = 413, SND.UNA = 413
(B) RCV.NXT = 413, SND.NXT = 1549, SND.UNA = 101

A -> (SEQ = 413, ACK = 1549, LEN = 0)
(A) RCV.NXT = 1549, SND.NXT = 414, SND.UNA = 414 **(or 413?)**
(B) RCV.NXT = 414, SND.NXT = 1549, SND.UNA = 1549

It seems to make sense to increment SND.NXT every time you send a packet (even if payload len = 0), but would you also increment the SND.UNA? This seems rather arbitrary and a strange exception to the SND.UNA = ACK assignment. However, it seems to me, that if you don't do this then your SND.UNA will be off by one at the end of an exchange.

Is there something I'm missing?


Solution

  • Let's rewrite your example with the initial SYNs to keep things clear:

    A- ISN 1000
    B- ISN 2000
    
    A -> ([SYN] SEQ = 1000, ACK = ----, LEN = 0 bytes)
    (A) RCV.NXT = ----, SND.NXT = 1001, SND.UNA = 1000
    (B) RCV.NXT = 1001, SND.NXT = 2000, SND.UNA = ----
    
    A <- ([SYN,ACK] SEQ = 2000, ACK = 1001, LEN = 0)
    (A) RCV.NXT = 2001, SND.NXT = 1001, SND.UNA = 1001
    (B) RCV.NXT = 1001, SND.NXT = 2001, SND.UNA = 2000
    
    A -> ([ACK] SEQ = 1001, ACK = 2001, LEN = 0 bytes)
    (A) RCV.NXT = 2001, SND.NXT = 1001, SND.UNA = 1001
    (B) RCV.NXT = 1001, SND.NXT = 2001, SND.UNA = 2001
    

    This finishes the establishment of the TCP connection. The last packet in that sequece is a "pure ACK", that is, a TCP packet with the ACK signal and 0 data length. It does not advance the senders sequence number, therefor does not advance snd.nxt or snd.una.