Connected: An Internet Encyclopedia
3.3 Sequence Numbers

Up: Connected: An Internet Encyclopedia
Up: Requests For Comments
Up: RFC 793
Up: 3. FUNCTIONAL SPECIFICATION
Prev: 3.2 Terminology
Next: 3.4 Establishing a connection

3.3 Sequence Numbers

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. This mechanism allows for straight-forward duplicate detection in the presence of retransmission. Numbering of octets within a segment is that the first data octet immediately following the header is the lowest numbered, and the following octets are numbered consecutively.

It is essential to remember that the actual sequence number space is finite, though very large. This space ranges from 0 to 2**32 - 1. Since the space is finite, all arithmetic dealing with sequence numbers must be performed modulo 2**32. This unsigned arithmetic preserves the relationship of sequence numbers as they cycle from 2**32 - 1 to 0 again. There are some subtleties to computer modulo arithmetic, so great care should be taken in programming the comparison of such values. The symbol "=<" means "less than or equal" (modulo 2**32).

The typical kinds of sequence number comparisons which the TCP must perform include:

    (a)  Determining that an acknowledgment refers to some sequence
         number sent but not yet acknowledged.

    (b)  Determining that all sequence numbers occupied by a segment
         have been acknowledged (e.g., to remove the segment from a
         retransmission queue).

    (c)  Determining that an incoming segment contains sequence numbers
         which are expected (i.e., that the segment "overlaps" the
         receive window).

In response to sending data the TCP will receive acknowledgments. The following comparisons are needed to process the acknowledgments.

    SND.UNA = oldest unacknowledged sequence number

    SND.NXT = next sequence number to be sent

    SEG.ACK = acknowledgment from the receiving TCP (next sequence
              number expected by the receiving TCP)

    SEG.SEQ = first sequence number of a segment

    SEG.LEN = the number of octets occupied by the data in the segment
              (counting SYN and FIN)

    SEG.SEQ+SEG.LEN-1 = last sequence number of a segment

A new acknowledgment (called an "acceptable ack"), is one for which the inequality below holds:

    SND.UNA < SEG.ACK =< SND.NXT

A segment on the retransmission queue is fully acknowledged if the sum of its sequence number and length is less or equal than the acknowledgment value in the incoming segment.

When data is received the following comparisons are needed:

    RCV.NXT = next sequence number expected on an incoming segments, and
        is the left or lower edge of the receive window

    RCV.NXT+RCV.WND-1 = last sequence number expected on an incoming
        segment, and is the right or upper edge of the receive window

    SEG.SEQ = first sequence number occupied by the incoming segment

    SEG.SEQ+SEG.LEN-1 = last sequence number occupied by the incoming
        segment

A segment is judged to occupy a portion of valid receive sequence space if

    RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

or

    RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND

The first part of this test checks to see if the beginning of the segment falls in the window, the second part of the test checks to see if the end of the segment falls in the window; if the segment passes either part of the test it contains data in the window.

Actually, it is a little more complicated than this. Due to zero windows and zero length segments, we have four cases for the acceptability of an incoming segment:

    Segment Receive  Test
    Length  Window
    ------- -------  -------------------------------------------

       0       0     SEG.SEQ = RCV.NXT

       0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

      >0       0     not acceptable

      >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
                  or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND

Note that when the receive window is zero no segments should be acceptable except ACK segments. Thus, it is be possible for a TCP to maintain a zero receive window while transmitting data and receiving ACKs. However, even when the receive window is zero, a TCP must process the RST and URG fields of all incoming segments.

We have taken advantage of the numbering scheme to protect certain control information as well. This is achieved by implicitly including some control flags in the sequence space so they can be retransmitted and acknowledged without confusion (i.e., one and only one copy of the control will be acted upon). Control information is not physically carried in the segment data space. Consequently, we must adopt rules for implicitly assigning sequence numbers to control. The SYN and FIN are the only controls requiring this protection, and these controls are used only at connection opening and closing. For sequence number purposes, the SYN is considered to occur before the first actual data octet of the segment in which it occurs, while the FIN is considered to occur after the last actual data octet in a segment in which it occurs. The segment length (SEG.LEN) includes both data and sequence space occupying controls. When a SYN is present then SEG.SEQ is the sequence number of the SYN.

Initial Sequence Number Selection

The protocol places no restriction on a particular connection being used over and over again. A connection is defined by a pair of sockets. New instances of a connection will be referred to as incarnations of the connection. The problem that arises from this is -- "how does the TCP identify duplicate segments from previous incarnations of the connection?" This problem becomes apparent if the connection is being opened and closed in quick succession, or if the connection breaks with loss of memory and is then reestablished.

To avoid confusion we must prevent segments from one incarnation of a connection from being used while the same sequence numbers may still be present in the network from an earlier incarnation. We want to assure this, even if a TCP crashes and loses all knowledge of the sequence numbers it has been using. When new connections are created, an initial sequence number (ISN) generator is employed which selects a new 32 bit ISN. The generator is bound to a (possibly fictitious) 32 bit clock whose low order bit is incremented roughly every 4 microseconds. Thus, the ISN cycles approximately every 4.55 hours. Since we assume that segments will stay in the network no more than the Maximum Segment Lifetime (MSL) and that the MSL is less than 4.55 hours we can reasonably assume that ISN's will be unique.

For each connection there is a send sequence number and a receive sequence number. The initial send sequence number (ISS) is chosen by the data sending TCP, and the initial receive sequence number (IRS) is learned during the connection establishing procedure.

For a connection to be established or initialized, the two TCPs must synchronize on each other's initial sequence numbers. This is done in an exchange of connection establishing segments carrying a control bit called "SYN" (for synchronize) and the initial sequence numbers. As a shorthand, segments carrying the SYN bit are also called "SYNs". Hence, the solution requires a suitable mechanism for picking an initial sequence number and a slightly involved handshake to exchange the ISN's.

The synchronization requires each side to send it's own initial sequence number and to receive a confirmation of it in acknowledgment from the other side. Each side must also receive the other side's initial sequence number and send a confirming acknowledgment.

    1) A --> B  SYN my sequence number is X
    2) A <-- B  ACK your sequence number is X
    3) A <-- B  SYN my sequence number is Y
    4) A --> B  ACK your sequence number is Y

Because steps 2 and 3 can be combined in a single message this is called the three way (or three message) handshake.

A three way handshake is necessary because sequence numbers are not tied to a global clock in the network, and TCPs may have different mechanisms for picking the ISN's. The receiver of the first SYN has no way of knowing whether the segment was an old delayed one or not, unless it remembers the last sequence number used on the connection (which is not always possible), and so it must ask the sender to verify this SYN. The three way handshake and the advantages of a clock-driven scheme are discussed in [3].

Knowing When to Keep Quiet

To be sure that a TCP does not create a segment that carries a sequence number which may be duplicated by an old segment remaining in the network, the TCP must keep quiet for a maximum segment lifetime (MSL) before assigning any sequence numbers upon starting up or recovering from a crash in which memory of sequence numbers in use was lost. For this specification the MSL is taken to be 2 minutes. This is an engineering choice, and may be changed if experience indicates it is desirable to do so. Note that if a TCP is reinitialized in some sense, yet retains its memory of sequence numbers in use, then it need not wait at all; it must only be sure to use sequence numbers larger than those recently used.

The TCP Quiet Time Concept

    This specification provides that hosts which "crash" without
    retaining any knowledge of the last sequence numbers transmitted on
    each active (i.e., not closed) connection shall delay emitting any
    TCP segments for at least the agreed Maximum Segment Lifetime (MSL)
    in the internet system of which the host is a part.  In the
    paragraphs below, an explanation for this specification is given.
    TCP implementors may violate the "quiet time" restriction, but only
    at the risk of causing some old data to be accepted as new or new
    data rejected as old duplicated by some receivers in the internet
    system.

    TCPs consume sequence number space each time a segment is formed and
    entered into the network output queue at a source host. The
    duplicate detection and sequencing algorithm in the TCP protocol
    relies on the unique binding of segment data to sequence space to
    the extent that sequence numbers will not cycle through all 2**32
    values before the segment data bound to those sequence numbers has
    been delivered and acknowledged by the receiver and all duplicate
    copies of the segments have "drained" from the internet.  Without
    such an assumption, two distinct TCP segments could conceivably be
    assigned the same or overlapping sequence numbers, causing confusion
    at the receiver as to which data is new and which is old.  Remember
    that each segment is bound to as many consecutive sequence numbers
    as there are octets of data in the segment.

    Under normal conditions, TCPs keep track of the next sequence number
    to emit and the oldest awaiting acknowledgment so as to avoid
    mistakenly using a sequence number over before its first use has
    been acknowledged.  This alone does not guarantee that old duplicate
    data is drained from the net, so the sequence space has been made
    very large to reduce the probability that a wandering duplicate will
    cause trouble upon arrival.  At 2 megabits/sec. it takes 4.5 hours
    to use up 2**32 octets of sequence space.  Since the maximum segment
    lifetime in the net is not likely to exceed a few tens of seconds,
    this is deemed ample protection for foreseeable nets, even if data
    rates escalate to l0's of megabits/sec.  At 100 megabits/sec, the
    cycle time is 5.4 minutes which may be a little short, but still
    within reason.

    The basic duplicate detection and sequencing algorithm in TCP can be
    defeated, however, if a source TCP does not have any memory of the
    sequence numbers it last used on a given connection. For example, if
    the TCP were to start all connections with sequence number 0, then
    upon crashing and restarting, a TCP might re-form an earlier
    connection (possibly after half-open connection resolution) and emit
    packets with sequence numbers identical to or overlapping with
    packets still in the network which were emitted on an earlier
    incarnation of the same connection.  In the absence of knowledge
    about the sequence numbers used on a particular connection, the TCP
    specification recommends that the source delay for MSL seconds
    before emitting segments on the connection, to allow time for
    segments from the earlier connection incarnation to drain from the
    system.

    Even hosts which can remember the time of day and used it to select
    initial sequence number values are not immune from this problem
    (i.e., even if time of day is used to select an initial sequence
    number for each new connection incarnation).

    Suppose, for example, that a connection is opened starting with
    sequence number S.  Suppose that this connection is not used much
    and that eventually the initial sequence number function (ISN(t))
    takes on a value equal to the sequence number, say S1, of the last
    segment sent by this TCP on a particular connection.  Now suppose,
    at this instant, the host crashes, recovers, and establishes a new
    incarnation of the connection. The initial sequence number chosen is
    S1 = ISN(t) -- last used sequence number on old incarnation of
    connection!  If the recovery occurs quickly enough, any old
    duplicates in the net bearing sequence numbers in the neighborhood
    of S1 may arrive and be treated as new packets by the receiver of
    the new incarnation of the connection.

    The problem is that the recovering host may not know for how long it
    crashed nor does it know whether there are still old duplicates in
    the system from earlier connection incarnations.

    One way to deal with this problem is to deliberately delay emitting
    segments for one MSL after recovery from a crash- this is the "quite
    time" specification.  Hosts which prefer to avoid waiting are
    willing to risk possible confusion of old and new packets at a given
    destination may choose not to wait for the "quite time".
    Implementors may provide TCP users with the ability to select on a
    connection by connection basis whether to wait after a crash, or may
    informally implement the "quite time" for all connections.
    Obviously, even where a user selects to "wait," this is not
    necessary after the host has been "up" for at least MSL seconds.

    To summarize: every segment emitted occupies one or more sequence
    numbers in the sequence space, the numbers occupied by a segment are
    "busy" or "in use" until MSL seconds have passed, upon crashing a
    block of space-time is occupied by the octets of the last emitted
    segment, if a new connection is started too soon and uses any of the
    sequence numbers in the space-time footprint of the last segment of
    the previous connection incarnation, there is a potential sequence
    number overlap area which could cause confusion at the receiver.


Next: 3.4 Establishing a connection

Connected: An Internet Encyclopedia
3.3 Sequence Numbers