RFC 1072

TCP extensions for long-delay paths

๐Ÿ“… published October 1988, from ietf

RFC 1072 ๐Ÿ’… TCP Extensions for Long-Delay Paths

Okay bestie, this is RFC 1072, and it's all about making TCP behave on paths that are super long and super fat ๐ŸŒˆ. Here's the title block tea:

  • Authors: V. Jacobson (LBL) and R. Braden (ISI) ๐Ÿ‘‘
  • Date: October 1988 ๐Ÿ“…
  • Status: not proposed as an Internet standard at this time ๐Ÿงช
  • Obsoletes / Updates: none listed in the title block, so this one isn't replacing or patching anything ๐Ÿซถ

Status of This Memo ๐Ÿ“

Okay so this memo is a pitch for a set of TCP extensions that help it run efficiently on a path with a high bandwidth*delay product ๐Ÿฆ‹. Real talk though: these extensions are not being pushed as an Internet standard yet. They're more of a starting point for experimenting and researching transport protocol performance ๐Ÿ”ฌ. Distribution of this memo is unlimited, so share it with everyone ๐Ÿ’–.


1. INTRODUCTION ๐Ÿฆ‹

Recent work on TCP performance has shown that TCP can work well across a huge range of Internet paths, from 800 Mbit/sec I/O channels all the way down to 300 bit/sec dial-up modems [Jacobson88]. Wild range, right? ๐Ÿคฏ But there's still one fundamental bottleneck for one specific situation: paths with high bandwidth and long round-trip delays ๐Ÿข.

The number that really matters here is the product of bandwidth (bits per second) and round-trip delay (RTT in seconds). This product tells you how many bits it takes to "fill the pipe", which is basically the amount of unacknowledged data TCP has to juggle to keep the pipeline full ๐Ÿ“. When that product gets big, say well past 10**5 bits, TCP performance starts to suffer. We'll call an Internet path in this zone a "long, fat pipe", and a network containing that path an "LFN" (pronounced "elephan(t)") ๐Ÿ˜๐Ÿ’œ.

LFNs are everywhere once you look for them. High-capacity packet satellite channels, like DARPA's Wideband Net, are LFNs. A T1-speed satellite channel has a bandwidth*delay product of 10**6 bits or more, which works out to 100 outstanding TCP segments of 1200 bytes each! ๐Ÿ˜ญ And future terrestrial fiber-optical paths will land in the LFN class too. For example, a cross-country delay of 30 ms at a DS3 bandwidth (45Mbps) also goes past 10**6 bits ๐ŸŒธ.

Clever algorithms alone won't get us good TCP performance over LFNs. We actually have to extend the protocol itself โœจ. This RFC proposes a set of TCP extensions to do exactly that.

There are three fundamental problems with the current TCP over LFN paths:

(1) Window Size Limitation

The TCP header uses a 16 bit field to report the receive window size to the sender, so the biggest window you can use is 216 = 65K bytes ๐Ÿงฑ. (In practice, some TCP implementations will "break" for windows bigger than 215, because they don't do unsigned arithmetic. Yikes ๐Ÿ’€.)

To get around this, we propose a new TCP option that allows windows larger than 2**16. This option defines an implicit scale factor. You multiply the window size value found in the TCP header by that factor to get the true window size ๐ŸŽ€.

(2) Cumulative Acknowledgments

Any packet loss in an LFN can wreck your throughput, and TCP's simple cumulative acknowledgment makes it worse ๐Ÿ˜ฉ. When a segment gets lost, the transmitting TCP will (eventually) time out and retransmit the missing segment. The problem is that the sending TCP has no idea which segments already reached the receiver and are just sitting in the queue because they weren't at the left window edge. So it can end up retransmitting those segments for no reason ๐Ÿ™ƒ.

Our fix is a TCP extension for selective acknowledgments. With these, the receiver tells the sender about every segment that arrived successfully, so the sender only retransmits the segments that were actually lost ๐Ÿน.

Selective acknowledgments aren't new, honestly. They've shown up in a bunch of experimental Internet protocols, including VMTP [Cheriton88], NETBLT [Clark87], and RDP [Velten84]. There's also some empirical evidence in their favor: simple RDP experiments showed that turning off the selective acknowledgment facility greatly increases the number of retransmitted segments over a lossy, high-delay Internet path [Partridge87]. A simulation study of a simple form of selective acknowledgments added to the ISO transport protocol TP4 also looked promising for performance [NBS85] ๐Ÿ“ˆ.

(3) Round Trip Timing

TCP handles reliable delivery by measuring the RTT, which is the time between sending a segment and getting an acknowledgment for it. Any segment that isn't acknowledged within some small multiple of the average RTT gets retransmitted โฑ๏ธ. Accurate, current RTT estimates are essential for adapting to changing traffic conditions. Without them, a busy network can fall into an instability known as "congestion collapse" [Nagle84] ๐Ÿ˜ฑ.

Here's the tricky part. TCP segments may be repacketized when they're retransmitted, and the cumulative TCP acknowledgment adds its own complications. Put those together and measuring a segment's RTT can take a non-trivial amount of computation in some implementations ๐Ÿงฎ. To cut down on that work, some implementations only time one segment per window. That's an adequate approximation for small windows, like a 4 to 8 segment Arpanet window. But for an LFN, like a 100 segment Wideband Network window, the RTT estimate ends up being unacceptably poor ๐Ÿ™ˆ.

Errors make everything worse. Zhang [Zhang86], Jain [Jain86], and Karn [Karn87] showed that you can't build reliable RTT estimates if retransmitted segments get included in the estimate ๐Ÿšซ. Once a retransmission happens, a whole window of data has already gone out, so every segment in that window has to be ACKed before the next RTT sample can be taken. That adds at least another window's worth of time between RTT measurements. And as the error rate climbs toward one error per window of data (say, 10**-6 errors per bit for the Wideband Net), getting an RTT measurement becomes effectively impossible ๐Ÿ’€.

So we propose a TCP "echo" option that lets each segment carry its own timestamp ๐Ÿ•ฐ๏ธ. That way every segment, retransmissions included, can be timed at negligible computational cost. Iconic โœจ.

In designing new TCP options, we have to be really careful about interoperating with existing implementations ๐Ÿซฃ. The only TCP option defined so far is an "initial option", meaning it may only appear on a SYN segment. Most implementations will probably just ignore any SYN options they don't understand, so new initial options shouldn't cause a problem. Non-initial options are a different story. We're worried that receiving unexpected ones could crash some TCPs ๐Ÿ˜ญ.

That's why, for each extension we propose, non-initial options may only be sent if an exchange of initial options has shown that both sides understand the extension ๐Ÿค. This approach also lets a TCP figure out, when the connection opens, how big a TCP header it's going to be sending ๐Ÿ“.


2. TCP WINDOW SCALE OPTION ๐ŸŽ€

The obvious way to add a window scale factor would be a new TCP option included in any segment that specifies a window. The receiver would put it in every acknowledgment segment, and the sender would interpret it. Unfortunately, that simple plan doesn't work ๐Ÿ™…โ€โ™€๏ธ. The sender has to reliably know the receiver's current scale factor, but a TCP option in an acknowledgment segment won't be delivered reliably. The only exception is when the ACK happens to be piggy-backed on data.

SYN segments, though, are always sent reliably. So each side can communicate its window scale factor in an initial TCP option ๐Ÿ’ก. There's a catch: the scale has to be set when the connection opens and can't be changed after that. Other alternatives would be way more complicated, though, so we propose a new initial option called Window Scale ๐Ÿงš.

2.1. Window Scale Option โœจ

This three-byte option may be sent in a SYN segment by a TCP to do two things. First, it says the TCP is prepared to do both send and receive window scaling (1). Second, it communicates a scale factor to be applied to its receive window (2) ๐Ÿช„. The scale factor is encoded logarithmically, as a power of 2, which presumably gets implemented with binary shifts ๐Ÿ”ข.

Note: the window in the SYN segment itself is never scaled. ๐Ÿ™…โ€โ™€๏ธ

Here's what the option looks like on the wire:

      TCP Window Scale Option:

      Kind: 3

             +---------+---------+---------+
             | Kind=3  |Length=3 |shift.cnt|
             +---------+---------+---------+

So shift.cnt is the number of bits the receiver right-shifts the true receive-window value, to squish it into a 16-bit value that gets sent in the TCP header. (We'll explain how this scaling works below ๐Ÿ‘€.) The value of shift.cnt can be zero. That's still an offer to scale, just one that applies a scale factor of 1 to the receive window ๐ŸŒˆ.

Important bit, bestie: this option is an offer, not a promise. Both sides have to send Window Scale options in their SYN segments before window scaling is enabled in either direction ๐Ÿซถ๐Ÿ’…

2.2. Using the Window Scale Option ๐ŸŽ€

okay so this is the model implementation for window scaling, and it's written in the notation from RFC-793 [Postel81], so if you know that one you're set ๐Ÿ’…

  • the send-window (SND.WND) and receive-window (RCV.WND) sizes in the connection state block, and in all sequence space calculations, get expanded from 16 to 32 bits ๐Ÿ“ˆ
  • two window shift counts get added to the connection state: snd.scale and rcv.scale ๐Ÿงš. they're the shift counts applied to the incoming and outgoing windows, respectively. the exact algorithm is below
  • every outgoing SYN segment is sent with the Window Scale option, carrying shift.cnt = R, which is the value the TCP would like to use for its receive window ๐Ÿซถ
  • snd.scale and rcv.scale start at zero, and they only change while a received SYN segment is being processed. if that SYN has a Window Scale option with shift.cnt = S, set snd.scale to S and rcv.scale to R. otherwise, both stay at zero ๐Ÿ™ˆ
  • the window field (SEG.WND) in every incoming segment gets left-shifted by snd.scale bits before SND.WND is updated. (this doesn't apply to SYN segments, bestie). it looks like this:
SND.WND = SEG.WND << snd.scale

this assumes the other conditions of RFC793 are met, and it uses the "C" notation "<<" for left-shift โœจ

  • the window field (SEG.WND) of every outgoing segment, again except for SYN segments, has been right-shifted by rcv.scale bits ๐Ÿ’œ
SEG.WND = RCV.WND >> rcv.scale

okay now the math is where it gets spicy ๐ŸŒถ๏ธ TCP decides whether a data segment is "old" or "new" by checking if its sequence number is within 231 bytes of the left edge of the window. if it isn't, the data is "old" and gets thrown out. so new data never gets mistaken for old data (and vice versa), the left edge of the sender's window has to be at least 231 away from the right edge of the receiver's window. same deal for the sender's right edge and the receiver's left edge ๐Ÿ˜ญ

the right and left edges of either window differ by the window size, and the sender and receiver windows can be out of phase by at most the window size. so these constraints mean 2 * the max window size has to be less than 2**31, which works out to:

max window < 2**30

the max window is 2S (where S is the scaling shift count) times at most 216 - 1 (the maximum unscaled window). that means the max window is guaranteed to be < 2*30 if S <= 14. so the shift count has to be limited to 14 ๐Ÿ”ฅ (this allows windows of 2**30 = 1 Gbyte, which is wild). if a Window Scale option comes in with a shift.cnt value bigger than 14, the TCP should log the error but use 14 instead of the value it was given ๐Ÿ“


3. TCP SELECTIVE ACKNOWLEDGMENT OPTIONS ๐Ÿฆ‹

to keep the impact on TCP small, the selective acknowledgment extension uses two brand new TCP options. the first one is an enabling option called "SACK-permitted". it may be sent in a SYN segment to say the SACK option can be used once the connection is up โœจ the other one is the SACK option itself, which may be sent over an established connection once SACK-permitted has given permission ๐ŸŽ€

the SACK option goes in a segment sent from a TCP that's receiving data, to the TCP that's sending that data. we'll call these the data receiver and the data sender, respectively ๐Ÿงš we're only looking at one simplex data flow. any data flowing the other way over the same connection can be treated independently ๐Ÿ’…

3.1. SACK-Permitted Option ๐ŸŒธ

this two-byte option may be sent in a SYN by a TCP that has been extended to receive (and presumably process) the SACK option once the connection has opened. it's giving "I'm ready for SACK" energy ๐Ÿซถ

TCP Sack-Permitted Option:

  • Kind: 4
+---------+---------+
| Kind=4  | Length=2|
+---------+---------+

3.2. SACK Option ๐Ÿ’–

the SACK option is used to convey extended acknowledgment information over an established connection. specifically, a data receiver sends it to tell the data transmitter about non-contiguous blocks of data that have been received and queued. the data receiver is waiting for data in later retransmissions to fill the gaps in sequence space between those blocks. once that happens, the data receiver acknowledges the data normally by advancing the left window edge in the Acknowledgment Number field of the TCP header ๐Ÿ‘‘

it's really important to get this part: the SACK option does NOT change what the Acknowledgment Number field means. its value still specifies the left window edge, which is one byte past the last sequence number of fully-received data. the SACK option is advisory. if it gets ignored, TCP acknowledgments keep working exactly as the protocol specifies โœจ

that said, SACK gives the data transmitter extra info it can use to optimize retransmissions ๐Ÿ”ฅ the TCP data receiver can include the SACK option in an acknowledgment segment whenever it has queued, unacknowledged data. of course, the SACK option may only be sent once the TCP has received the SACK-permitted option in the SYN segment for that connection ๐Ÿ™ˆ

TCP SACK Option:

  • Kind: 5
  • Length: Variable
 +--------+--------+--------+--------+--------+--------+...---+
 | Kind=5 | Length | Relative Origin |   Block Size    |      |
 +--------+--------+--------+--------+--------+--------+...---+

this option has a list of the blocks of contiguous sequence space occupied by data that's been received and queued within the window. each block is contiguous and isolated. that means the octets just below the block:

Acknowledgment Number + Relative Origin -1

and just above the block:

Acknowledgment Number + Relative Origin + Block Size

have NOT been received. (the vibe is "isolated, no neighbors, just vibes" ๐Ÿฆ‹)

each contiguous block of queued data at the receiver is defined in the SACK option by two 16-bit integers:

  • Relative Origin: this is the first sequence number of the block, relative to the Acknowledgment Number field in the TCP header. in other words, relative to the data receiver's left window edge ๐Ÿงš
  • Block Size: this is the size in octets of this block of contiguous data ๐Ÿ“

a SACK option that specifies n blocks has a length of 4*n+2 octets. so the 44 bytes available for TCP options can specify a maximum of 10 blocks ๐Ÿ˜ญ of course, if other TCP options get introduced, they'll compete for those 44 bytes, and the limit of 10 may be reduced in particular segments.

there's no requirement on the order the blocks appear in within a single SACK option. fully allowed, no rules ๐Ÿ’…

Note: requiring that the blocks be ordered would allow a slightly more efficient algorithm in the transmitter. however, this does not seem to be an important optimization. ๐Ÿ™„

3.3. SACK with Window Scaling ๐ŸŒˆ

if window scaling is in effect, then 16 bits may not be enough for the SACK option fields that define the origin and length of a block. there are two possible ways to handle this ๐Ÿค”

  1. expand the SACK origin and length fields to 24 or 32 bits.
  2. scale the SACK fields by the same factor as the window.

the first option would seriously cut down on how many blocks fit in a SACK option. so we went with the second one: scaling the SACK information as well as the window โœจ

scaling the SACK info does introduce some loss of precision. a SACK option has to report queued data blocks whose origins and lengths are multiples of the window scale factor rcv.scale. and those reported blocks must be equal to or smaller than the actual blocks of queued data ๐Ÿซถ

here's the specific deal. say the receiver has a contiguous block of queued data occupying sequence numbers L, L+1, ... L+N-1, and the window scale factor is S = rcv.scale. then the matching block that gets reported in a SACK option will be:

Relative Origin = int((L+S-1)/S)
Block Size = int((L+N)/S) - (Relative Origin)

where the function int(x) returns the greatest integer contained in x ๐Ÿงฎ

the loss of precision isn't a big deal for the sender ๐Ÿ’– if the data-sending TCP keeps track of the boundaries of all segments in its retransmission queue, it will generally be able to infer from the imprecise SACK data which full segments don't need to be retransmitted. this only fails if S is larger than the maximum segment size. in that case, some segments may get retransmitted unnecessarily ๐Ÿ˜ญ

if the sending TCP doesn't keep track of transmitted segment boundaries, the imprecision of the scaled SACK quantities only results in retransmitting a small amount of unneeded sequence space. on average, the data sender will unnecessarily retransmit J*S bytes of sequence space for each SACK received. here J is the number of blocks reported in the SACK, and S = snd.scale ๐Ÿง 

3.4. SACK Option Examples ๐Ÿ“

let's do some examples ๐ŸŽ€ assume the left window edge is 5000, and the data transmitter sends a burst of 8 segments, each carrying 500 data bytes. unless specified otherwise, we assume the scale factor S = 1.

Case 1: The first 4 segments are received but the last 4 are dropped.

the data receiver returns a normal TCP ACK segment acknowledging sequence number 7000, with no SACK option. easy peasy ๐ŸŒธ

Case 2: The first segment is dropped but the remaining 7 are received.

the data receiver returns a TCP ACK segment that acknowledges sequence number 5000 and contains a SACK option specifying one block of queued data:

Relative Origin = 500;  Block Size = 3500

Case 3: The 2nd, 4th, 6th, and 8th (last) segments are dropped.

the data receiver returns a TCP ACK segment that acknowledges sequence number 5500 and contains a SACK option specifying the 3 blocks:

Relative Origin =  500;  Block Size = 500
Relative Origin = 1500;  Block Size = 500
Relative Origin = 2500;  Block Size = 500

Case 4: Same as Case 3, except Scale Factor S = 16.

the SACK option would specify the 3 scaled blocks:

Relative Origin =   32;  Block Size = 30
Relative Origin =   94;  Block Size = 31
Relative Origin =  157;  Block Size = 30

these three reported blocks have sequence numbers 512 through 991, 1504 through 1999, and 2512 through 2992, respectively. ๐Ÿ‘‘๐Ÿซถ

3.5. Generating the SACK Option โœจ

okay so let's say the data receiver keeps a queue of valid segments that it hasn't passed up to the user or acknowledged yet, because some earlier data is still missing ๐Ÿซถ. This queue is ordered by starting sequence number, and making the SACK option only takes one pass down it ๐Ÿ’…. Segments that sit in contiguous sequence space get squished into one SACK block ๐Ÿงฉ. Every gap in the sequence space starts a brand new SACK block, EXCEPT a gap that gets terminated by the right window edge ๐Ÿ™ˆ. If this algorithm ends up with more than 10 blocks, only the first 10 can make it into the option ๐Ÿ’€.

3.6. Interpreting the SACK Option ๐Ÿฆ‹

The data transmitter is assumed to have a retransmission queue full of segments that were sent but not acknowledged yet, in sequence-number order ๐Ÿ“ฆ. If the transmitter does re-packetization before retransmitting, the block boundaries in a SACK option it receives might not land on segment boundaries in that queue. Lowkey, that's not a serious problem for the transmitter ๐Ÿ’โ€โ™€๏ธ.

Let's suppose each segment in the retransmission queue gets a (new) flag bit called ACK'd, which marks that the segment has been entirely acknowledged โœ…. When a segment is first transmitted, it enters the queue with its ACK'd bit off. If the bit gets turned on later (because a SACK option was processed), the transmitter skips that segment in any later retransmission. The segment still isn't dequeued and its buffer isn't freed until the left window edge advances over it ๐Ÿงน.

When an acknowledgment segment with a SACK option arrives, the transmitter turns on the ACK'd bits for the segments that were selectively acknowledged. For each block in the SACK option, it turns on the ACK'd flags for all segments in the retransmission queue that are wholly contained within that block. This only takes straightforward sequence number comparisons, bestie ๐Ÿง โœจ.


4. TCP ECHO OPTIONS ๐Ÿ”

A simple way to measure the RTT of a segment would be this: the sender puts a timestamp in the segment, and the receiver returns that timestamp in the matching ACK segment. When the ACK segment reaches the sender, the difference between the current time and the timestamp is the RTT โฑ๏ธ. To make this timing method work, the receiver just has to reflect or echo selected data (the timestamp) from the sender's segments. This idea is the basis of the "TCP Echo" and "TCP Echo Reply" options ๐Ÿ’–.

4.1. TCP Echo and TCP Echo Reply Options ๐ŸŽ€

TCP Echo Option:

Kind: 6

Length: 6

    +--------+--------+--------+--------+--------+--------+
    | Kind=6 | Length |   4 bytes of info to be echoed    |
    +--------+--------+--------+--------+--------+--------+

This option carries four bytes of information that the receiving TCP may send back in a subsequent TCP Echo Reply option (see below). A TCP may send the TCP Echo option in any segment, but only if a TCP Echo option was received in a SYN segment for the connection ๐Ÿงš.

When the TCP echo option is used for RTT measurement, it will be included in data segments, and the four information bytes will define the time at which the data segment was transmitted, in any format convenient to the sender โฐ.

TCP Echo Reply Option:

Kind: 7

Length: 6

    +--------+--------+--------+--------+--------+--------+
    | Kind=7 | Length |    4 bytes of echoed info         |
    +--------+--------+--------+--------+--------+--------+

A TCP that receives a TCP Echo option containing four information bytes will return these same bytes in a TCP Echo Reply option ๐Ÿชž.

This TCP Echo Reply option must be returned in the next segment (e.g., an ACK segment) that is sent. If more than one Echo option is received before a reply segment is sent, the TCP must choose only one of the options to echo and ignore the others. Specifically, it must choose the newest segment with the oldest sequence number (see next section.) ๐ŸŽฏ

To use the TCP Echo and Echo Reply options, a TCP must send a TCP Echo option in its own SYN segment and receive a TCP Echo option in a SYN segment from the other TCP. A TCP that does not implement the TCP Echo or Echo Reply options must simply ignore any TCP Echo options it receives. However, a TCP should not receive one of these options in a non-SYN segment unless it included a TCP Echo option in its own SYN segment ๐Ÿšซ.

4.2. Using the Echo Options ๐ŸŒธ

If we want to use the Echo/Echo Reply options for RTT measurement, we have to define what the receiver does when there isn't a one-to-one correspondence between data and ACK segments. Assuming we want to minimize the state kept in the receiver (i.e., the number of unprocessed Echo options), we can plan on a receiver remembering the information value from at most one Echo between ACKs. There are three situations to consider ๐Ÿ‘€:

(A) Delayed ACKs.

Many TCPs acknowledge only every Kth segment out of a group of segments arriving within a short time interval. This policy is known generally as "delayed ACK's" ๐Ÿข. The data-sender TCP must measure the effective RTT, including the additional time due to delayed ACK's, or else it will retransmit unnecessarily. Thus, when delayed ACK's are in use, the receiver should reply with the Echo option information from the earliest unacknowledged segment โณ.

(B) A hole in the sequence space (segment(s) have been lost).

The sender will keep sending until the window is filled, and we may be generating ACKs as these out-of-order segments arrive (e.g., for the SACK information or to aid "fast retransmit") ๐Ÿ•ณ๏ธ. An Echo Reply option will tell the sender the RTT of some recently sent segment. Since the ACK can only contain the sequence number of the hole, the sender may not be able to determine which segment it was, but that doesn't matter ๐Ÿคทโ€โ™€๏ธ. If the loss was due to congestion, these RTTs may be particularly valuable to the sender, since they reflect the network characteristics immediately after the congestion ๐ŸŒช๏ธ.

(C) A filled hole in the sequence space.

The segment that fills the hole represents the most recent measurement of the network characteristics ๐Ÿฉน. On the other hand, an RTT computed from an earlier segment would probably include the sender's retransmit time-out, which would badly bias the sender's average RTT estimate ๐Ÿ“‰.

Case (A) suggests the receiver should remember and return the Echo option information from the oldest unacknowledged segment. Cases (B) and (C) suggest that the option should come from the most recent unacknowledged segment. An algorithm that covers all three cases is for the receiver to return the Echo option information from the newest segment with the oldest sequence number, as specified earlier ๐Ÿงฉโœจ.

A model implementation of these options is as follows ๐Ÿ› ๏ธ.

(1) Receiver Implementation

A 32-bit slot for Echo option data, rcv.echodata, is added to the receiver connection state, together with a flag, rcv.echopresent, that indicates whether there is anything in the slot. When the receiver generates a segment, it checks rcv.echopresent and, if it is set, adds an echo-reply option containing rcv.echodata to the outgoing segment, then clears rcv.echopresent ๐Ÿ“ค.

If an incoming segment is in the window and contains an echo option, the receiver checks rcv.echopresent. If it isn't set, the value of the echo option is copied to rcv.echodata and rcv.echopresent is set. If rcv.echopresent is already set, the receiver checks whether the segment is at the left edge of the window. If so, the segment's echo option value is copied to rcv.echodata (this is situation (C) above). Otherwise, the segment's echo option is ignored ๐Ÿ™…โ€โ™€๏ธ.

(2) Sender Implementation

The sender's connection state has a single flag bit, snd.echoallowed, added. If snd.echoallowed is set, or if the segment contains a SYN, the sender is free to add a TCP Echo option (presumably containing the current time in some units convenient to the sender) to every outgoing segment ๐Ÿ•.

Snd.echoallowed should be set if a SYN is received with a TCP Echo option (presumably, a host that implements the option will attempt to use it to time the SYN segment) ๐ŸŽฌ.


5. CONCLUSIONS AND ACKNOWLEDGMENTS ๐Ÿ‘‘

We have proposed five new TCP options for scaled windows, selective acknowledgments, and round-trip timing, in order to provide efficient operation over large-bandwidth*delay-product paths ๐Ÿš€. These extensions are designed to provide compatible interworking with TCPs that do not implement the extensions ๐Ÿซถ.

The Window Scale option was originally suggested by Mike St. Johns of USAF/DCA. The present form of the option was suggested by Mike Karels of UC Berkeley in response to a more cumbersome scheme proposed by Van Jacobson. Gerd Beling of FGAN (West Germany) contributed the initial definition of the SACK option ๐Ÿ™Œ.

All three options have evolved through discussion with the End-to-End Task Force, and the authors are grateful to the other members of the Task Force for their advice and encouragement ๐Ÿ’œ.


6. REFERENCES ๐Ÿ“š

  • [Cheriton88] Cheriton, D., "VMTP: Versatile Message Transaction Protocol", RFC 1045, Stanford University, February 1988.
  • [Jain86] Jain, R., "Divergence of Timeout Algorithms for Packet Retransmissions", Proc. Fifth Phoenix Conf. on Comp. and Comm., Scottsdale, Arizona, March 1986.
  • [Karn87] Karn, P. and C. Partridge, "Estimating Round-Trip Times in Reliable Transport Protocols", Proc. SIGCOMM '87, Stowe, VT, August 1987.
  • [Clark87] Clark, D., Lambert, M., and L. Zhang, "NETBLT: A Bulk Data Transfer Protocol", RFC 998, MIT, March 1987.
  • [Nagle84] Nagle, J., "Congestion Control in IP/TCP Internetworks", RFC 896, FACC, January 1984.
  • [NBS85] Colella, R., Aronoff, R., and K. Mills, "Performance Improvements for ISO Transport", Ninth Data Comm Symposium, published in ACM SIGCOMM Comp Comm Review, vol. 15, no. 5, September 1985.
  • [Partridge87] Partridge, C., "Private Communication", February 1987.
  • [Postel81] Postel, J., "Transmission Control Protocol - DARPA Internet Program Protocol Specification", RFC 793, DARPA, September 1981.
  • [Velten84] Velten, D., Hinden, R., and J. Sax, "Reliable Data Protocol", RFC 908, BBN, July 1984.
  • [Jacobson88] Jacobson, V., "Congestion Avoidance and Control", to be presented at SIGCOMM '88, Stanford, CA., August 1988.
  • [Zhang86] Zhang, L., "Why TCP Timers Don't Work Well", Proc. SIGCOMM '86, Stowe, Vt., August 1986. ๐ŸŽ‰
๐Ÿ“ฆ where this page comes from