RFC 813
Window and Acknowledgement Strategy in TCP
RFC 813 ๐
WINDOW AND ACKNOWLEDGEMENT STRATEGY IN TCP ๐
Written by David D. Clark, MIT Laboratory for Computer Systems and Communications Group, July 1982 ๐ฆ Honestly the header is pretty minimal: it doesn't list a category, a status, or anything it obsoletes or updates, so there's nothing extra to report up here. ๐
1. Introduction โจ
okay bestie, so this doc is all about how to implement two TCP mechanisms: the window and the acknowledgement ๐ง The spec already describes them, but you can follow the spec and still end up with implementations that perform terribly ๐ The good news? The traps in window and ack strategies are super easy to dodge. ๐ธ
Checking performance is way harder than checking correctness, ngl ๐ we've got less experience here, and there's no real formal technique we can lean on. Still, it's important to try writing this stuff down, because different implementors could pick algorithms that look totally reasonable on their own but clash with each other when they meet ๐ญ This doc walks through one particular set of algorithms that have been tested out in the field and seem to play nicely together. ๐ With more experience they might end up as part of the formal spec, but until then, using them is recommended. ๐ซถ
2. The Mechanisms ๐
The acknowledgement mechanism is the core of TCP, and honestly it's the main character ๐ The idea is simple: when data shows up at the recipient, the protocol says the recipient has to send back an acknowledgement for it. Every byte of data gets a sequence number, so the recipient can ack by naming the highest-numbered byte it's received, which also acks all the bytes before it. (Technically it's pointing at the first byte it hasn't gotten yet, but that's a tiny detail ๐) The protocol only says, in general terms, that data should be acked promptly. It doesn't say how fast an ack has to go out, or how much data each ack should cover. ๐
The window mechanism is all about flow control ๐ฆ Whenever it makes sense, the recipient sends the sender a number that's roughly the size of the buffer it currently has free. That number is called the window, and it's the most the sender is allowed to transmit until the receiver sends more window. Sometimes the receiver has zero buffer space, so it returns a window of zero ๐ญ In that situation, the protocol requires the sender to send a small segment every so often to check whether the receiver is accepting data yet. And if the window stays closed at zero for a long stretch and the sender hears nothing back at all, the protocol requires the sender to decide the receiver has died and close the connection. ๐ Again, the spec doesn't say much about performance here: when the window should grow, and how the sender should react to that new info, is left pretty vague.
A badly written window algorithm can tank performance hard. We're talking throughput and CPU use getting hit by several factors of ten, not just a little dip ๐ซ This particular disaster is so specific that it got its own name: Silly Window Syndrome, or SWS ๐คก The happy part is that SWS is easy to avoid if you follow a few simple rules โจ The main job of this memo is to describe SWS so implementors really get what's going on, and to describe the algorithms that stop it from happening. ๐ It also covers performance-boosting algorithms related to acknowledgements, and looks at how ack and window algorithms interact when SWS is involved. ๐ฅ
3. SILLY WINDOW SYNDROME ๐
Before we can understand SWS, we need two new terms, okay? ๐ On the surface the window is super simple: there's a number, called "the window," that goes from the receiver back to the sender. But we need a more precise way to talk about what that number means. The receiver computes a value called the "offered window." In a simple case, the offered window matches the buffer space the receiver has free. That match isn't always exact, but it's a good enough model for what we're about to talk about. ๐ง The offered window is what actually gets sent back to the sender. The sender then uses it to work out a different value, the "usable window," which is the offered window minus the amount of data that's outstanding and unacknowledged. The usable window is always less than or equal to the offered window, and it can be way smaller. ๐ญ
Here's a quick example. The receiver starts out offering a window of 1,000. The sender uses up that whole window by sending five segments of 200 bytes each. When the receiver processes the first of those segments, it sends back an ack that also carries an updated window value. Let's say the receiver has already pulled those first 200 bytes out of its buffer, so it has 1,000 bytes free again. That means it sends back an offered window of 1,000 bytes, same as before. Now the sender gets that first ack and works out how many more bytes it's allowed to send. Here's the catch: out of the 1,000 bytes the recipient is ready to take, 800 are already in transit, sent in response to the previous offered window. So the usable window is only 200 bytes. ๐
Now let's look at how SWS actually starts. Keep going with the same example: at some point the sender has a usable window of 200 bytes, but it only has 50 bytes to send before it hits a "push" point. So it sends those 50 bytes in one segment, and then the other 150 bytes in the next segment. ๐ Later on, that 50-byte segment reaches the recipient, which processes it, removes the 50 bytes, and sends back an offered window of 1,000 bytes again. But the sender now calculates that there are 950 bytes still in transit on the network, so the usable window is down to just 50 bytes. Result? The sender sends another 50-byte segment, even though nothing about the data is forcing a break there anymore. ๐ญ
Honestly, this just keeps going. Every time an ack for a small segment comes back, the usable window it carries makes the sender fire off another segment of that same tiny size, until something weird breaks the pattern ๐ It's easy to see how small segments get started: natural boundaries in the data sometimes make the sender take a usable window and split it between two segments. Once that split happens, there's no natural way for those pieces to get stitched back together, so the usable window keeps getting chopped into little bits. ๐
So SWS is a slow decline in throughput that builds up over time during a long data transfer ๐ If the sender ever stops, say because it's out of data, the receiver will eventually ack all the outstanding data, and then the usable window the sender computes will equal the receiver's full offered window. At that point the situation has healed, and data flows efficiently again. โจ But in large file transfers that never pause, SWS can cause appalling performance ๐ฑ The network between sender and receiver gets clogged with lots of small segments and an equal number of acks, and that leads to lost segments, which sets off massive retransmission. The worst cases ever seen had an average segment size that was one-tenth of what the sender and receiver could actually handle, with an average of five retransmissions for every successful segment sent. ๐ Iconic behavior? Absolutely not.
The good news is SWS is trivial to avoid ๐ซถ The next sections describe two algorithms, one run by the sender and one by the receiver, that appear to wipe out SWS completely. Honestly, either one by itself is enough to stop SWS, which means it can protect your host from a foreign implementation that didn't handle this problem properly ๐ก๏ธ When you run both together, you get an extra cut in CPU consumption, and in practice it's been seen going as high as a factor of four. ๐ฅ
4. Improved Window Algorithms ๐ฆ
The receiver can take a really simple step to kill SWS ๐ When it frees up a small amount of data, it can artificially shrink the offered window in its later acks, so the usable window the sender computes doesn't allow sending any more data. Then, once the receiver has processed a much larger chunk of incoming data, it can lift the artificial limit all at once. That way the sender sees one big jump instead of a bunch of tiny jumps in its usable window. ๐ง
At this level the algorithm is pretty straightforward, but figuring out exactly when to open the window back up means looking at some other implementation details too ๐ค It depends on whether the window is held artificially closed for a short time or a long time, because two different problems can show up. We already covered the first one: never closing the window artificially, which leads straight to SWS. The second one is what happens if the window only opens up every now and then. The data pipeline between sender and receiver might run completely empty while the sender is being held off, so there's a delay before more data shows up. ๐ฉ That delay does hurt throughput, but it doesn't eat up network or CPU resources the way SWS does. So this is the direction you want to overcompensate in โจ For a simple implementation, a rule of thumb that works in practice is to keep artificially shrinking the offered window until the shrinkage adds up to one half of the available space. Then you bump the window back up to advertise the entire space again. ๐ธ Either way, the chunk you open the window by should at least allow one reasonably large segment. (If the receiver is so short on buffers that it can never advertise a buffer big enough for even one large segment, it's hopeless to expect high throughput. ๐)
There's also an algorithm the sender can use to get the same effect, and it's a super simple, elegant rule first described by Michael Greenwald at MIT ๐ The sender takes the offered window and uses it to compute a usable window. Then it compares the usable window to the offered window, and it holds off on sending anything if the ratio of usable to offered is less than a certain fraction. Clearly, if the computed usable window is small compared to the offered window, this
means that a substantial amount of previously sent info is still chilling in the pipeline ๐ฐ from the sender to the receiver, which in turn means that the sender can count on being granted a larger useable window in the future โจ. Until the useable window reaches a certain amount, the sender SHOULD simply refuse to send anything ๐ โโ๏ธ.
Simple experiments suggest that the exact value of the ratio is not very important ๐คทโโ๏ธ, but a value of about 25 percent is sufficient to avoid SWS and achieve reasonable throughput ๐, even for machines with a small offered window. An additional enhancement which might help throughput would be to attempt to hold off sending until one can send a maximum size segment ๐ฆ. Another enhancement would be to send anyway, even if the ratio is small, if the useable window is sufficient to hold the data available up to the next "push point" ๐ธ.
This algorithm at the sender end is very simple ๐ง . Notice that it is not necessary to set a timer to protect against protocol lockup when postponing the send operation โฐ. Further acknowledgements, as they arrive, will inevitably change the ratio of offered to useable window ๐ฆ. (To see this, note that when all the data in the catanet pipeline has arrived at the receiver, the resulting acknowledgement MUST yield an offered window and useable window that equal each other.) If the expected acknowledgements do not arrive, the retransmission mechanism will come into play to assure that something finally happens ๐. Thus, to add this algorithm to an existing TCP implementation usually requires one line of code ๐. As part of the send algorithm it is already necessary to compute the useable window from the offered window. It is a simple matter to add a line of code which, if the ratio is less than a certain percent, sets the useable window to zero ๐ซถ. The results of SWS are so devastating that no sender SHOULD be without this simple piece of insurance ๐ก๏ธ๐ .
5. Improved Acknowledgement Algorithms โจ
In the beginning of this paper, an overly simplistic implementation of TCP was described, which led to SWS ๐. One of the characteristics of this implementation was that the recipient of data sent a separate acknowledgement for every segment that it received. This compulsive acknowledgement was one of the causes of SWS, because each acknowledgement provided some new useable window, but even if one of the algorithms described above is used to eliminate SWS, overly frequent acknowledgement still has a substantial problem ๐ค, which is that it greatly increases the processing time at the sender's end. Measurement of TCP implementations, especially on large operating systems, indicate that most of the overhead of dealing with a segment is not in the processing at the TCP or IP level, but simply in the scheduling of the handler which is REQUIRED to deal with the segment ๐งพ. A steady dribble of acknowledgements causes a high overhead in scheduling, with very little to show for it ๐. This waste is to be avoided if possible โป๏ธ.
There are two reasons for prompt acknowledgement ๐ฏ. One is to prevent retransmission. We will discuss later how to determine whether unnecessary retransmission is occurring. The other reason one acknowledges promptly is to permit further data to be sent. However, the previous section makes quite clear that it is not always desirable to send a little bit of data, even though the receiver may have room for it ๐. Therefore, one can state a general rule that under normal operation, the receiver of data need not, and for efficiency reasons SHOULD NOT, acknowledge the data unless either the acknowledgement is intended to produce an increased useable window, is necessary in order to prevent retransmission or is being sent as part of a reverse direction segment being sent for some other reason. We will consider an algorithm to achieve these goals ๐.
Only the recipient of the data can control the generation of acknowledgements ๐๏ธ. Once an acknowledgement has been sent from the receiver back to the sender, the sender MUST process it. Although the extra overhead is incurred at the sender's end, it is entirely under the receiver's control. Therefore, we MUST now describe an algorithm which occurs at the receiver's end. Obviously, the algorithm MUST have the following general form; sometimes the receiver of data, upon processing a segment, decides not to send an acknowledgement now, but to postpone the acknowledgement until some time in the future, perhaps by setting a timer โฒ๏ธ. The peril of this approach is that on many large operating systems it is extremely costly to respond to a timer event, almost as costly as to respond to an incoming segment ๐ญ. Clearly, if the receiver of the data, in order to avoid extra overhead at the sender end, spends a great deal of time responding to timer interrupts, no overall benefit has been achieved, for efficiency at the sender end is achieved by great thrashing at the receiver end ๐. We MUST find an algorithm that avoids both of these perils ๐ง.
The following scheme seems a good compromise ๐ค. The receiver of data will refrain from sending an acknowledgement under certain circumstances, in which case it MUST set a timer which will cause the acknowledgement to be sent later. However, the receiver SHOULD do this only where it is a reasonable guess that some other event will intervene and prevent the necessity of the timer interrupt ๐ฎ. The most obvious event on which to depend is the arrival of another segment ๐จ. So, if a segment arrives, postpone sending an acknowledgement if both of the following conditions hold. First, the push bit is not set in the segment, since it is a reasonable assumption that there is more data coming in a subsequent segment. Second, there is no revised window information to be sent back ๐ง.
This algorithm will insure that the timer, although set, is seldom used โฑ๏ธ. The interval of the timer is related to the expected inter-segment delay, which is in turn a function of the particular network through which the data is flowing ๐. For the Arpanet, a reasonable interval seems to be 200 to 300 milliseconds ๐. Appendix A describes an adaptive algorithm for measuring this delay ๐.
The section on improved window algorithms described both a receiver algorithm and a sender algorithm, and suggested that both SHOULD be used ๐. The reason for this is now clear ๐ก. While the sender algorithm is extremely simple, and useful as insurance, the receiver algorithm is REQUIRED in order that this improved acknowledgement strategy work ๐ซง. If the receipt of every segment causes a new window value to be returned, then of necessity an acknowledgement will be sent for every data segment. When, according to the strategy of the previous section, the receiver determines to artificially reduce the offered window, that is precisely the circumstance under which an acknowledgement need not be sent ๐. When the receiver window algorithm and the receiver acknowledgement algorithm are used together, it will be seen that sending an acknowledgement will be triggered by one of the following events ๐ฆ. First, a push bit has been received. Second, a temporary pause in the data stream is detected. Third, the offered window has been artificially reduced to one-half its actual value ๐.
In the beginning of this section, it was pointed out that there are two reasons why one MUST acknowledge data ๐ง. Our consideration at this point has been concerned only with the first, that an acknowledgement MUST be returned as part of triggering the sending of new data. It is also necessary to acknowledge whenever the failure to do so would trigger retransmission by the sender. Since the retransmission interval is selected by the sender, the receiver of the data cannot make a precise determination of when the acknowledgement MUST be sent ๐ซ . However, there is a rough rule the sender can use to avoid retransmission, provided that the receiver is reasonably well behaved ๐ฅน.
We will assume that sender of the data uses the optional algorithm described in the TCP specification, in which the roundtrip delay is measured using an exponential decay smoothing algorithm ๐. Retransmission of a segment occurs if the measured delay for that segment exceeds the smoothed average by some factor. To see how retransmission might be triggered, one MUST consider the pattern of segment arrivals at the receiver ๐. The goal of our strategy was that the sender SHOULD send off a number of segments in close sequence, and receive one acknowledgement for the whole burst ๐. The acknowledgement will be generated by the receiver at the time that the last segment in the burst arrives at the receiver. (To ensure the prompt return of the acknowledgement, the sender could turn on the "push" bit in the last segment of the burst.) The delay observed at the sender between the initial transmission of a segment and the receipt of the acknowledgement will include both the network transit time, plus the holding time at the receiver. The holding time will be greatest for the first segments in the burst, and smallest for the last segments in the burst. Thus, the smoothing algorithm will measure a delay which is roughly proportional to the average roundtrip delay for all the segments in the burst ๐ข. Problems will arise if the average delay is substantially smaller than the maximum delay and the smoothing algorithm used has a very small threshold for triggering retransmission ๐ฌ. The widest variation between average and maximum delay will occur when network transit time is negligible, and all delay is processing time. In this case, the maximum will be twice the average (by simple algebra) so the threshold that controls retransmission SHOULD be somewhat more than a factor of two โ๏ธ2๏ธโฃ.
In practice, retransmission of the first segments of a burst has not been a problem because the delay measured consists of the network roundtrip delay, as well as the delay due to withholding the acknowledgement, and the roundtrip tends to dominate except in very low roundtrip time situations (such as when sending to one's self for test purposes) ๐ช. This low roundtrip situation can be covered very simply by including a minimum value below which the roundtrip estimate is not permitted to drop ๐ง.
In our experiments with this algorithm, retransmission due to faulty calculation of the roundtrip delay occurred only once, when the parameters of the exponential smoothing algorithm had been misadjusted so that they were only taking into account the last two or three segments sent ๐. Clearly, this will cause trouble since the last two or three segments of any burst are the ones whose holding time at the receiver is minimal, so the resulting total estimate was much lower than appropriate ๐๐. Once the parameters of the algorithm had been adjusted so that the number of segments taken into account was approximately twice the number of segments in a burst of average size, with a threshold factor of 1.5, no further retransmission has ever been identified due to this problem, including when sending to ourself and when sending over high delay nets ๐โจ.
6. Conservative Vs. Optimistic Windows ๐
According to the TCP specification, the offered window is presumed
to have some relationship to the amount of data the receiver is actually prepared to receive ๐ซถ it's not necessarily an exact match tho. we'll call it a "conservative window" when the offered window is precisely no bigger than the actual buffering available ๐ the drawback? conservative windows can be sooo slow in long delay situations ๐ญ the most a conservative window algorithm can push through is one bufferfull every roundtrip delay in the net, because the next bufferfull can't get launched until the updated window/acknowledgement info from the previous transmission has made the roundtrip. it's giving stuck ๐
in certain cases, you can actually boost the overall throughput by offering a window that's bigger than the buffer the receiver really has ๐ฆ we'll call that an "optimistic window" strategy. it works if the network delivers data slowly enough that the receiver can process it fast enough to keep the buffer from overflowing ๐ธ if the receiver is faster than the sender, you could, with luck, permit an infinitely optimistic window, where the sender is just allowed to send full-speed ๐๏ธ but if the sender is faster than the receiver and the window is too optimistic, some segments will cause a buffer overflow and get discarded ๐ฉ so the correct move with an optimistic window is to increase the window size until segments start to be lost. this only works if you can detect that a segment has been lost ๐ sometimes that's easy, because the segment gets partially processed inside the receiving host before it's thrown away. other times, overflows can clog the network interface, which causes segments to be lost somewhere else in the net ๐ it's inadvisable to try an optimistic window strategy unless you're certain the algorithm can detect the resulting lost segments. BUT the throughput boost from optimistic windows is quite substantial โจ any systems with small buffer space should seriously consider the merit of optimistic windows ๐
the selection of an appropriate window algorithm is honestly more complicated than all that ๐ง the following considerations aren't meant to be built into current TCP implementations. they're background for the sophisticated designer trying to figure out how their TCP will respond to all kinds of networks, with different speed and delay characteristics ๐ the pattern of windows and acknowledgements sent from receiver to sender affects two things about the data being sent. first, they control the average data rate. the sender's average rate can't exceed the receiver's average rate, or long-term buffer overflow will happen ๐จ second, they influence how bursty the data from the sender is. burstiness has both perks and downsides ๐ the perk is that it reduces the CPU processing needed to send the data. this follows from the observed fact, especially on large machines, that most of the cost of sending a segment isn't the TCP or IP processing, but the scheduling overhead of getting started ๐
on the other hand, the downside of burstiness is that it can cause buffers to overflow, either in the eventual recipient (which we talked about above) or in an intermediate gateway, a problem this paper ignores ๐ the algorithms described above try to strike a balance between excessive burstiness, which in extreme cases can cause delays because a burst isn't requested soon enough, and excessive fragmentation of the data stream into small segments, which we identified as Silly Window Syndrome ๐ญ๐ซ
under conditions of extreme delay in the network, none of the algorithms described above will achieve adequate throughput ๐ conservative window algorithms have a predictable throughput limit of one windowfull per roundtrip delay. trying to solve this with optimistic window strategies may cause buffer overflows because the arriving data is so bursty ๐ฆ a very sophisticated way to solve this is for the receiver, having measured the roundtrip delay and intersegment arrival rate of the actual connection by some means, to open its window not in one gigantic optimistic increment, but in a number of smaller optimistic increments. these are carefully spaced using a timer, so the resulting smaller bursts that arrive are each small enough to fit into the existing buffers ๐ง you can picture it as a bunch of requests flowing backwards through the net, which trigger a bunch of bursts that flow back, evenly spaced, from the sender to the receiver ๐ฆ the overall result is that the receiver uses the window mechanism to control the burstiness of the arrivals and the average rate. so iconic ๐
to my knowledge, no such strategy has been implemented in any TCP ๐ซฃ first, we don't normally have delays high enough to need this kind of treatment. second, the strategy described above is probably not stable unless it's very carefully balanced. just like buses on a single bus route tend to bunch up, bursts that start out equally spaced could end up piling into each other and forming the single large burst the receiver was hoping to avoid ๐๐ฅ it's still important to understand this extreme case, though, so we know the limits beyond which TCP, as normally implemented with either conservative or simple optimistic windows, can be expected to deliver throughput that's a reasonable percentage of the actual network capacity ๐
7. Conclusions โจ
this paper describes three simple algorithms for performance enhancement in TCP, one at the sender end and two at the receiver ๐ the sender algorithm is to refrain from sending if the useable window is smaller than 25 percent of the offered window. the receiver algorithms are: first, to artificially reduce the offered window when processing new data if the resulting reduction doesn't represent more than some fraction, say 50 percent, of the actual space available; and second, to refrain from sending an acknowledgment at all if two simple conditions hold ๐ธ
either of these algorithms will prevent the worst aspects of Silly Window Syndrome ๐ and when they're used together, they produce substantial improvement in CPU utilization by eliminating the process of excess acknowledgements ๐ฅ
preliminary experiments with these algorithms suggest that they work, and work very well ๐คฉ both the sender and receiver algorithms have been shown to eliminate SWS, even when talking to fairly silly algorithms at the other end. the Multics mailer, in particular, had suffered substantial attacks of SWS while sending large mail to a number of hosts ๐ญ we believe that implementing the sender side algorithm has eliminated every known case of SWS detected in our mailer ๐ implementing the receiver side algorithm produced substantial improvements in CPU time when Multics was the sending system. Multics is a typical large operating system, with scheduling costs that are large compared to the actual processing time for protocol handlers ๐ฅ๏ธ tests were done sending from Multics to a host that implemented the SWS suppression algorithm, and which could either refrain or not refrain from sending acknowledgements on each segment. as predicted, suppressing the return acknowledgements did not influence the throughput for large data transfer at all, since the throttling effect was elsewhere ๐ง however, the CPU time required to process the data at the Multics end was cut by a factor of four. (in this experiment, the bursts of data being sent were approximately eight segments. thus, the number of acknowledgements in the two experiments differed by a factor of eight.) ๐คโจ
an important consideration in evaluating these algorithms is that they must not cause the protocol implementations to deadlock ๐ฑ all of the recommendations in this document have the characteristic that they suggest one refrain from doing something even though the protocol specification permits one to do it. the possibility exists that if you refrain from doing something now, you may never get to do it later, and both ends will halt, even though it would look superficially like the transaction could continue ๐๐ซ
formally, the idea that things continue to work is referred to as "liveness" ๐ one of the defects of ad hoc solutions to performance problems is the possibility that two different approaches will interact to prevent liveness. it is believed that the algorithms described in this paper are always live, and that's one of the reasons there's a strong advantage in uniform use of this particular proposal, except in cases where it's explicitly demonstrated not to work ๐
the argument for liveness in these solutions goes like this ๐ง first, the sender algorithm can only be stopped by one thing: a refusal of the receiver to acknowledge sent data. as long as the receiver keeps acknowledging data, the ratio of useable window to offered window will approach one, and eventually the sender must continue to send. but notice that the receiver algorithm we've advocated involves refraining from acknowledging. therefore, we certainly do have a situation where improper operation of this algorithm can prevent liveness ๐ฌ
what we have to show is that the receiver of the data, if it chooses to refrain from acknowledging, will do so only for a short time, and not forever ๐ซถ the design of the algorithm described above was intended to achieve exactly this goal: whenever the receiver of data refrained from sending an acknowledgement, it was required to set a timer. the only event permitted to clear that timer is the receipt of another segment, which essentially resets the timer and starts it going again. so an acknowledgement will be sent as soon as no data has been received. this has exactly the effect we want: if the data flow appears to be disrupted for any reason, the receiver responds by sending an up-to-date acknowledgement ๐ in fact, the receiver algorithm is designed to be more robust than this, because transmission of an acknowledgment is triggered by two events: either a cessation of data, or a reduction in the amount of offered window to 50 percent of the actual value. this is the condition that will normally trigger the transmission of this acknowledgement ๐
APPENDIX A ๐
Dynamic Calculation of Acknowledgement Delay ๐ฆ
the text suggested that when setting a timer to postpone the sending of an acknowledgement, a fixed interval of 200 to 300 milliseconds would work properly in practice ๐ฐ๏ธ this hasn't been verified over a wide variety of network delays, and clearly, if there's a very slow net that stretches out the intersegment arrival time, a fixed interval will fail ๐ญ in a sophisticated TCP, which is expected to adjust dynamically (rather than manually) to changing network conditions, it would be appropriate to measure this interval and respond
dynamically, bestie ๐ so the algorithm lives in an Appendix, because it hasn't been tested yet ๐ but it seems sensible โจ
Here's the vibe: whenever a segment shows up without the push bit on, you start a timer ๐ That timer keeps running until the next segment arrives. Then you average all those interarrival intervals with an exponential decay smoothing function ๐ It's tuned to think about maybe the last ten or twenty segments that came in, so it's giving memory without being obsessed with the past ๐
Now, sometimes there's a really long gap even for a segment that doesn't end a pushed piece of data ๐ญ That can happen because a window went to zero, or some glitch in the sender or the network held the data up ๐ So you look at each interarrival interval and toss it out of the smoothing if it's bigger than the current estimate by some amount, maybe a ratio of two or four times ๐ง Rejecting those big gaps means you end up with a smoothed estimate of how fast segments arrive inside a burst ๐ธ
The number doesn't have to be exact ๐ซถ The timer that triggers the acknowledgement can add a pretty generous fudge factor on top without messing up the sender's estimate of the retransmission interval, as long as that fudge factor stays constant โจ It's giving stability, periodt ๐ฅ
๐ฆ where this page comes from
- ietf: rfc813 1982-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms