RFC 2883

An Extension to the Selective Acknowledgement (SACK) Option for TCP

๐Ÿ“… published July 2000, from ietf

RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP ๐Ÿ’–

okay bestie, this one is from the Network Working Group ๐ŸŽ€ and it's a Standards Track doc, which means it's a real protocol spec people are supposed to actually implement ๐Ÿ’… It's dated July 2000 ๐ŸŒธ

The authors are S. Floyd (ACIRI), J. Mahdavi (Novell), M. Mathis (Pittsburgh Supercomputing Center), and M. Podolsky (UC Berkeley) ๐Ÿซถ

The title block doesn't list anything this RFC obsoletes or updates. What it does do is extend RFC 2018, which the Abstract explains in detail โœจ


Status of this Memo ๐Ÿ“œ

Okay so this doc specifies an Internet standards track protocol for the whole Internet community, and it's literally asking everyone to discuss it and send in suggestions ๐Ÿ’ฌ For the standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“– Distribution of this memo is unlimited ๐Ÿฆ‹

Copyright (C) The Internet Society (2000). All Rights Reserved.

Abstract ๐ŸŒˆ

So this note extends the Selective Acknowledgement (SACK) Option from [RFC2018] for TCP ๐Ÿ”ฅ RFC 2018 explained how to use the SACK option to acknowledge out-of-sequence data that isn't covered by TCP's cumulative acknowledgement field. This note takes it further by saying how to use SACK to acknowledge duplicate packets ๐Ÿ™ˆ

The idea is that when duplicate packets show up, the first block of the SACK option field can report the sequence numbers of the packet that triggered the acknowledgement โœจ That lets the TCP sender figure out the order its packets arrived in at the receiver, so it can tell when it retransmitted a packet for no reason ๐Ÿงš The sender can then use that info to be more robust when packets get reordered [BPS99], when ACKs get lost, when packets get replicated, and/or when early retransmit timeouts happen ๐Ÿ‘‘

1. Conventions and Acronyms ๐ŸŽ€

The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this document, are to be interpreted as described in [B97] ๐Ÿ’…

2. Introduction ๐Ÿฆ‹

Okay so the Selective Acknowledgement (SACK) option from RFC 2018 is what the TCP data receiver uses to acknowledge non-contiguous blocks of data that the Cumulative Acknowledgement field doesn't cover ๐ŸŒธ The thing is, RFC 2018 doesn't say anything about using the SACK option when duplicate segments arrive ๐Ÿ™ƒ This note fills that gap and specifies using SACK when acknowledging the receipt of a duplicate packet [F99]. We call a SACK block that reports a duplicate segment a D-SACK (for duplicate-SACK) block ๐Ÿ’–

This document doesn't change how TCP uses the cumulative acknowledgement field, and it doesn't change the TCP receiver's decision of when to send an acknowledgement packet โœจ It's only about what goes inside the SACK option when an acknowledgement is sent ๐Ÿซถ

This extension is compatible with current implementations of the SACK option in TCP ๐ŸŽ€ Like, if one TCP end-node doesn't implement this D-SACK extension and the other one does, we believe that the D-SACK use on one end won't cause problems ๐Ÿ’…

Also, using D-SACK doesn't need separate negotiation between a TCP sender and receiver that have already negotiated SACK capability ๐ŸŒˆ That means the TCP receiver could send D-SACK blocks even when the TCP sender doesn't understand this SACK extension. In that case the sender just throws away any D-SACK blocks and processes the other SACK blocks in the SACK option field like it normally would ๐Ÿงš

3. The Sack Option Format as defined in RFC 2018 ๐Ÿ“

Here's the SACK option format from RFC 2018 ๐Ÿ‘‘

                            +--------+--------+
                            | Kind=5 | Length |
          +--------+--------+--------+--------+
          |      Left Edge of 1st Block       |
          +--------+--------+--------+--------+
          |      Right Edge of 1st Block      |
          +--------+--------+--------+--------+
          |                                   |
          /            . . .                  /
          |                                   |
          +--------+--------+--------+--------+
          |      Left Edge of nth Block       |
          +--------+--------+--------+--------+
          |      Right Edge of nth Block      |
          +--------+--------+--------+--------+

So the SACK option in the TCP header holds a bunch of SACK blocks, and each block marks the left and right edge of a stretch of data the TCP receiver got ๐Ÿ’– A block is a contiguous sequence space of data that's been received and queued at the receiver. The "left edge" is the first sequence number in the block, and the "right edge" is the sequence number right after the block's last one โœจ

RFC 2018 implies that the first SACK block should describe the segment that triggered the acknowledgement ๐Ÿ”ฅ RFC 2018 says that when the data receiver chooses to send a SACK option, "the first SACK block ... MUST specify the contiguous block of data containing the segment which triggered this ACK, unless that segment advanced the Acknowledgment Number field in the header."

RFC 2018 doesn't cover what happens with the SACK option when a duplicate segment gets acknowledged, though ๐Ÿ™ˆ For example, RFC 2018 says that "each block represents received bytes of data that are contiguous and isolated". It also says that "if sent at all, SACK options SHOULD be included in all ACKs which do not ACK the highest sequence number in the data receiver's queue." What it doesn't specify is using the SACK option when a duplicate segment comes in and the cumulative acknowledgement field in the ACK already acknowledges all the data in the data receiver's queue ๐Ÿ’€

4. Use of the SACK option for reporting a duplicate segment ๐Ÿ’…

This section explains how SACK blocks get used when the SACK option is reporting a duplicate segment ๐ŸŽ€ When D-SACK is used, the first block of the SACK option should be a D-SACK block that gives the sequence numbers for the duplicate segment that triggered the acknowledgement ๐ŸŒธ If that duplicate segment is part of a bigger block of non-contiguous data in the receiver's data queue, the following SACK block should be used to specify that bigger block ๐Ÿงš Extra SACK blocks can be used to specify additional non-contiguous blocks of data, as RFC 2018 specifies โœจ

Here are the guidelines for reporting duplicate segments, summed up ๐Ÿฆ‹

(1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by the receiver in the most recent packet.

(2) Each duplicate contiguous sequence of data received is reported in at most one D-SACK block. (I.e., the receiver sends two identical D-SACK blocks in subsequent packets only if the receiver receives two duplicate segments.) ๐Ÿ’œ

(3) The left edge of the D-SACK block specifies the first sequence number of the duplicate contiguous sequence, and the right edge of the D-SACK block specifies the sequence number immediately following the last sequence in the duplicate contiguous sequence.

(4) If the D-SACK block reports a duplicate contiguous sequence from a (possibly larger) block of data in the receiver's data queue above the cumulative acknowledgement, then the second SACK block in that SACK option should specify that (possibly larger) block of data. ๐Ÿ‘‘

(5) Following the SACK blocks described above for reporting duplicate segments, additional SACK blocks can be used for reporting additional blocks of data, as specified in RFC 2018.

Heads up though, because each duplicate segment only gets reported in one ACK packet, info about that duplicate segment is lost if that ACK packet gets dropped in the network ๐Ÿ˜ญ

4.1. Reporting Full Duplicate Segments ๐ŸŒˆ

We're going to show these guidelines with three examples โœจ In each example, we assume the data receiver has already received eight segments of 500 bytes each, and has sent an acknowledgement with the cumulative acknowledgement field set to 4000 (assuming the first sequence number is zero) ๐Ÿซถ The D-SACK block is underlined in each example ๐Ÿ”ฅ

4.1.1. Example 1: Reporting a duplicate segment. ๐Ÿงš

Several ACK packets get lost, so the data sender retransmits packet 3000-3499, and the data receiver then gets a duplicate segment with sequence numbers 3000-3499 ๐Ÿ’… The receiver sends an acknowledgement with the cumulative acknowledgement field set to 4000, and the first D-SACK block specifying sequence numbers 3000-3500 ๐ŸŽ€

        Transmitted    Received    ACK Sent
        Segment        Segment     (Including SACK Blocks)

        3000-3499      3000-3499   3500 (ACK dropped)
        3500-3999      3500-3999   4000 (ACK dropped)
        3000-3499      3000-3499   4000, SACK=3000-3500
                                              ---------

4.1.2. Example 2: Reporting an out-of-order segment and a duplicate segment. ๐ŸŒธ

Okay so after a lost data packet, the receiver gets an out-of-order data segment, and that triggers the SACK option as RFC 2018 specifies ๐Ÿฆ‹ Because several ACK packets were lost, the sender then retransmits a data packet ๐Ÿ™ƒ The receiver gets the duplicate packet and reports it in the first D-SACK block ๐Ÿ’–

        Transmitted    Received    ACK Sent
        Segment        Segment     (Including SACK Blocks)

        3000-3499      3000-3499   3500 (ACK dropped)
        3500-3999      3500-3999   4000 (ACK dropped)
        4000-4499      (data packet dropped)
        4500-4999      4500-4999   4000, SACK=4500-5000 (ACK dropped)
        3000-3499      3000-3499   4000, SACK=3000-3500, 4500-5000
                                                 ---------

4.1.3. Example 3: Reporting a duplicate of an out-of-order segment. ๐Ÿ‘‘

Because of a lost data packet, the receiver gets two out-of-order segments ๐Ÿ˜ญ Then the receiver gets a duplicate segment for one of those out-of-order segments ๐Ÿ’…

        Transmitted    Received    ACK Sent
        Segment        Segment     (Including SACK Blocks)

        3500-3999      3500-3999   4000
        4000-4499      (data packet dropped)
        4500-4999      4500-4999   4000, SACK=4500-5000
        5000-5499      5000-5499   4000, SACK=4500-5500
                       (duplicated packet)
                       5000-5499   4000, SACK=5000-5500, 4500-5500
                                              ---------

4.2. Reporting Partial Duplicate Segments โœจ

okay so it's totally possible for a sender to send a packet where only part of it already reached the receiver ๐Ÿ‘€ like some of the bytes are repeats and some are brand new. this can happen when the sender's segments get bigger, which can happen when the PMTU increases in the middle of a TCP session, for example ๐Ÿฆ‹ the rules from Section 4 above apply to partial duplicates too, not just full ones. this section gives examples of how those rules work for partial duplicates ๐Ÿ’…

when the SACK option is used for reporting partial duplicate segments, the first D-SACK block reports the first duplicate sub-segment ๐ŸŽ€ and if the data packet being acknowledged has multiple partial duplicate sub-segments, only that first duplicate sub-segment gets reported in the SACK option. we'll show you how with the examples below ๐Ÿ’–

4.2.1. Example 4: Reporting a single duplicate subsegment.

the sender bumps the packet size from 500 bytes up to 1000 bytes ๐Ÿ“ˆ then the receiver gets a 1000-byte packet that has one 500-byte subsegment it already got and one it hasn't. the receiver only reports the one it already has, using a single D-SACK block ๐ŸŒธ

        Transmitted    Received    ACK Sent
        Segment        Segment     (Including SACK Blocks)

        500-999        500-999     1000
        1000-1499      (delayed)
        1500-1999      (data packet dropped)
        2000-2499      2000-2499   1000, SACK=2000-2500
        1000-2000      1000-1499   1500, SACK=2000-2500
                       1000-2000   2500, SACK=1000-1500
                                              ---------

4.2.2. Example 5: Two non-contiguous duplicate subsegments covered by

the cumulative acknowledgement.

so after the sender goes from 500 bytes up to 1500 bytes ๐Ÿš€ the receiver gets a packet with two non-contiguous duplicate 500-byte subsegments that both sit below the cumulative acknowledgement field ๐Ÿ˜ญ the receiver reports the first of those duplicates in one D-SACK block. iconic behavior tbh ๐Ÿ‘‘

         Transmitted    Received    ACK Sent
         Segment        Segment     (Including SACK Blocks)

         500-999        500-999     1000
         1000-1499      (delayed)
         1500-1999      (data packet dropped)
         2000-2499      (delayed)
         2500-2999      (data packet dropped)
         3000-3499      3000-3499   1000, SACK=3000-3500
         1000-2499      1000-1499   1500, SACK=3000-3500
                        2000-2499   1500, SACK=2000-2500, 3000-3500
                        1000-2499   2500, SACK=1000-1500, 3000-3500
                                               ---------

4.2.3. Example 6: Two non-contiguous duplicate subsegments not covered

by the cumulative acknowledgement.

this one is basically Example 5 but flipped ๐Ÿ™ƒ after the sender bumps the packet size, the receiver gets a packet with two non-contiguous duplicate subsegments that sit above the cumulative acknowledgement field instead of below it. the first D-SACK block reports the first duplicate subsegment ๐Ÿงš then the second, regular SACK block reports the bigger chunk of non-contiguous data that duplicate belongs to. the whole thing is giving organized ๐Ÿ“

         Transmitted    Received    ACK Sent
         Segment        Segment     (Including SACK Blocks)

         500-999        500-999     1000
         1000-1499      (data packet dropped)
         1500-1999      (delayed)
         2000-2499      (data packet dropped)
         2500-2999      (delayed)
         3000-3499      (data packet dropped)
         3500-3999      3500-3999   1000, SACK=3500-4000
         1000-1499      (data packet dropped)
         1500-2999      1500-1999   1000, SACK=1500-2000, 3500-4000
                        2000-2499   1000, SACK=2000-2500, 1500-2000,
                                            3500-4000
                        1500-2999   1000, SACK=1500-2000, 1500-3000,
                                               ---------
                                            3500-4000

4.3. Interaction Between D-SACK and PAWS ๐ŸŽ€

okay this part is about how D-SACK plays with PAWS ๐Ÿค“ RFC 1323 [RFC1323] specifies an algorithm for Protection Against Wrapped Sequence Numbers (PAWS). PAWS helps tell apart sequence numbers for new data from sequence numbers left over from a previous cycle through the sequence number space ๐Ÿ” duplicate segments might get flagged by PAWS as belonging to one of those previous cycles.

RFC 1323 says that for those packets, the receiver should do the following:

   Send an acknowledgement in reply as specified in RFC 793 page 69,
   and drop the segment.

since PAWS still requires sending an ACK, there's no harmful interaction between PAWS and D-SACK โœจ the D-SACK block can go in the SACK option of the ACK, as outlined in Section 4, no matter whether the TCP receiver is using PAWS, and no matter what PAWS decided about whether the data segment was valid or invalid ๐Ÿ’…

TCP senders that get D-SACK blocks should keep in mind that a segment reported as a duplicate could possibly have come from a prior cycle through the sequence number space ๐ŸŒˆ this is true no matter whether the TCP data receiver uses PAWS. we don't expect this to cause big problems for senders using D-SACK information ๐Ÿซถ

5. Detection of Duplicate Packets ๐Ÿ”

this extension to the SACK option lets the receiver accurately report when it receives duplicate data ๐Ÿ™Œ but since each duplicate packet is only reported in one ACK packet, losing a single ACK means the sender might never hear about it ๐Ÿ˜ญ also, the sender can not necessarily trust the receiver to send it accurate information [SCWA99]. receiver trust issues, we've all been there ๐Ÿ’€

so the sender can check whether the first (D)SACK block of an acknowledgement really acknowledges duplicate data, it should compare the sequence space in the first SACK block to the cumulative ACK which is carried IN THE SAME PACKET ๐Ÿง if the SACK sequence space is less than that cumulative ACK, it's a sign that the segment identified by the SACK block was received more than once by the receiver. an implementation MUST NOT compare the sequence space in the SACK block to the TCP state variable snd.una (which carries the total cumulative ACK), because that can lead to the wrong conclusion if ACK packets get reordered ๐Ÿ™…โ€โ™€๏ธ

if the sequence space in the first SACK block is greater than the cumulative ACK, then the sender next compares the sequence space in the first SACK block with the sequence space in the second SACK block, if there is one โœจ this comparison can tell whether the first SACK block is reporting duplicate data that sits above the cumulative ACK.

TCP implementations that follow RFC 2581 [RFC2581] could see duplicate packets in each of the following four situations ๐Ÿฆ‹ this document does not specify what action a TCP implementation should take in these cases. the extension to the SACK option just lets the sender detect each of these cases. these four conditions aren't an exhaustive list of every possible duplicate packet case ๐ŸŒธ they're the most common and likely ones. later documents will describe experimental proposals for how senders could respond when they detect unnecessary retransmits caused by reordering, lost ACKs, or early retransmit timeouts ๐Ÿ”ฎ

5.1. Replication by the network ๐Ÿชž

if a packet gets replicated in the network, this extension to the SACK option can spot it โœจ for example:

         Transmitted    Received    ACK Sent
         Segment        Segment     (Including SACK Blocks)

         500-999        500-999     1000
         1000-1499      1000-1499   1500
                        (replicated)
                        1000-1499   1500, SACK=1000-1500
                                               ---------

in this case, the second packet was replicated in the network ๐Ÿ‘ฏ an ACK with a D-SACK block that's lower than its ACK field, and that isn't identical to a previously retransmitted segment, is a sign of replication by the network ๐Ÿšจ

WITHOUT D-SACK: if D-SACK isn't used and the last ACK was piggybacked on a data packet, the sender would have no idea that a packet got replicated in the network ๐Ÿ˜ฑ if D-SACK isn't used and neither of the last two ACKs was piggybacked on a data packet, the sender could reasonably guess that either some data packet or the final ACK packet got replicated in the network. getting a D-SACK packet gives the sender positive knowledge that this data packet was replicated in the network (assuming the receiver isn't lying ๐Ÿคฅ).

RESEARCH ISSUES: the current SACK option already lets the sender identify duplicate ACKs that don't acknowledge new data ๐Ÿงช but the D-SACK option gives the sender a much stronger basis for figuring out that a duplicate ACK doesn't acknowledge new data. knowing that lets the sender skip using those duplicate ACKs to infer packet loss (like Fast Retransmit) or to send more data (like Fast Recovery) ๐Ÿ’œ

5.2. False retransmit due to reordering ๐Ÿ”€

Okay so, if packets get reordered in the network so a segment arrives more than 3 packets out of order, TCP's Fast Retransmit algorithm will retransmit the out-of-order packet ๐Ÿ˜ญ Here's how the drama plays out:

             Transmitted    Received    ACK Sent
             Segment        Segment     (Including SACK Blocks)

             500-999        500-999     1000
             1000-1499      (delayed)
             1500-1999      1500-1999   1000, SACK=1500-2000
             2000-2499      2000-2499   1000, SACK=1500-2500
             2500-2999      2500-2999   1000, SACK=1500-3000
             1000-1499      1000-1499   3000
                            1000-1499   3000, SACK=1000-1500
                                                   ---------

So here's the tea: an ACK with a SACK block that's lower than its ACK field and identical to a previously retransmitted segment is a big sign of serious reordering followed by a false (unnecessary) retransmission. It's giving "I was never lost, I was just late" ๐Ÿ’…

WITHOUT D-SACK:

With D-SACK in the mix (like we saw above), the sender knows that either the first transmission of segment 1000-1499 was just delayed in the network, or the first transmission got dropped and the second transmission got duplicated. Since no other segments were duplicated in the network, that second option is pretty unlikely ๐Ÿ™ˆ

If we didn't have D-SACK, the sender would only know that either the first transmission of segment 1000-1499 was delayed, or that one of the data segments or the final ACK got duplicated in the network. So D-SACK is the main character here, because it lets the sender way more reliably figure out that the first transmission of segment 1000-1499 was NOT dropped โœจ

[AP99], [L99], and [LK00] point out that the sender could unambiguously detect an unnecessary retransmit by using the timestamp option. [LK00] proposes a timestamp-based algorithm that minimizes the penalty for an unnecessary retransmit. [AP99] proposes a heuristic for detecting an unnecessary retransmit in an environment with neither timestamps nor SACK. [L99] also proposes a two-bit field as an alternative to the timestamp option for unambiguously marking the first three retransmissions of a packet. A similar idea was proposed in [ISO8073] ๐ŸŽ€

RESEARCH ISSUES:

D-SACK lets the sender detect some cases (for example, when no ACK packets have been lost) where a Fast Retransmit happened because of packet reordering instead of packet loss. That means the TCP sender can adjust the duplicate acknowledgment threshold so these unnecessary Fast Retransmits don't keep happening ๐Ÿ”ฅ Also, when the sender figures out after the fact that it made an unnecessary window reduction, it has the option of "undoing" that reduction in the congestion window. It does this by resetting ssthresh to the value of the old congestion window, then slow-starting until the congestion window gets back to that point. Redemption arc, honestly ๐Ÿ‘‘

Any proposal for "undoing" a reduction in the congestion window would have to deal with the possibility that the TCP receiver could be lying in its reports of received packets [SCWA99]. Nobody's perfect, bestie ๐Ÿ™ƒ


5.3. Retransmit Timeout Due to ACK Loss ๐Ÿซ 

If an entire window of ACKs gets lost, a timeout will result. Check out this example:

             Transmitted    Received    ACK Sent
             Segment        Segment     (Including SACK Blocks)

             500-999        500-999     1000 (ACK dropped)
             1000-1499      1000-1499   1500 (ACK dropped)
             1500-1999      1500-1999   2000 (ACK dropped)
             2000-2499      2000-2499   2500 (ACK dropped)
             (timeout)
             500-999        500-999     2500, SACK=500-1000
                                                   --------

In this case, all of the ACKs get dropped, which leads to a timeout ๐Ÿ’€ You can spot this situation because the first ACK received after the timeout carries a D-SACK block saying duplicate data was received. Iconic detective work ๐Ÿ•ต๏ธโ€โ™€๏ธ

WITHOUT D-SACK:

Without D-SACK, the sender in this case would be unable to decide that no data packets were dropped. Major mystery energy ngl ๐ŸŒธ

RESEARCH ISSUES:

For a TCP that implements some form of ACK congestion control [BPK97], being able to tell apart dropped data packets from dropped ACK packets would be super useful. In that case, the connection could run congestion control for the return (ACK) path separately from the congestion control on the forward (data) path. Separate lanes, separate vibes ๐Ÿฆ‹


5.4. Early Retransmit Timeout โฐ

If the sender's RTO is too short, an early retransmission timeout can happen even when no packets were actually dropped in the network. Here's what that looks like:

             Transmitted    Received    ACK Sent
             Segment        Segment     (Including SACK Blocks)

             500-999        (delayed)
             1000-1499      (delayed)
             1500-1999      (delayed)
             2000-2499      (delayed)
             (timeout)
             500-999        (delayed)
                            500-999     1000
             1000-1499      (delayed)
                            1000-1499   1500
             ...
                            1500-1999   2000
                            2000-2499   2500
                            500-999     2500, SACK=500-1000
                                                   --------
                            1000-1499   2500, SACK=1000-1500
                                                   ---------
                            ...

So in this case, the first packet gets retransmitted after the timeout. Then the original window of packets shows up at the receiver, and ACKs go out for those segments. After that, the retransmissions arrive, and the ACKs carrying SACK blocks identify them as duplicate segments. Plot twist, but make it make sense ๐ŸŽญ

You can tell this is an early retransmission timeout because the ACK for byte 1000 arrives after the timeout with no SACK information, followed by an ACK carrying SACK information (500-999) that shows the retransmitted segment had already been received โœจ

WITHOUT D-SACK:

If D-SACK wasn't used and one of the duplicate ACKs got piggybacked on a data packet, the sender wouldn't know how many duplicate packets had been received. If D-SACK wasn't used and none of the duplicate ACKs were piggybacked on a data packet, then the sender would have sent N duplicate packets, for some N, and received N duplicate ACKs. In that situation, the sender could reasonably infer that some data or ACK packet had been replicated in the network, or that an early retransmission timeout had happened (or that the receiver is lying) ๐Ÿ™ˆ

RESEARCH ISSUES:

After the sender determines that an unnecessary (i.e., early) retransmit timeout happened, it could adjust the parameters used for setting the RTO, so it doesn't keep having unnecessary retransmit timeouts. Coupled with this, when the sender figures out after the fact that it made an unnecessary window reduction, it has the option of "undoing" that reduction in the congestion window ๐Ÿงš


6. Security Considerations ๐Ÿ”

This document neither strengthens nor weakens TCP's current security properties. Nothing gets better, nothing gets worse, we just keep it moving ๐Ÿ’…

7. Acknowledgements ๐Ÿซถ

We would like to thank Mark Handley, Reiner Ludwig, and Venkat Padmanabhan for conversations on these issues, and to thank Mark Allman for helpful feedback on this document. Shoutout to the whole crew ๐Ÿ’–

8. References ๐Ÿ“š

[AP99] Mark Allman and Vern Paxson, On Estimating End-to-End Network Path Properties, SIGCOMM 99, August 1999. URL "http://www.acm.org/sigcomm/sigcomm99/papers/session7-3.html".

[BPS99] J.C.R. Bennett, C. Partridge, and N. Shectman, Packet Reordering is Not Pathological Network Behavior, IEEE/ACM Transactions on Networking, Vol. 7, No. 6, December 1999, pp. 789-798.

[BPK97] Hari Balakrishnan, Venkata Padmanabhan, and Randy H. Katz, The Effects of Asymmetry on TCP Performance, Third ACM/IEEE Mobicom Conference, Budapest, Hungary, Sep 1997. URL "http://www.cs.berkeley.edu/~padmanab/index.html#Publications".

[F99] Floyd, S., Re: TCP and out-of-order delivery, Message ID <199902030027.QAA06775@owl.ee.lbl.gov> to the end-to-end-interest mailing list, February 1999. URL "http://www.aciri.org/floyd/notes/TCP_Feb99.email".

[ISO8073] ISO/IEC, Information-processing systems - Open Systems Interconnection - Connection Oriented Transport Protocol Specification, Internation Standard ISO/IEC 8073, December 1988.

[L99] Reiner Ludwig, A Case for Flow Adaptive Wireless links, Technical Report UCB//CSD-99-1053, May 1999. URL "http://iceberg.cs.berkeley.edu/papers/Ludwig-FlowAdaptive/".

[LK00] Reiner Ludwig and Randy H. Katz, The Eifel Algorithm: Making TCP Robust Against Spurious Retransmissions, SIGCOMM Computer Communication Review, V. 30, N. 1, January 2000. URL "http://www.acm.org/sigcomm/ccr/archive/ccr-toc/ccr-toc-2000.html".

[RFC1323] Jacobson, V., Braden, R. and D. Borman, "TCP Extensions for High Performance", RFC 1323, May 1992.

[RFC2018] Mathis, M., Mahdavi, J., Floyd, S. and A. Romanow, "TCP Selective Acknowledgement Options", RFC 2018, April 1996.

[RFC2581] Allman, M., Paxson,V. and W. Stevens, "TCP Congestion Control", RFC 2581, April 1999.

[SCWA99] Stefan Savage, Neal Cardwell, David Wetherall, Tom Anderson, TCP Congestion Control with a Misbehaving Receiver, ACM Computer Communications Review, pp. 71-78, V. 29, N. 5, October, 1999. URL "http://www.acm.org/sigcomm/ccr/archive/ccr-toc/ccr-toc-99.html".

Authors' Addresses ๐ŸŽ€

Sally Floyd AT&T Center for Internet Research at ICSI (ACIRI)

Phone: +1 510-666-6989 EMail: floyd@aciri.org URL: http://www.aciri.org/floyd/

Jamshid Mahdavi Novell

Phone: 1-408-967-3806 EMail: mahdavi@novell.com

Matt Mathis Pittsburgh Supercomputing Center

Phone: 412 268-3319 EMail: mathis@psc.edu URL: http://www.psc.edu/~mathis/

Matthew Podolsky UC Berkeley Electrical Engineering & Computer Science Dept.

Phone: 510-649-8914 EMail: podolsky@eecs.berkeley.edu URL: http://www.eecs.berkeley.edu/~podolsky

Okay so bestie, this part is the legal stuff, but it's still giving clear and organized vibes ๐Ÿ’…

Copyright (C) The Internet Society (2000). All Rights Reserved. ๐ŸŒธ

You are allowed to copy this document and share it with others. You can also make derivative works that comment on it, explain it, or help people implement it, and publish and distribute those works, in whole or in part, with no restrictions of any kind ๐Ÿฆ‹. The only catch is that the above copyright notice and this paragraph have to be included on every copy and every derivative work.

The document itself is a different story. It may not be modified in any way. You can't remove the copyright notice or the references to the Internet Society or other Internet organizations. The exceptions are when it's needed for developing Internet standards, in which case the copyright procedures in the Internet Standards process must be followed, and when it's translated into a language other than English ๐ŸŒˆ

The permissions here are perpetual, which means they won't be revoked by the Internet Society or its successors or assigns ๐Ÿ’œ

This document and the information in it are provided on an "AS IS" basis, and the disclaimer below covers everything:

THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐Ÿ™ˆ

Acknowledgement ๐Ÿซถ

Funding for the RFC Editor function is currently provided by the Internet Society. ๐ŸŽ€ Thank you to them for keeping these documents coming, bestie. โœจ

๐Ÿ“ฆ where this page comes from