Summary

  • RFC 3448 let a receiver report arrival rate, loss-event rate and timing evidence, but the sender still calculated a TCP-shaped rate, capped it against the report, paced packets and limited acceleration.
  • Silence was not interpreted as consent: when feedback stopped, TFRC reduced the allowed rate. Neither feedback, a smooth trace nor the equation proved spare capacity, exact fairness or application delivery.

A smoother flow still owed the network a response

Window-based TCP could change its sending rate abruptly. That was tolerable for bulk transfer and awkward for telephony or streaming media, where a large short-term swing could become audible or visible. RFC 3448, published in January 2003 by Mark Handley, Sally Floyd, Jitendra Padhye and Jörg Widmer, specified TCP-Friendly Rate Control as a rate-based alternative for unicast best-effort traffic.

The adjective “friendly” carried a deliberately limited promise. TFRC aimed to be reasonably fair when sharing a path with TCP: its rate should generally remain within a factor of two of a TCP flow under the same conditions. That was not a claim of equal instantaneous throughput, equal queue share or identical application quality. The mechanism pursued smoother motion while retaining a TCP-shaped response to congestion.

It was also not a complete transport. The document did not define reliability or a packet format. TFRC could sit inside a transport such as RTP, an application with its own end-to-end control, or endpoint congestion management. The plain text, RFC Editor record, Datatracker file, history, references, later citations and errata search establish that specification record. They do not prove how any named network used it.

The receiver compressed packet history into an event rate

The receiver saw arrival sequence, loss or ECN marking, and timing. It did not simply divide lost packets by sent packets. TFRC grouped losses that occurred within roughly one round-trip time into one loss event, matching the idea that TCP would normally reduce once for a congestion episode rather than once for every packet in the same window.

That compression mattered. Five nearby losses might become one control event; five widely separated losses might become five. The receiver then calculated weighted inter-loss intervals and inverted their average to obtain the loss-event rate p. History discounting could give a long current interval more influence when conditions improved.

The result was useful precisely because it was not a raw ledger. It encoded a control interpretation of history. It discarded packet-by-packet multiplicity, did not identify the bottleneck, and could not distinguish congestion loss from every other physical cause. RFC 3168 let ECN marking enter the same congestion signal without requiring a dropped packet, but a mark still described a network signal rather than an application outcome.

The receiver also measured its arrival rate X_recv and returned timing material. Its feedback packet was a report: this many bytes arrived over this interval; this is the inferred event rate; this timestamp is being echoed. It was not a reservation, a grant, or a declaration of future capacity.

The sender applied three independent brakes

The sender owned the action. It used the echoed timing information to estimate round-trip time and applied the throughput equation developed in RFC 2915. Packet size, RTT, the loss-event rate and a retransmission-timeout term produced an equation rate, X_calc, intended to approximate a TCP Reno flow.

That number did not flow directly onto the wire. In congestion avoidance, TFRC bounded the sending rate by both X_calc and twice X_recv, while retaining a small floor tied to the maximum backoff interval. The equation asked what a modeled TCP flow might obtain. The receive-rate ceiling asked whether recent delivered traffic supported that ambition. Neither coordinate could authorize the other away.

A third brake governed motion between rates. The sender normally did not more than double its rate in one RTT, and it paced packets instead of releasing an allowed amount as one burst. A receiver report therefore passed through model, recent-arrival ceiling and temporal control before becoming packet transmission.

This separation also limited a dishonest receiver. A receiver that understated loss or overstated its arrival rate could influence the loop, and RFC 3448 discussed that risk. The sender's own equation and increase rules constrained the damage, though they did not turn an untrusted report into verified truth.

Missing feedback caused retreat, not inference

The sharpest evidence boundary appeared when no feedback arrived. The sender did not decide that silence meant a clear path. A no-feedback timer expired after a period related to RTT and the current inter-packet interval. The sender then reduced its permitted rate—commonly by halving the cached receiver rate—and restarted the timer.

Silence was ambiguous. The reverse-path report might have been lost. The forward path might have failed. The receiver might have stopped. The sender might have gone idle. RFC 3448 did not need to diagnose which story was true before choosing a conservative action. It separated safe response from causal certainty.

That choice is easy to overlook because a feedback protocol invites a command metaphor: the receiver “tells” the sender how fast to go. TFRC did something more disciplined. The receiver supplied observations. The sender maintained state and responsibility. When the observation channel failed, responsibility remained with the sender.

The mechanism evolved without becoming a delivery receipt

The surrounding standards clarify the design's scope. RFC 2914 framed congestion control as an Internet stability obligation. RFC 2581 and RFC 3390 supplied contemporary TCP behavior and initial-window context. RFC 3550 supplied the RTP environment in which smoother media transport mattered.

RFC 4342 later carried TFRC into DCCP congestion-control ID 3. RFC 4828 explored a small-packet variant, where fairness in bytes and fairness in packet processing could diverge. RFC 5348 eventually obsoleted RFC 3448 and refined the specification. These documents show revision and reuse; they do not establish universal deployment or measured success.

Most importantly, none of the control receipts reached the application by themselves. A loss-event rate was not a physical diagnosis. X_recv was not capacity. X_calc was not permission. The chosen sending rate was not forwarding. Forwarding was not receipt by a decoder. A smooth graph was not acceptable media.

The ledger had to remain layered

Heng Lu's reality-layer discipline gives this old feedback loop a modern clarity. Packet observations, receiver aggregation, the feedback message, sender calculation, pacing decision, network forwarding and application experience are different records. A system becomes unaccountable when one convenient number is promoted into proof of all the others.

Running-code primacy appears in the refusal to trust a declaration alone. The sender did not merely accept a receiver's symbolic rate; it recomputed, bounded, paced and backed off when evidence stopped. The minimum-initial-specification lens explains the protocol's restraint: specify the congestion-control loop, not a universal packet format, reliability layer or application contract. This is an editorial interpretation, not a claim about the authors' private intent.

RFC 3448's lasting lesson is therefore not one equation. It is an allocation of evidentiary roles. The observer could report. The actor still had to decide safely. No participant could convert yesterday's arrival trace into a right to tomorrow's capacity.

Sources