RFC 700
Protocol experiment
Title Block ๐๐
okay bestie so here's the header info ๐ this is NWG/RFC 700 (also NIC 31020, and it's INWG Experiments Note 1) from August 1974 โจ the title is A Protocol Experiment ๐ง and the authors are Eric R. Mader, William W. Plummer, and Raymond S. Tomlinson ๐ซถ the header doesn't list a category, a status, or anything it obsoletes or updates, so there's nothing to report there ๐
I. Introduction ๐ธ
okay so in early February 1974 the main line printer on BBN's TENEX system died ๐ and the team was like "fine, we'll use the PDP-11 line printer over the ARPANET instead" ๐จ๏ธ and it had a double purpose ๐ they wanted the actual listings AND they wanted to study network protocols, so it was giving multitasking energy from day one ๐ฅ
II. The Basic Protocol ๐ฆ
this one is built on the protocol Cerf and Kahn described in INWG Note #39 ๐ you're expected to already know that doc, so this is just a quick sketch ๐ also heads up, not every feature in this section actually got implemented, so check out Section VI for the details ๐
okay so at any moment the sender has two pointers into the stream of bytes it's sending ๐ฏโโ๏ธ bytes to the left of the LEFT pointer have already been sent AND acknowledged โ the bytes sitting in the "window" between LEFT and RIGHT have been sent (zero or more times) but no success signal has come back yet ๐ฅบ and bytes to the right of RIGHT are still waiting their turn in the future ๐
in operation the sender keeps on sending bytes from the input stream, so RIGHT keeps advancing ๐โโ๏ธ and positive acknowledgements from the receiver push the LEFT edge of the window toward the RIGHT edge ๐
LEFT and RIGHT are actually numerical byte positions in the data stream ๐ข the low order 16 bits of RIGHT get sent with every message as a sequence number, so the receiver can tell which part of the stream it's getting even when messages show up out of order ๐ the receiver only has a finite amount of buffer space to rebuild an image of the transmitter's window ๐งฉ and it throws away any message whose sequence number is outside its buffer area ๐๏ธ BUT messages to the left of LEFT must still be acknowledged even though they're discarded ๐ญ otherwise a lost ACK would make the sender keep retransmitting a message the receiver keeps ignoring, forever and ever ๐ messages with bad checksums get tossed too ๐ซ
as "good" messages come in, the holes in the receiver's buffer get filled ๐ฉน and the continuous segments on the left edge get passed to the physical line printer (in our case) ๐จ๏ธ the receiver tells the sender what's up by sending an ACK (acknowledgement) message โ๏ธ that ACK specifies the sequence number of the byte it'd like to receive next (which becomes the new value of LEFT in the sender) AND the amount of buffer space it currently has free (which becomes the new maximum window width in the sender) ๐ the sender ignores ACKs to the left of LEFT and to the right of RIGHT ๐ โโ๏ธ so the sender and receiver are both ready to handle multiple copies of the same messages ๐ซถ
now the failures ๐ messages with bad checksums, messages lost in transit (data AND ACKs), and messages thrown out for sequence numbers that looked out of range all look exactly the same to the sender: a dropped ACK โ a dropped ACK makes the sender's LEFT edge stop advancing, so the unacknowledged message just sits at the left of the sender's window, and there might be a matching hole at the left of the receiver's image of the window ๐ณ๏ธ eventually transmission stops, and a (10 second) timeout goes off in the sender, which retransmits everything in the window ๐ and here's the tea โ at the instant of a timeout there's no guarantee the un-ACK'd message is exactly at the left edge, or that it's the only unacknowledged message in the window ๐คทโโ๏ธ retransmissions will probably make the receiver see stuff it's already seen, but duplicates get discarded thanks to sequence number checks ๐งน
III. "Say Again" ๐ฃ๏ธ
okay this one's an extension to the INWN #39 protocol that actually got implemented ๐ the receiver can force a retransmission of the entire window by switching on a flag in any message it sends back to the sender ๐ฉ this is super useful when the receiver thinks a data message got dropped and wants a redo right away instead of waiting around for the sender's timeout ๐โโ๏ธ but it only works if the network keeps messages in order ๐ฌ and it's not great if the error rate is high, because you'd be resending the whole window just to recover one or two messages ๐ฉ
IV. Establishing an Association ๐ค
in the experiment, two flags were used to set up an association ๐ FRST (FiRST flag) was the equivalent of SYN from INWG Note #39 โจ it marks the first message of an association, and it tells the receiver to accept the sequence number in that message as the starting point for sequence numbers for the association ๐ฑ
the second flag is HUH, a receiver-to-sender flag ๐โโ๏ธ it's the receiver asking the sender to define the sequence numbers ๐ข when the sender gets a message with a HUH in it, it responds by switching on FRST in the next data message ๐ซถ normally HUH only gets sent if the receiver has been restarted, or if it's replying to messages on a port it knows isn't part of an association ๐ช
V. A Problem ๐ฌ
okay so this is a severe problem the team found while working on association setup ๐จ if the PDP-11 (receiver) got reloaded while the spooler (sender) was running, the first few pages of the data stream got printed about six times before normal operation kicked in ๐ here's how it happened:
- The sender would be stuck in a loop, timing out and retransmitting because the receiver hadn't responded.
- When the receiver restarted, it would see a whole window's worth of messages and reply to each one with a HUH.
- For each HUH, the sender would reset the window and include a FRST flag with the first message in each of the (six) retransmissions.
- The receiver would see the first message of the first retransmission containing a FRST, accept the sequence number, and print the data from that message and the ones after it. Then another message containing the FRST flag would show up and the cycle would repeat (five more times). Note that the ACKs generated in the repetitions were ignored by the sender because they were to the left of the window. ๐๐
the "cure" they tried first was changing the receiver program so that after sending a HUH, it ignores messages until one with a FRST flag shows up ๐ฉน but this is NOT a real solution in general ๐ โโ๏ธ because if either the message containing the HUH or the response gets lost in transmission, the receiver port is useless ๐ they used a timeout to guard against that, but the timeout can't be trusted, because it might cause two messages with FRST flags to be received, which is literally the exact problem they were trying to avoid ๐คฆโโ๏ธ
there's an alternate cure that doesn't depend on the network being lossless ๐ the sender would respond to a HUH by ignoring all messages for at least a round trip delay time before sending its response containing the FRST flag โณ the catch is you'd have to define what that time is ๐ค and in general this can't be done when messages can get trapped for indefinite amounts of time in network partitions ๐งฑ this will be discussed more fully in a subsequent document ๐
VI. Features not Investigated ๐
none of the programs so far have supported any of these features ๐
- Window size control. The window size was a constant (2048 bytes). In a future experiment the window size will be varied not only by indications of buffer space in the receiver, but also as a function of estimated transit time. (see below). ๐
- Reassembly. Since reassembly is conceptually easy, it is likely to be one of the first extensions. A message corrupter will be included in the receiver to test the functioning of the reassembly mechanism. ๐งช
- Expanded Internetwork Addresses
- Multiple Associations
- Reliable Making and Breaking of Associations
VII. Implementations Notes ๐ ๏ธ
the sender is about ten pages of assembly code for the network message interface ๐ it has two processes: one fills a buffer by reading the input data stream, and the other sends network messages from the buffer and processes replies from the receiver ๐ the two are joined by a coroutine mechanism, but in the future they'll be two parallel TENEX processes ๐ง
the receiver program is about four pages of BCPL code, plus IO device drivers and routines that implement the queueing primitives ๐
each message holds between zero and 255 bytes of data, arranged (as a coding convenience) in a way that's directly compatible with the BCPL string handling routines ๐งต messages carry a single byte of checksum, which is the low eight bits of the twos complement negation of the twos complement sum of all the other bytes in the message ๐ข the authors recommend that some more reliable checksum function get used in the future ๐ they say even eight-bit ones complement arithmetic would be better โจ
source files for the various programs are available from the authors at Bolt Beranek and Newman, 50 Moulton Street, Cambridge Mass., 02138 ๐ฌ
VIII. Simple Rate Calculations ๐งฎ
okay math time, but make it cute ๐ if we assume an active association has reached steady state, that processing delays are lumped into the transit time T, and that there are no errors, then we can calculate the maximum data rate like this ๐ฆ
say the sequence numbers passed by the RIGHT pointer are some function of time, R(t) ๐ฐ๏ธ messages the receiver gets are the same function of time, just delayed by T (a transit time) seconds ๐ since processing time is zero, the acknowledgments carry this same function, R(t-T) โ๏ธ and the acknowledgements the sender receives have sequence numbers R(t-2T) ๐
L(t) = R(t-2T)
L(t) = R(t) - W
the acknowledgements at the sender set the LEFT pointer, L(t) ๐ฏ and R(t) is ahead of L(t) by the width of the window, which is a constant in steady state ๐ so we get the two relations above ๐
now let R(t) = Bt, which means the sequence numbers increase linearly with time ๐
R(t) = Bt
(microscopically, short bursts alternate with longer periods of inactivity, but the average bandwidth is still B ๐) under those assumptions the bandwidth comes out to:
B = W/2T
so the bandwidth in bytes per second is just the steady state window width divided by the round trip delay time ๐ and going the other way, that same relation can determine the buffer size needed ๐งฉ for the receiver to guarantee it accepts information that was transmitted, it has to supply buffering equal to (or greater than) the window size ๐ก๏ธ the window size has to be equal to or greater than the desired bandwidth times the round-trip delay time, which means it equals the number of messages in a round-trip "pipeline" ๐ฐ
the bandwidth in the presence of a relatively low error rate can also be calculated ๐ assume B and W are expressed in terms of (full) messages rather than byte numbers ๐ฆ each error has two effects: a timeout delay of D seconds, and retransmission of W messages ๐ญ so the time
๐ to be continued! part 2 is coming with the rest of the maths and everything after it ๐ง
Okay so Q(M,N) is basically the total time it takes to send M messages when N of them get messed up ๐ญ It's three things added together: the time to send everything once, N*D seconds of timeout waiting, and the time to resend the window N more times ๐
Q(M,N) = (2T/W)*M + N*D + N*2T
Next we divide by M to get the time per message, and multiply the last term by (W/W), which is just 1, bestie ๐ง
Q(M,N)/M = (2T/W) + (N/M)*D + (2T/W)*(N/M)*W .
And (M/N) is just the fraction of messages in error, so we call it E ๐ฆ
Q(E) = (2T/W)*(1 + EW) + ED
B(E) = 1/[(2T/W)(1+EW) + ED]
Now the "say again" mechanism (see Section III.) is literally the main character here โจ It forces D to be zero, which means you still get a reasonable average data rate even when errors are happening. Iconic, honestly ๐
Let's look at an example. Say you've got a network with an E of 0.01, W is 20 messages, and T is 0.5 second. A 10 second timeout gives you B(D=10) = 6.7, but with forced retransmission, B(D=0) = 20. That's a huge glow-up ๐ธ๐ฅ
IX. A Sequence Number Consideration ๐
Okay, sequence numbers have to be big enough to reject duplicate messages ๐ The rule is that it must be impossible to cycle through more than half the sequence number space during a message's lifetime, even at the maximum transmission rate ๐ญ
Let's do the math. If we assume a 1 MegaByte per second network and a maximum lifetime of 500 seconds, the sequence number field of each message has to be able to hold the number 2*500*10**6. That's 10**9, or about 2**30 ๐คฏ So a 32-bit (4-byte) sequence number field is recommended. Periodt ๐
X. Additional Control Functions ๐ง
Okay so when someone tries to establish an association by sending a SYN, the receiver should be able to deny the attempt with a RELease. There are three ways to do it ๐
REJECT. (I'm busy. Try again later.)
ABORT. (I don't understand what you are sending.
(Bad port, etc.))
ABNORMAL (SYN arrived on a established connection.)
(Receiver breaks connection and issues this REL.)
And once an association is already up, the sender can RELease it in either of these ways ๐
DONE. (I'm done sending to you.)
GAG. (Stop. You are sending garbage (ACK's).)
Last thing, and it's a vibe: these can be coded as combinations of bits in the FLAGS, which are convenient for programming ๐ซถโจ
๐ฆ where this page comes from
- ietf: rfc700 1974-08
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms