Network Working Group S. Floyd Request for Comments: 5348 ICIR Obsoletes: 3448 M. Handley Updates: 4342 University College London J. Padhye Microsoft J. Widmer DoCoMo September 2008 TCP Friendly Rate Control (TFRC): Protocol Specification Status of This Memo This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.Abstract
This document specifies TCP Friendly Rate Control (TFRC). TFRC is a congestion control mechanism for unicast flows operating in a best- effort Internet environment. It is reasonably fair when competing for bandwidth with TCP flows, but has a much lower variation of throughput over time compared with TCP, making it more suitable for applications such as streaming media where a relatively smooth sending rate is of importance. This document obsoletes RFC 3448 and updates RFC 4342.Table of Contents
1. Introduction ....................................................3 2. Conventions .....................................................4 3. Protocol Mechanism ..............................................4 3.1. TCP Throughput Equation ....................................5 3.2. Packet Contents ............................................7 3.2.1. Data Packets ........................................7 3.2.2. Feedback Packets ....................................8 4. Data Sender Protocol ............................................8 4.1. Measuring the Segment Size .................................9 4.2. Sender Initialization .....................................10 4.3. Sender Behavior When a Feedback Packet Is Received ........10 4.4. Expiration of Nofeedback Timer ............................15 4.5. Reducing Oscillations .....................................17
4.6. Scheduling of Packet Transmissions ........................18 5. Calculation of the Loss Event Rate (p) .........................19 5.1. Detection of Lost or Marked Packets .......................19 5.2. Translation from Loss History to Loss Events ..............20 5.3. The Size of a Loss Interval ...............................22 5.4. Average Loss Interval .....................................22 5.5. History Discounting .......................................24 6. Data Receiver Protocol .........................................26 6.1. Receiver Behavior When a Data Packet Is Received ..........27 6.2. Expiration of Feedback Timer ..............................27 6.3. Receiver Initialization ...................................28 6.3.1. Initializing the Loss History after the First Loss Event ...................................29 7. Sender-Based Variants ..........................................30 8. Implementation Issues ..........................................31 8.1. Computing the Throughput Equation .........................31 8.2. Sender Behavior When a Feedback Packet Is Received ........32 8.2.1. Determining If an Interval Was a Data-Limited Interval ..............................32 8.2.2. Maintaining X_recv_set .............................34 8.3. Sending Packets before Their Nominal Send Time ............34 8.4. Calculation of the Average Loss Interval ..................36 8.5. The Optional History Discounting Mechanism ................36 9. Changes from RFC 3448 ..........................................36 9.1. Overview of Changes .......................................36 9.2. Changes in Each Section ...................................37 10. Security Considerations .......................................39 10.1. Security Considerations for TFRC in DCCP .................40 11. Acknowledgments ...............................................40 Appendix A. Terminology ...........................................41 Appendix B. The Initial Value of the Nofeedback Timer .............43 Appendix C. Response to Idle or Data-Limited Periods ..............44 C.1. Long Idle or Data-Limited Periods ........................45 C.2. Short Idle or Data-Limited Periods .......................48 C.3. Moderate Idle or Data-Limited Periods ....................49 C.4. Losses During Data-Limited Periods .......................50 C.5. Other Patterns ...........................................53 C.6. Evaluating TFRC's Response to Idle Periods ...............53 References ........................................................54 Normative References ...........................................54 Informative References .........................................54
1. Introduction
This document specifies TCP Friendly Rate Control (TFRC). TFRC is a congestion control mechanism designed for unicast flows operating in an Internet environment and competing with TCP traffic [FHPW00]. Instead of specifying a complete protocol, this document simply specifies a congestion control mechanism that could be used in a transport protocol such as DCCP (Datagram Congestion Control Protocol) [RFC4340], in an application incorporating end-to-end congestion control at the application level, or in the context of endpoint congestion management [BRS99]. This document does not discuss packet formats or reliability. Implementation-related issues are discussed only briefly, in Section 8. TFRC is designed to be reasonably fair when competing for bandwidth with TCP flows, where we call a flow "reasonably fair" if its sending rate is generally within a factor of two of the sending rate of a TCP flow under the same conditions. However, TFRC has a much lower variation of throughput over time compared with TCP, which makes it more suitable for applications such as telephony or streaming media where a relatively smooth sending rate is of importance. The penalty of having smoother throughput than TCP while competing fairly for bandwidth is that TFRC responds slower than TCP to changes in available bandwidth. Thus, TFRC should only be used when the application has a requirement for smooth throughput, in particular, avoiding TCP's halving of the sending rate in response to a single packet drop. For applications that simply need to transfer as much data as possible in as short a time as possible, we recommend using TCP, or if reliability is not required, using an Additive-Increase, Multiplicative-Decrease (AIMD) congestion control scheme with similar parameters to those used by TCP. TFRC is designed for best performance with applications that use a fixed segment size, and vary their sending rate in packets per second in response to congestion. TFRC can also be used, perhaps with less optimal performance, with applications that do not have a fixed segment size, but where the segment size varies according to the needs of the application (e.g., video applications). Some applications (e.g., some audio applications) require a fixed interval of time between packets and vary their segment size instead of their packet rate in response to congestion. The congestion control mechanism in this document is not designed for those applications; TFRC-SP (Small-Packet TFRC) is a variant of TFRC for applications that have a fixed sending rate in packets per second but either use small packets or vary their packet size in response to congestion. TFRC-SP is specified in a separate document [RFC4828].
This document specifies TFRC as a receiver-based mechanism, with the calculation of the congestion control information (i.e., the loss event rate) in the data receiver rather in the data sender. This is well-suited to an application where the sender is a large server handling many concurrent connections, and the receiver has more memory and CPU cycles available for computation. In addition, a receiver-based mechanism is more suitable as a building block for multicast congestion control. However, it is also possible to implement TFRC in sender-based variants, as allowed in DCCP's Congestion Control ID 3 (CCID 3) [RFC4342]. This document obsoletes RFC 3448. In the transport protocol DCCP (Datagram Congestion Control Protocol) [RFC4340], the Congestion Control ID Profiles CCID-3 [RFC4342] and CCID-4 [CCID-4] both specify the use of TFRC from RFC 3448. CCID-3 and CCID-4 implementations SHOULD use this document instead of RFC 3448 for the specification of TFRC. The normative specification of TFRC is in Sections 3-6. Section 7 discusses sender-based variants, Section 8 discusses implementation issues, and Section 9 gives a non-normative overview of differences with RFC 3448.2. Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. Appendix A gives a list of technical terms used in this document.3. Protocol Mechanism
For its congestion control mechanism, TFRC directly uses a throughput equation for the allowed sending rate as a function of the loss event rate and round-trip time. In order to compete fairly with TCP, TFRC uses the TCP throughput equation, which roughly describes TCP's sending rate as a function of the loss event rate, round-trip time, and segment size. We define a loss event as one or more lost or marked packets from a window of data, where a marked packet refers to a congestion indication from Explicit Congestion Notification (ECN) [RFC3168]. Generally speaking, TFRC's congestion control mechanism works as follows: o The receiver measures the loss event rate and feeds this information back to the sender.
o The sender also uses these feedback messages to measure the round-trip time (RTT). o The loss event rate and RTT are then fed into TFRC's throughput equation, and the resulting sending rate is limited to at most twice the receive rate to give the allowed transmit rate X. o The sender then adjusts its transmit rate to match the allowed transmit rate X. The dynamics of TFRC are sensitive to how the measurements are performed and applied. We recommend specific mechanisms below to perform and apply these measurements. Other mechanisms are possible, but it is important to understand how the interactions between mechanisms affect the dynamics of TFRC.3.1. TCP Throughput Equation
Any realistic equation giving TCP throughput as a function of loss event rate and RTT should be suitable for use in TFRC. However, we note that the TCP throughput equation used must reflect TCP's retransmit timeout behavior, as this dominates TCP throughput at higher loss rates. We also note that the assumptions implicit in the throughput equation about the loss event rate parameter have to be a reasonable match to how the loss rate or loss event rate is actually measured. While this match is not perfect for the throughput equation and loss rate measurement mechanisms given below, in practice the assumptions turn out to be close enough. The throughput equation currently REQUIRED for TFRC is a slightly simplified version of the throughput equation for Reno TCP from [PFTK98]. Ideally, we would prefer a throughput equation based on selective acknowledgment (SACK) TCP, but no one has yet derived the throughput equation for SACK TCP, and simulations and experiments suggest that the differences between the two equations would be relatively minor [FF99] (Appendix B). The throughput equation for X_Bps, TCP's average sending rate in bytes per second, is: s X_Bps = ---------------------------------------------------------- R*sqrt(2*b*p/3) + (t_RTO * (3*sqrt(3*b*p/8)*p*(1+32*p^2))) Where: X_Bps is TCP's average transmit rate in bytes per second. (X_Bps is the same as X_calc in RFC 3448.)
s is the segment size in bytes (excluding IP and transport protocol headers). R is the round-trip time in seconds. p is the loss event rate, between 0 and 1.0, of the number of loss events as a fraction of the number of packets transmitted. t_RTO is the TCP retransmission timeout value in seconds. b is the maximum number of packets acknowledged by a single TCP acknowledgement. Setting the TCP retransmission timeout value t_RTO: Implementations SHOULD set t_RTO = 4*R. Implementations MAY choose to implement a more accurate calculation of t_RTO. Implementations MAY also set t_RTO to max(4*R, one second), to match the recommended minimum of one second on the RTO [RFC2988]. Setting the parameter b for delayed acknowledgements: Some current TCP connections use delayed acknowledgements, sending an acknowledgement for every two data packets received. However, TCP is also allowed to send an acknowledgement for every data packet. For the revised TCP congestion control mechanisms, [RFC2581bis] currently specifies that the delayed acknowledgement algorithm should be used with TCP. However, [RFC2581bis] recommends increasing the congestion window during congestion avoidance by one segment per RTT even in the face of delayed acknowledgements, consistent with a TCP throughput equation with b = 1. On an experimental basis, [RFC2581bis] allows for increases of the congestion window during slow-start that are also consistent with a TCP throughput equation with b = 1. Thus, the use of b = 1 is consistent with [RFC2581bis]. The use of b = 1 is RECOMMENDED. With t_RTO=4*R and b=1, the throughput equation for X_Bps, the TCP sending rate in bytes per second, can be simplified as: s X_Bps = ----------------------------------------------- R * (sqrt(2*p/3) + 12*sqrt(3*p/8)*p*(1+32*p^2)) In the future, updates to this document could specify different TCP equations to be substituted for this equation. The requirement is that the throughput equation be a reasonable approximation of the sending rate of TCP for conformant TCP congestion control.
The throughput equation can also be expressed in terms of X_pps, the sending rate in packets per second, with X_pps = X_Bps / s . The parameters s (segment size), p (loss event rate), and R (RTT) need to be measured or calculated by a TFRC implementation. The measurement of s is specified in Section 4.1, the measurement of R is specified in Section 4.3, and the measurement of p is specified in Section 5. In the rest of this document, data rates are measured in bytes per second unless otherwise specified.3.2. Packet Contents
Before specifying the sender and receiver functionality, we describe the contents of the data packets sent by the sender and feedback packets sent by the receiver. As TFRC will be used along with a transport protocol, we do not specify packet formats, as these depend on the details of the transport protocol used.3.2.1. Data Packets
Each data packet sent by the data sender contains the following information: o A sequence number. This number MUST be incremented by one for each data packet transmitted. The field must be sufficiently large that it does not wrap causing two different packets with the same sequence number to be in the receiver's recent packet history at the same time. o A timestamp indicating when the packet is sent. We denote by ts_i the timestamp of the packet with sequence number i. The resolution of the timestamp SHOULD typically be measured in milliseconds. This timestamp is used by the receiver to determine which losses belong to the same loss event. The timestamp is also echoed by the receiver to enable the sender to estimate the round-trip time, for senders that do not save timestamps of transmitted data packets. We note that, as an alternative to a timestamp incremented in milliseconds, a "timestamp" that increments every quarter of a round-trip time MAY be used for determining when losses belong to the same loss event, in the context of a protocol where this is understood by both sender and receiver and where the sender saves the timestamps of transmitted data packets.
o The sender's current estimate of the round-trip time. The estimate reported in packet i is denoted by R_i. The round-trip time estimate is used by the receiver, along with the timestamp, to determine when multiple losses belong to the same loss event. The round-trip time estimate is also used by the receiver to determine the interval to use for calculating the receive rate and to determine when to send feedback packets. If the sender sends a coarse-grained "timestamp" that increments every quarter of a round-trip time, as discussed above, then the sender is not required to send its current estimate of the round trip time.3.2.2. Feedback Packets
Each feedback packet sent by the data receiver contains the following information: o The timestamp of the last data packet received. We denote this by t_recvdata. If the last packet received at the receiver has sequence number i, then t_recvdata = ts_i. This timestamp is used by the sender to estimate the round-trip time, and is only needed if the sender does not save the timestamps of transmitted data packets. o The amount of time elapsed between the receipt of the last data packet at the receiver and the generation of this feedback report. We denote this by t_delay. o The rate at which the receiver estimates that data was received in the previous round-trip time. We denote this by X_recv. o The receiver's current estimate of the loss event rate p.4. Data Sender Protocol
The data sender sends a stream of data packets to the data receiver at a controlled rate. When a feedback packet is received from the data receiver, the data sender changes its sending rate based on the information contained in the feedback report. If the sender does not receive a feedback report for four round-trip times, then the sender cuts its sending rate in half. This is achieved by means of a timer called the nofeedback timer.
We specify the sender-side protocol in the following steps: o Measurement of the mean segment size being sent. o Sender initialization. o The sender behavior when a feedback packet is received. o The sender behavior when the nofeedback timer expires. o Oscillation prevention (optional). o Scheduling of packet transmission and allowed burstiness.4.1. Measuring the Segment Size
The TFRC sender uses the segment size, s, in the throughput equation, in the setting of the maximum receive rate, the setting of the minimum and initial sending rates, and the setting of the nofeedback timer. The TFRC receiver MAY use the average segment size, s, in initializing the loss history after the first loss event. As specified in Section 6.3.1, if the TFRC receiver does not know the segment size, s, used by the sender, the TFRC receiver MAY instead use the arrival rate in packets per second in initializing the loss history. The segment size is normally known to an application. This may not be so in two cases: 1) The segment size naturally varies depending on the data. In this case, although the segment size varies, that variation is not coupled to the transmit rate. The TFRC sender can either compute the average segment size or use the maximum segment size for the segment size, s. 2) The application needs to change the segment size rather than the number of segments per second to perform congestion control. This would normally be the case with packet audio applications where a fixed interval of time needs to be represented by each packet. Such applications need to have a completely different way of measuring parameters. For the first class of applications where the segment size varies depending on the data, the sender SHOULD estimate the segment size, s, as the average segment size over the last four loss intervals. The sender MAY estimate the average segment size over longer time intervals, if so desired.
The second class of applications are discussed separately in a separate document on TFRC-SP [RFC4828]. For the remainder of this section we assume the sender can estimate the segment size and that congestion control is performed by adjusting the number of packets sent per second.4.2. Sender Initialization
The initial values for X (the allowed sending rate in bytes per second) and tld (the Time Last Doubled during slow-start, in seconds) are undefined until they are set as described below. If the sender is ready to send data when it does not yet have a round-trip sample, the value of X is set to s bytes per second, for segment size s, the nofeedback timer is set to expire after two seconds, and tld is set to 0 (or to -1, either one is okay). Upon receiving the first round-trip time measurement (e.g., after the first feedback packet or the SYN exchange from the connection setup, or from a previous connection [RFC2140]), tld is set to the current time, and the allowed transmit rate, X, is set to the initial_rate, specified as W_init/R, for W_init based on [RFC3390]: initial_rate = W_init/R; W_init = min(4*MSS, max(2*MSS, 4380)). In computing W_init, instead of using Maximum Segment Size (MSS), the TFRC sender SHOULD use the maximum segment size to be used for the initial round-trip time of data, if that is known by the TFRC sender when X is initialized. For responding to the initial feedback packet, this replaces step (4) of Section 4.3 below. Appendix B explains why the initial value of TFRC's nofeedback timer is set to two seconds, instead of the recommended initial value of three seconds for TCP's retransmit timer from [RFC2988].4.3. Sender Behavior When a Feedback Packet Is Received
The sender knows its current allowed sending rate, X, and maintains an estimate of the current round-trip time R. The sender also maintains X_recv_set as a small set of recent X_recv values (typically only two values). Initialization: X_recv_set is first initialized to contain a single item, with value Infinity. (As an implementation-specific issue, X_recv_set MAY be initialized to a large number instead of to Infinity, e.g., to the largest integer that is easily representable.)
When a feedback packet is received by the sender at time t_now, the current time in seconds, the following actions MUST be performed. 1) Calculate a new round-trip sample: R_sample = (t_now - t_recvdata) - t_delay. As described in Section 3.2.2, t_delay gives the elapsed time at the receiver. 2) Update the round-trip time estimate: If no feedback has been received before { R = R_sample; } Else { R = q*R + (1-q)*R_sample; } TFRC is not sensitive to the precise value for the filter constant q, but a default value of 0.9 is RECOMMENDED. 3) Update the timeout interval: RTO = max(4*R, 2*s/X) 4) Update the allowed sending rate as follows. This procedure uses the variables t_mbi and recv_limit: t_mbi: the maximum backoff interval of 64 seconds. recv_limit: the limit on the sending rate computed from X_recv_set. This procedure also uses the procedures Maximize X_recv_set() and Update X_recv_set(), which are defined below.
The procedure for updating the allowed sending rate: If (the entire interval covered by the feedback packet was a data-limited interval) { If (the feedback packet reports a new loss event or an increase in the loss event rate p) { Halve entries in X_recv_set; X_recv = 0.85 * X_recv; Maximize X_recv_set(); recv_limit = max (X_recv_set); } Else { Maximize X_recv_set(); recv_limit = 2 * max (X_recv_set); } } Else { // typical behavior Update X_recv_set(); recv_limit = 2 * max (X_recv_set); } If (p > 0) { // congestion avoidance phase Calculate X_Bps using the TCP throughput equation. X = max(min(X_Bps, recv_limit), s/t_mbi); } Else if (t_now - tld >= R) { // initial slow-start X = max(min(2*X, recv_limit), initial_rate); tld = t_now; } 5) If oscillation reduction is used, calculate the instantaneous transmit rate, X_inst, following Section 4.5. 6) Reset the nofeedback timer to expire after RTO seconds. The procedure for maximizing X_recv_set keeps a single value, the largest value from X_recv_set and the new X_recv. Maximize X_recv_set(): Add X_recv to X_recv_set; Delete initial value Infinity from X_recv_set, if it is still a member. Set the timestamp of the largest item to the current time; Delete all other items.
The procedure for updating X_recv_set keeps a set of X_recv values with timestamps from the two most recent round-trip times. Update X_recv_set(): Add X_recv to X_recv_set; Delete from X_recv_set values older than two round-trip times. Definition of a data-limited interval: We define a sender as data-limited any time it is not sending as much as it is allowed to send. We define an interval as a 'data-limited interval' if the sender was data-limited over the *entire* interval; Section 8.2.1 discusses implementation issues for a sender in determining if an interval was a data-limited interval. The term 'data-limited interval' is used in the first "if" condition in step (4), which prevents a sender from having to reduce its sending rate as a result of a feedback packet reporting the receive rate from a data-limited period. As an example, consider a sender that is sending at its full allowed rate, except that it is sending packets in pairs, rather than sending each packet as soon as it can. Such a sender is considered data- limited part of the time, because it is not always sending packets as soon as it can. However, consider an interval that covers this sender's transmission of at least two data packets; such an interval does not meet the definition of a data-limited interval because the sender was not data-limited *over the entire interval*. If the feedback packet reports a receive rate X_recv of zero (i.e., the first feedback packet), the sender does not consider that the entire interval covered by the feedback packet was a data-limited interval. X_recv_set and the first feedback packet: Because X_recv_set is initialized with a single item, with value Infinity, recv_limit is set to Infinity for the first two round-trip times of the connection. As a result, the sending rate is not limited by the receive rate during that period. This avoids the problem of the sending rate being limited by the value of X_recv from the first feedback packet. The interval covered by a feedback packet: How does the sender determine the period covered by a feedback packet? This is discussed in more detail in Section 8.2. In general, the receiver will be sending a feedback packet once per round-trip time; so typically, the sender will be able to determine exactly the period covered by the current feedback packet from the previous feedback packet. However, in cases when the previous
feedback packet was lost, or when the receiver sends a feedback packet early because it detected a lost or ECN-marked packet, the sender will have to estimate the interval covered by the feedback packet. As specified in Section 6.2, each feedback packet sent by the receiver covers a round-trip time, for the round-trip time estimate R_m maintained by the receiver R_m seconds before the feedback packet was sent. The response to a loss during a data-limited interval: In TFRC, after the initial slow-start, the sender always updates the calculated transmit rate, X_Bps, after a feedback packet is received, and the allowed sending rate, X, is always limited by X_Bps. However, during a data-limited interval, when the actual sending rate is usually below X_Bps, the sending rate is still limited by recv_limit, derived from X_recv_set. If the sender is data-limited, possibly with a varying sending rate from one round-trip time to the next, and is experiencing losses, then we decrease the entry in X_recv_set in order to reduce the allowed sending rate. The sender can detect a loss event during a data-limited period either from explicit feedback from the receiver, or from a reported increase in the loss event rate. When the sender receives a feedback packet reporting such a loss event in a data-limited interval, the sender limits the allowed increases in the sending rate during the data-limited interval. The initial slow-start phase: Note that when p=0, the sender has not yet learned of any loss events, and the sender is in the initial slow-start phase. In this initial slow-start phase, the sender can approximately double the sending rate each round-trip time until a loss occurs. The initial_rate term in step (4) gives a minimum allowed sending rate during slow-start of the initial allowed sending rate. We note that if the sender is data-limited during slow-start, or if the connection is limited by the path bandwidth, then the sender is not necessarily able to double its sending rate each round-trip time; the sender's sending rate is limited to at most twice the past receive rate, or at most initial_rate, whichever is larger. This is similar to TCP's behavior, where the sending rate is limited by the rate of incoming acknowledgement packets as well as by the congestion window. Thus, in TCP's slow-start, for the most aggressive case of the TCP receiver acknowledging every data packet, the TCP sender's sending rate is limited to at most twice the rate of these incoming acknowledgment packets.
The minimum allowed sending rate: The term s/t_mbi ensures that when p > 0, the sender is allowed to send at least one packet every 64 seconds.4.4. Expiration of Nofeedback Timer
This section specifies the sender's response to a nofeedback timer. The nofeedback timer could expire because of an idle period or because of data or feedback packets dropped in the network. This section uses the variable recover_rate. If the TFRC sender has been idle ever since the nofeedback timer was set, the allowed sending rate is not reduced below the recover_rate. For this document, the recover_rate is set to the initial_rate (specified in Section 4.2). Future updates to this specification may explore other possible values for the recover_rate. If the nofeedback timer expires, the sender MUST perform the following actions: 1) Cut the allowed sending rate in half. If the nofeedback timer expires when the sender has had at least one RTT measurement, the allowed sending rate is reduced by modifying X_recv_set as described in the pseudocode below (including item (2)). In the general case, the sending rate is limited to at most twice X_recv. Modifying X_recv_set limits the sending rate, but still allows the sender to slow-start, doubling its sending rate each RTT, if feedback messages resume reporting no losses. If the sender has been idle since this nofeedback timer was set and X_recv is less than the recover_rate, then the allowed sending rate is not halved, and X_recv_set is not changed. This ensures that the allowed sending rate is not reduced to less than half the recover_rate as a result of an idle period. In the general case, the allowed sending rate is halved in response to the expiration of the nofeedback timer. The details, in the pseudocode below, depend on whether the sender is in slow- start, is in congestion avoidance limited by X_recv, or is in congestion avoidance limited by the throughput equation.
X_recv = max (X_recv_set); If (sender does not have an RTT sample, has not received any feedback from receiver, and has not been idle ever since the nofeedback timer was set) { // We do not have X_Bps or recover_rate yet. // Halve the allowed sending rate. X = max(X/2, s/t_mbi); } Else if (((p>0 && X_recv < recover_rate) or (p==0 && X < 2 * recover_rate)), and sender has been idle ever since nofeedback timer was set) { // Don't halve the allowed sending rate. Do nothing; } Else if (p==0) { // We do not have X_Bps yet. // Halve the allowed sending rate. X = max(X/2, s/t_mbi); } Else if (X_Bps > 2*X_recv)) { // 2*X_recv was already limiting the sending rate. // Halve the allowed sending rate. Update_Limits(X_recv;) } Else { // The sending rate was limited by X_Bps, not by X_recv. // Halve the allowed sending rate. Update_Limits(X_Bps/2); } The term s/t_mbi limits the backoff to one packet every 64 seconds. The procedure Update_Limits() uses the variable timer_limit for the limit on the sending rate computed from the expiration of the nofeedback timer, as follows: Update_Limits(timer_limit): If (timer_limit < s/t_mbi) timer_limit = s/t_mbi; Replace X_recv_set contents with the single item timer_limit/2; Recalculate X as in step (4) of Section 4.3; 2) Restart the nofeedback timer to expire after max(4*R, 2*s/X) seconds. If the sender has been data-limited but not idle since the nofeedback timer was set, it is possible that the nofeedback timer expired because data or feedback packets were dropped in the network. In
this case, the nofeedback timer is the backup mechanism for the sender to detect these losses, similar to the retransmit timer in TCP. Note that when the sender stops sending data for a period of time, the receiver will stop sending feedback. When the sender's nofeedback timer expires, the sender could use the procedure above to limit the sending rate. If the sender subsequently starts to send again, X_recv_set will be used to limit the transmit rate, and slow- start behavior will occur until the transmit rate reaches X_Bps. The TFRC sender's reduction of the allowed sending rate after the nofeedback timer expires is similar to TCP's reduction of the congestion window, cwnd, after each RTO seconds of an idle period, for TCP with Congestion Window Validation [RFC2861].4.5. Reducing Oscillations
To reduce oscillations in queueing delay and sending rate in environments with a low degree of statistical multiplexing at the congested link, it is RECOMMENDED that the sender reduce the transmit rate as the queueing delay (and hence RTT) increases. To do this, the sender maintains R_sqmean, a long-term estimate of the square root of the RTT, and modifies its sending rate depending on how the square root of R_sample, the most recent sample of the RTT, differs from the long-term estimate. The long-term estimate R_sqmean is set as follows: If no feedback has been received before { R_sqmean = sqrt(R_sample); } Else { R_sqmean = q2*R_sqmean + (1-q2)*sqrt(R_sample); } Thus, R_sqmean gives the exponentially weighted moving average of the square root of the RTT samples. The constant q2 should be set similarly to q, the constant used in the round-trip time estimate R. A value of 0.9 as the default for q2 is RECOMMENDED. When sqrt(R_sample) is greater than R_sqmean, then the current round-trip time is greater than the long-term average, implying that queueing delay is probably increasing. In this case, the transmit rate is decreased to minimize oscillations in queueing delay. The sender obtains the base allowed transmit rate, X, as described in step (4) of Section 4.3 above. It then calculates a modified instantaneous transmit rate X_inst, as follows:
X_inst = X * R_sqmean / sqrt(R_sample); If (X_inst < s/t_mbi) X_inst = s/t_mbi; Because we are using square roots, there is generally only a moderate difference between the instantaneous transmit rate X_inst and the allowed transmit rate X. For example, in a somewhat extreme case when the current RTT sample R_sample is twice as large as the long- term average, then sqrt(R_sample) will be roughly 1.44 times R_sqmean, and the allowed transmit rate will be reduced by a factor of roughly 0.7. We note that this modification for reducing oscillatory behavior is not always needed, especially if the degree of statistical multiplexing in the network is high. We also note that the modification for reducing oscillatory behavior could cause problems for connections where the round-trip time is not strongly correlated with the queueing delay (e.g., in some wireless links, over paths with frequent routing changes, etc.). However, this modification SHOULD be implemented because it makes TFRC behave better in some environments with a low level of statistical multiplexing. The performance of this modification is illustrated in Section 3.1.3 of [FHPW00]. If it is not implemented, implementations SHOULD use a very low value of the weight q for the average round-trip time.4.6. Scheduling of Packet Transmissions
As TFRC is rate-based, and as operating systems typically cannot schedule events precisely, it is necessary to be opportunistic about sending data packets so that the correct average rate is maintained despite the coarse-grain or irregular scheduling of the operating system. To help maintain the correct average sending rate, the TFRC sender MAY send some packets before their nominal send time. In addition, the scheduling of packet transmissions controls the allowed burstiness of senders after an idle or data-limited period. The TFRC sender MAY accumulate sending 'credits' for past unused send times; this allows the TFRC sender to send a burst of data after an idle or data-limited period. To compare with TCP, TCP may send up to a round-trip time's worth of packets in a single burst, but never more. As examples, packet bursts can be sent by TCP when an ACK arrives acknowledging a window of data, or when a data-limited sender suddenly has a window of data to send after a delay of nearly a round-trip time.
To limit burstiness, a TFRC implementation MUST prevent bursts of arbitrary size. This limit MUST be less than or equal to one round- trip time's worth of packets. A TFRC implementation MAY limit bursts to less than a round-trip time's worth of packets. In addition, a TFRC implementation MAY use rate-based pacing to smooth bursts. As an implementation-specific example, a sending loop could calculate the correct inter-packet interval, t_ipi, as follows: t_ipi = s/X_inst; Let t_now be the current time and i be a natural number, i = 0, 1, ..., with t_i the nominal send time for the i-th packet. Then, the nominal send time t_(i+1) would derive recursively as: t_0 = t_now, t_(i+1) = t_i + t_ipi. For TFRC senders allowed to accumulate sending credits for unused send time over the last T seconds, the sender would be allowed to use unused nominal send times t_j for t_j < now - T, for T set to the round-trip time.