<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.20 (Ruby 3.3.5) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

<!ENTITY RFC2119 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC8174 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY RFC9000 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9000.xml">
<!ENTITY I-D.ietf-moq-transport SYSTEM "https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-moq-transport.xml">
<!ENTITY RFC9331 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9331.xml">
]>


<rfc ipr="trust200902" docName="draft-huitema-ccwg-c4-spec-02" category="exp" consensus="true" submissionType="IETF">
  <front>
    <title abbrev="C4 Specification">Specification of Christian's Congestion Control Code (C4)</title>

    <author initials="C." surname="Huitema" fullname="Christian Huitema">
      <organization>Private Octopus Inc.</organization>
      <address>
        <email>huitema@huitema.net</email>
      </address>
    </author>
    <author initials="S." surname="Nandakumar" fullname="Suhas Nandakumar">
      <organization>Cisco</organization>
      <address>
        <email>snandaku@cisco.com</email>
      </address>
    </author>
    <author initials="C." surname="Jennings" fullname="Cullen Jennings">
      <organization>Cisco</organization>
      <address>
        <email>fluffy@iii.ca</email>
      </address>
    </author>

    <date year="2026" month="February" day="26"/>

    <area>Web and Internet Transport</area>
    
    <keyword>C4</keyword> <keyword>Congestion Control</keyword> <keyword>Realtime Communication</keyword> <keyword>Media over QUIC</keyword>

    <abstract>


<?line 44?>

<t>Christian's Congestion Control Code is a new congestion control
algorithm designed to support Real-Time applications such as
Media over QUIC. It is designed to drive towards low delays,
with good support for the "application limited" behavior
frequently found when using variable rate encoding, and
with fast reaction to congestion to avoid the "priority
inversion" happening when congestion control overestimates
the available capacity. The design emphasizes simplicity and
avoids making too many assumptions about the "model" of
the network.</t>



    </abstract>



  </front>

  <middle>


<?line 57?>

<section anchor="introduction"><name>Introduction</name>

<t>Christian's Congestion Control Code (C4) is a congestion control
algorithm designed to support Real-Time multimedia applications, specifically
multimedia applications using QUIC <xref target="RFC9000"/> and the Media
over QUIC transport <xref target="I-D.ietf-moq-transport"/>.</t>

<t>The two main variables describing the state of a flow are the
"nominal rate" (see <xref target="nominal-rate"/>) and the
"nominal max RTT" (see <xref target="nominal-max-rtt"/>).
C4 organizes the management of the flow through a series of
states: Initial, during which the first assessment of nominal-rate
and nominal max RTT are obtained, Recovery in which a flow is
stabilized after the Initial or Pushing phase, Cruising during which
a flow uses the nominal rate, and Pushing during which the flow
tries to discover if more resource is available -- see <xref target="c4-states"/>.</t>

<t>C4 divides the duration of the connection in a set of "eras",
each corresponding to a packet round trip. Transitions between protocol
states typically happen at the end of an era, except if the
transition is forced by a congestion event.</t>

<t>C4 assumes that the transport stack is
capable of signaling events such
as acknowledgements, RTT measurements, ECN signals or the detection
of packet losses. It also assumes that the congestion algorithm
controls the transport stack by setting the congestion window
(CWND) and the pacing rate (see <xref target="congestion-response"/>).</t>

<t>C4 introduces the concept of "sensitivity" (see <xref target="sensitivity"/>)
to ensure that flows using a large amount of bandwidth are more
"sensitive" to congestion signals than flows using fewer bandwidth,
and thus that multiple flows sharing a common bottleneck are driven
to share the resource evenly.</t>

</section>
<section anchor="key-words"><name>Key Words</name>

<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED",
"MAY", and "OPTIONAL" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

</section>
<section anchor="c4-variables"><name>C4 variables</name>

<t>In addition to the nomnal rate and the nominal max RTT,
C4 maintains a set a variables per flow (see <xref target="global-variables"/>)
and per era (see <xref target="era-variables"/>).</t>

<section anchor="nominal-rate"><name>Nominal rate</name>

<t>The nominal rate is an estimate of the bandwidth available to the flow.
On initialization, the nominal rate is set to zero, and default values
are used when setting the pacing rate and CWND for the flow.</t>

<t>C4 evaluates the nominal rate after acknowledgements are received
using the number of bytes acknowledged since the packet was sent
(<spanx style="verb">bytes_acknowledged</spanx>) and the time delay it took to process these packets.</t>

<t>That delay is normally set to the difference between the time
at which the acknowledged packet was sent (<spanx style="verb">time_sent</spanx>),
and the current time (<spanx style="verb">current_time</spanx>). However, that difference
may sometimes be severely underestimated because of delay jitter
and ACK compression. We also compute a "send delay" as the difference
between the send time of the acknowledged packet and the send time
of the oldest "delivered" packet.</t>

<figure><artwork><![CDATA[
delay_estimate = max (current_time - time_sent, send_delay)
rate_estimate = bytes_acknowledged /delay_estimate
]]></artwork></figure>

<t>If we are not in a congestion situation, we update the
nominal rate:</t>

<figure><artwork><![CDATA[
if not congested and nominal_rate > rate_estimate:
    nominal_rate = rate_estimate
]]></artwork></figure>

<t>The data rate measurements can only cause increases in
the nominal rate. The nominal rate is reduced following
congestion events, as specified in <xref target="congestion-response"/>.</t>

<t>The "congested" condition is defined as being in the
recovery state and having either entered that state due
to a congestion event, or having received a congestion
event after entering recovery.</t>

<t>Updating the nominal rate
in these conditions would cause a congestion bounce: the
nominal rate is reduced because of a congestion event,
C4 enters recovery, but then packets sent at the previous
rate are received during recovery, generating a new estimate
and resetting the nominal rate to a value close to the one
that caused congestion.</t>

</section>
<section anchor="nominal-max-rtt"><name>Nominal max RTT</name>

<t>The nominal max RTT is an estimate of the maximum RTT
that can occur on the path in the absence of queues.
The RTT samples observed for the flow are the sum of four
components:</t>

<t><list style="symbols">
  <t>the latency of the path</t>
  <t>the jitter introduced by processes like link layer contention
or link layer retransmission</t>
  <t>queuing delays caused by competing applications</t>
  <t>queuing delays introduced by C4 itself.</t>
</list></t>

<t>C4's goal is to obtain a estimate of the combination of path latency
and maximum jitter. This is done by only taking measurements
when C4 is sending data at a rate not higher than the nominal transmission rate,
as happens for example in the recovery and cruising states. These measurements
will happen during the following era. C4 captures them
by recording the max RTT for packets sent in that era.
C4 will also progressively reduce the value of the
nominal max RTT over time, to account for changes in network
conditions.</t>

<figure><artwork><![CDATA[
# on end of era

if alpha_previous <= 1.0:
    if era_min_rtt < running_min_rtt:
        running_min_rtt = era_min_rtt
    else:
        running_min_rtt =
           (7*running_min_rtt + era_min_rtt)/8

    if era_max_rtt > running_min_rtt + MAX_JITTER:
        # cap RTT increases to MAX_JITTER, i.e., 250ms
        era_max_rtt = running_min_rtt + MAX_JITTER
    if era_max_rtt > nominal_max_rtt:
        nominal_max_rtt = era_max_rtt
    else:
        nominal_max_rtt =
          (7*nominal_max_rtt + era_max_rtt)/8
]]></artwork></figure>

<t>The decrease over time is tuned so that jitter
events will be remembered for several of the
cruising-pushing-recovery cycles, which is enough time for the
next jitter event to happen, at least on Wi-Fi networks.</t>

</section>
<section anchor="global-variables"><name>Global variables</name>

<t>In addition to the nominal rate and nominal MAX RTT,
C4 maintains a set of variables tracking the evolution of the flow:</t>

<t><list style="symbols">
  <t>running min RTT, an approximation of the min RTT for the flow,</t>
  <t>number of eras without increase (see <xref target="c4-initial"/>),</t>
  <t>current state of the algorithm, which can be Initial, Recovery,
Cruising or Pushing.</t>
  <t>probe level.</t>
</list></t>

<t>The probe level determines how aggressive the pushing phase is, and also
how long to wait between recovery and pushing.</t>

</section>
<section anchor="era-variables"><name>Per era variables</name>

<t>C4 keeps variables per era:</t>

<figure><artwork><![CDATA[
era_sequence; /* sequence number of first packet sent in this era */
alpha_current; /* coefficient alpha used in the current state */
alpha_previous; /* coefficient alpha used in the previous era */
era_max_rtt; /* max RTT observed during this era */
era_min_rtt; /* min RTT observed during this era */
]]></artwork></figure>

<t>These variables are initialized at the beginning of the era.</t>

</section>
</section>
<section anchor="c4-states"><name>States and Transition</name>

<t>The state machine for C4 has the following states:</t>

<t><list style="symbols">
  <t>"Initial": the initial state, during which the CWND is
set to twice the "nominal_CWND". The connection
exits startup if the "nominal_cwnd" does not
increase for 3 consecutive round trips. When the
connection exits startup, it enters "recovery".</t>
  <t>"Recovery": the connection enters that state after
"Initial", "pushing", or a congestion detection in
a "cruising" state. It remains in that state for
at least one roundtrip, until the first packet sent
in "recovery" is acknowledged. Once that happens,
the connection goes back
to "startup" if the last 3 pushing attemps have resulted
in increases of "nominal rate", or if it detects high
jitter and the previous initial was not run
in these conditions (see ). It enters "cruising"
otherwise.</t>
  <t>"Cruising": the connection is sending using the
"nominal_rate" and "nominal_max_rtt" value. If congestion is detected,
the connection exits cruising and enters
"recovery" after lowering the value of
"nominal_cwnd".
Otherwise, the connection will
remain in "cruising" state until at least 4 RTT and
the connection is not "app limited". At that
point, it enters "pushing".</t>
  <t>"Pushing": the connection is using a rate and CWND 25%
larger than "nominal_rate" and "nominal_CWND".
It remains in that state
for one round trip, i.e., until the first packet
send while "pushing" is acknowledged. At that point,
it enters the "recovery" state.</t>
</list></t>

<t>These transitions are summarized in the following state
diagram.</t>

<figure><artwork><![CDATA[
                    Start
                      |
                      v
                      +<-----------------------+
                      |                        |
                      v                        |
                 +----------+                  |
                 | Initial  |                  |
                 +----|-----+                  |
                      |                        |
                      v                        |
                 +------------+                |
  +--+---------->|  Recovery  |                |
  ^  ^           +----|---|---+                |
  |  |                |   |  First High Jitter |
  |  |                |   |  or Rapid Increase |
  |  |                |   +------------------->+
  |  |                |
  |  |                v
  |  |           +----------+
  |  |           | Cruising |
  |  |           +-|--|-----+
  |  | Congestion  |  |
  |  +-------------+  |
  |                   |
  |                   v
  |              +----------+
  |              | Pushing  |
  |              +----|-----+
  |                   |
  +<------------------+

]]></artwork></figure>

<section anchor="set_pace"><name>Setting pacing rate, congestion window and quantum</name>

<t>If the nominal rate or the nominal max RTT are not yet
assessed, C4 sets pacing rate, congestion window and
pacing quantum to initial values:</t>

<t><list style="symbols">
  <t>pacing rate: set to the data rate of the outgoing interface,</t>
  <t>congestion window: set to the equivalent of 10 packets,</t>
  <t>congestion quantum: set to zero.</t>
</list></t>

<t>If the nominal rate or the nominal max RTT are both
assessed, C4 sets pacing rate, and congestion window 
to values that depends on these variables
and on a coefficient <spanx style="verb">alpha_current</spanx>:</t>

<figure><artwork><![CDATA[
if (c4_state == initial):
    margin = 0
else:
    margin = min(nominal_max_rtt/4, 15_milliseconds)

pacing_rate = alpha_current * nominal_rate
cwnd = max ((pacing_rate+margin) * nominal_max_rtt, 2*MTU)
]]></artwork></figure>

<t>The "margin" coefficient accounts for errors on the
estimate of the nominal max rtt, which could cause C4
to be stuck operating at a too low data rate. It is only
applied outside of the initial phase.</t>

<t>The coefficient <spanx style="verb">alpha</spanx> for the different states is:</t>

<texttable>
      <ttcol align='left'>state</ttcol>
      <ttcol align='left'>alpha</ttcol>
      <ttcol align='left'>comments</ttcol>
      <c>Initial</c>
      <c>2</c>
      <c>&#160;</c>
      <c>Recovery</c>
      <c>15/16</c>
      <c>&#160;</c>
      <c>Cruising</c>
      <c>1</c>
      <c>&#160;</c>
      <c>Pushing</c>
      <c>5/4 or 17/16</c>
      <c>see <xref target="c4-pushing"/> for rules on choosing 5/4 or 17/16</c>
</texttable>

<t>Setting the pacing quantum is a tradeoff between two requirements.
Using a large quantum enables applications to send large batches of
packets in a single transaction, which improves performance. But
sending large batches of packets creates "instant queues" and
causes some Active Queue Management mechanisms to mark packets as
ECN/CE, or drop them. As a compromise, we set the quantum to
4 milliseconds worth of transmission, while capping it to 64KB.</t>

<figure><artwork><![CDATA[
quantum = max ( min (pacing_rate*4_milliseconds, 64KB), 2*MTU)
]]></artwork></figure>

</section>
<section anchor="c4-initial"><name>Initial state</name>

<t>When the flow is first initialized, it enters the Initial state,
during which it does a first assessment of the
"nominal rate" and "nominal max RTT".
The coefficient <spanx style="verb">alpha_current</spanx> is set to 2. The
"nominal rate" and "nominal max RTT" are initialized to zero,
which will cause pacing rate to be set to a default
initial value. The nominal max RTT will be set to the
first assessed RTT value, but is not otherwise changed
before the end of the initial phase.
The CWND will be set to the default initial value,
corresponding to 10 packets.</t>

<t>During the initial state, the nominal rate is updated
after receiving acknowledgements, see <xref target="nominal-rate"/>.
The value of CWND is increased after each acknowledgement
by the number of bytes newly acknowledged by this
acknowledgement.</t>

<t>C4 will exit the Initial state and enter Recovery if the 
nominal rate does not increase for 3 consecutive eras,
omitting the eras for which the transmission was
"application limited".</t>

<t>C4 exit the Initial when receiving a congestion signal if the
following conditions are true:</t>

<t>1- If the signal is due to "delay" or "ECN", C4 will only exit the
   initial state if the <spanx style="verb">nominal_rate</spanx> did not increase
   in the last 2 eras.</t>

<t>2- If the signal is due to "loss", C4 will only exit the
   initial state if more than 20 packets have been received.</t>

<t>The restriction on delay signals and ECN is meant to prevent spurious exit
due to delay jitter or competing connections. The restriction on loss
signals is meant to ensure that enough packets have been received to properly
assess the loss rate.</t>

<t>On exiting the Initial state, C4 computes an estimate of the nominal
max RTT as the quotient of the half the last CWND divided by the last
nominal rate, and updates the "nominal max RTT" accordingly. The probe level
is set to 1.</t>

<section anchor="reentering-the-initial-state"><name>Reentering the initial state</name>

<t>When reentering the initial state, C4 already has an estimate of the
current nominal rate and nominal max RTT. CWND is set to the product of
nominal rate and nominal max RTT. The initial state then operates as
specified in <xref target="c4-initial"/>.</t>

</section>
</section>
<section anchor="c4-recovery"><name>Recovery state</name>

<t>The recovery state is entered from the Initial or Pushing state,
or from the Cruising state in case of congestion. 
The coefficient <spanx style="verb">alpha_current</spanx> is set to 15/16. Because the multiplier
is lower than 1, the new value of CWND may well be lower
than the current number of bytes in transit. C4 will wait
until acknowledgements are received and the number of bytes
in transit is lower than CWND to send new packets.</t>

<t>The Recovery ends when the first packet sent during that state
is acknowledged. That means that acknowledgement and congestion
signals received during recovery are the consequence of packets
sent before. C4 assumes that whatever corrective action is required
by these events will be taken prior to entering recovery, and that
events arriving during recovery are duplicate of the prior events
and can be ignored.</t>

<t>Rate increases are detected when acknowledgements received during recovery
reflect a successful "push" during the Pushing phase. The prior "Pushing"
is considered successful if it did not trigger any congestion event,
and if the data rate increases sufficiently
between the end of previous Recovery and the end of this one, with
sufficiently being defined as:</t>

<t><list style="symbols">
  <t>Any increase if the prior pushing rate (alpha_prior) was 17/16 or
less,</t>
  <t>An increase of at least 1/4th of the expected increase otherwise,
for example an increase of 1/16th if <spanx style="verb">alpha_previous</spanx> was 5/4.</t>
</list></t>

<t>The probe level is updated as follow:</t>

<t><list style="symbols">
  <t>If the prior pushing was successful, and did not trigger an excessive rate of ECN/CE marks,
the probe level is increased by 1.</t>
  <t>If the prior pushing was successful but did trigger an excessive rate of ECN/CE marks,
the probe level remains unchanged.</t>
  <t>If the prior pushing was not successful but did not trigger an excessive rate of ECN/CE marks,
the probe level left unchanged if it was 0, set to 1 otherwise.</t>
  <t>If the prior pushing was not successful and did trigger an excessive rate of ECN/CE marks,
the probe level is set to 0.</t>
</list></t>

<t>C4 re-enters "Initial" at the end of the recovery period if the probe level
as reached a value 4 or larger, or if
high jitter requires restarting the Initial phase (see
<xref target="restart-high-jitter"/>. Otherwise, C4 enters cruising.</t>

<t>Reception of a congestion signal during the Initial phase does not
cause a change in the <spanx style="verb">nominal_rate</spanx> or <spanx style="verb">nominal_max_RTT</spanx>.</t>

<section anchor="restart-high-jitter"><name>Restarting Initial if High Jitter</name>

<t>The "nominal max RTT" is not updated during the Initial phase,
because doing so would prevent exiting Initial on high delay
detection. This can lead to underestimation of the "nominal
rate" if the flow is operating on a path with high jitter.</t>

<t>C4 will reenter the "initial" phase on the first time
high jitter is detected for the flow. The high jitter
is detected after updating the "nominal max RTT" at the
end of the recovery era, if:</t>

<figure><artwork><![CDATA[
running_min_rtt < nominal_max_rtt*2/5
]]></artwork></figure>

<t>This will be done at most once per flow.</t>

</section>
</section>
<section anchor="cruising-state-c4-cruising-"><name>Cruising state {#c4-cruising }</name>

<t>The Cruising state is entered from the Recovery state. 
The coefficient <spanx style="verb">alpha_current</spanx> is set to 1.</t>

<t>C4 will transition from Cruising state to Pushing state
after a number of eras that depend on the probe level:</t>

<t><list style="symbols">
  <t>1 era if the probe level is 0,</t>
  <t>4 eras if the probe level is 1,</t>
  <t>1 era if the probe level is 2 or 3.</t>
</list></t>

<t>C4 will transition to Recovery before that if
a congestion signal is received before transition to Pushing.</t>

</section>
<section anchor="c4-pushing"><name>Pushing state</name>

<t>The Pushing state is entered from the Cruising state.</t>

<t>The coefficient <spanx style="verb">alpha_current</spanx> depend on the probe level:</t>

<t><list style="symbols">
  <t>If the probe level is 0, <spanx style="verb">alpha_current</spanx> is set to 33/32.</t>
  <t>If the probe level is 1, <spanx style="verb">alpha_current</spanx> is set to 17/16.</t>
  <t>If the probe level is 2 or higher, <spanx style="verb">alpha_current</spanx> is set to 5/4.</t>
</list></t>

<t>C4 exits the pushing state after one era, or if a congestion
signal is received before that. In an exception to
standard congestion processing, the reduction in <spanx style="verb">nominal_rate</spanx> and
<spanx style="verb">nominal_max_RTT</spanx> are not applied if the congestion signal
is tied to a packet sent during the Pushing state.</t>

</section>
</section>
<section anchor="congestion-response"><name>Handling of congestion signals</name>

<t>C4 responds to congestion events by reducing the nominal rate, and
in some condition also reducing the nominal max RTT. C4 monitors
3 types of congestion events:</t>

<t><list style="numbers" type="1">
  <t>Excessive increase of measured RTT,</t>
  <t>Excessive rate of packet losses (but not mere Probe Time Out, see <xref target="no-pto"/>),</t>
  <t>Excessive rate of ECN/CE marks</t>
</list></t>

<t>C4 monitors successive RTT measurements and compare them to
a reference value, defined as the sum of the "nominal max rtt"
and a "delay threshold". C4 monitors the arrival of packet losses
computes a "smoothed error rate", and compares it to a
"loss threshold". When the path supports ECN, C4 monitors the
arrival of ECN marks and computes a "smoothed CE rate",
and compares it to a "CE threshold". These coefficients
depend on the sensitivity coefficient defined in <xref target="sensitivity"/>.</t>

<section anchor="sensitivity"><name>Variable Sensitivity</name>

<t>The three congestion detection thresholds are
function of the "sensitivity" coefficient,
which increases with the nominal rate of the flow. Flows
operating at a low data rate have a low sensitivity coefficient
and reacts slower to congestion signals than flows operating
at a higher rate. If multiple flows share the same bottleneck,
the flows with higher data rate will detect congestion signals
and back off faster than flow operating at lower rate. This will
drive these flows towards sharing the available resource evenly.</t>

<t>The sensitivity coefficient varies from 0 to 1, according to
a simple curve:</t>

<t><list style="symbols">
  <t>set sensitivity to 0 if data rate is lower than 50000 B/s</t>
  <t>linear interpolation between 0 and 0.92 for values
between 50,000 and 1,000,000 B/s.</t>
  <t>linear interpolation between 0.92 and 1 for values
between 1,000,000 and 10,000,000 B/s.</t>
  <t>set sensitivity to 1 if data rate is higher than
10,000,000 B/s</t>
</list></t>

<t>The sensitivity index is then used to set the value of delay and
loss and CE thresholds.</t>

</section>
<section anchor="detecting-excessive-delays"><name>Detecting Excessive Delays</name>

<t>The delay threshold is function of the nominal max RTT and the
sensitivity coefficient:</t>

<figure><artwork><![CDATA[
    delay_fraction = 1/16 + (1 - sensitivity)*3/16
    delay_threshold = min(25ms, delay_fraction*nominal_max_rtt)
]]></artwork></figure>

<t>A delay congestion signal is detected if:</t>

<figure><artwork><![CDATA[
    rtt_sample > nominal_max_rtt + delay_threshold
]]></artwork></figure>

</section>
<section anchor="detecting-excessive-losses"><name>Detecting Excessive Losses</name>

<t>C4 maintains an average loss rate, updated for every packet
as:</t>

<figure><artwork><![CDATA[
    if packet_is_lost:
        loss = 1
    else:
        loss = 0
    smoothed_loss_rate = (loss + 15*smoothed_loss_rate)/16
]]></artwork></figure>

<t>The loss threshold is computed as:</t>

<figure><artwork><![CDATA[
    loss_threshold = 0.02 + 0.50 * (1-sensitivity);
]]></artwork></figure>

<t>A loss is detected if the smoothed loss rate is larger than the threshold.
In that case, the coefficient <spanx style="verb">beta</spanx> is set to 1/4.</t>

<section anchor="no-pto"><name>Do not react to Probe Time Out</name>

<t>QUIC normally detect losses by observing gaps in the sequences of acknowledged
packet. That's a robust signal. QUIC will also inject "Probe time out"
packets if the PTO timeout elapses before the last sent packet has not been acknowledged.
This is not a robust congestion signal, because delay jitter may also cause
PTO timeouts. When testing in "high jitter" conditions, we realized that we should
not change the state of C4 for losses detected solely based on timer, and
only react to those losses that are detected by gaps in acknowledgements.</t>

</section>
</section>
<section anchor="process-ecn"><name>Detecting Excessive CE Marks</name>

<t>The way we handle ECN signals is designed to be compatible with L4S <xref target="RFC9331"/>.
When the path supports ECN marking, C4 monitors the arrival of ECN/CE and
ECN/ECT(1) marks by computing the ratio <spanx style="verb">ecn_alpha</spanx>. Congestion is detected
when that ratio exceeds <spanx style="verb">ecn_threshold</spanx>, which varies depending on the
sensitivity coefficient:</t>

<figure><artwork><![CDATA[
ecn_threshold = (2-sensitivity)*3/32
]]></artwork></figure>

<t>The ratio <spanx style="verb">ecn_alpha</spanx> is
updated each time an acknowledgement is received, as follow:</t>

<figure><artwork><![CDATA[
delta_ce = increase in the reported CE marks
delta_ect1 = increase in the reported ECT(1) marks
frac = delta_ce / (delta_ce + delta_ect1)

if frac >= 0.5:
    ecn_alpha = frac
else:
    ecn_alpha += (frac - ecn_alpha)/16

if ecn_alpha > ecn_threshold:
    report congestion
]]></artwork></figure>

<t>Congestion detection causes C4 to enter recovery. The
ration <spanx style="verb">ecn_alpha</spanx> is set to zero on exit of recovery.</t>

</section>
<section anchor="applying-congestion-signals"><name>Applying congestion signals</name>

<t>On congestion signal, if C4 was not in recovery state, it
will enter recovery.</t>

<t>As stated in <xref target="c4-initial"/> and <xref target="c4-pushing"/>, detecting
a congestion in the Initial or Pushing state does not cause
a change in the <spanx style="verb">nominal_rate</spanx> or <spanx style="verb">nominal_max_RTT</spanx>, because
the pacing rate in these states is larger than the
<spanx style="verb">nominal_rate</spanx>. Rate reduction only happens if recovery
was entered from the Cruising state.</t>

<section anchor="rate-reduction"><name>Rate Reduction on Congestion</name>

<t>On entering recovery from the cruising state, C4 reduces the
<spanx style="verb">nominal_rate</spanx> by the factor "beta"
corresponding to the congestion signal:</t>

<figure><artwork><![CDATA[
    nominal_rate = (1-beta)*nominal_rate
]]></artwork></figure>

<t>The coefficient <spanx style="verb">beta</spanx> differs depending on the nature of the congestion
signal. For packet losses, it is set to <spanx style="verb">1/4</spanx>, similar to the
value used in Cubic.</t>

<t>For delay based losses, it is proportional to the
difference between the measured RTT and the target RTT divided by
the acceptable margin, capped to <spanx style="verb">1/4</spanx>:</t>

<figure><artwork><![CDATA[
    beta = min(1/4,
              (rtt_sample - (nominal_max_rtt + delay_threshold)/
               delay_threshold))
]]></artwork></figure>

<t>If the signal is an ECN/CE rate, the coefficient is proportional
to the difference between <spanx style="verb">ecn_alpha</spanx> and <spanx style="verb">ecn_threshold</spanx>, capped to <spanx style="verb">1/4</spanx>:</t>

<figure><artwork><![CDATA[
    beta = min(1/4, (ecn_alpha - ecn_threshold)/ ecn_threshold)
]]></artwork></figure>

</section>
</section>
</section>
<section anchor="implementation-considerations"><name>Implementation considerations</name>

<t>Implementing C4 ought to be straightforward, but developers need to pay
attention to measurement of data rates and to pacing issues when the
CPU load is high.</t>

<section anchor="rate-measurement-should-be-conservative"><name>Rate measurement should be conservative</name>

<t>The standard algorithm for rate measurement is to consider the amount
of data acknowledged in an interval of time, and divide that amount
by the duration of the interval. This algorithm can result in
over-estimates of the rate in presence of data jitter. These
excessive estimates could cause C4 to set a nominal rate higher
than the network path bandwidth, resulting in queue build-up and
excessive delays.</t>

<t>There are two known ways to reduce the effect of jitter: filter out
measurements in which the data rate measured through acknowledgements
is larger than the send rate; and, make sure that the measurement
interval are long enough so jitter only has a small influence. Cautious
implementations should use both strategies.</t>

</section>
<section anchor="pacing-and-cpu-load"><name>Pacing and CPU load</name>

<t>C4 relies on pacing during to avoid sending data too fast during the
recovery, cruising and pushing states. Pacing is often implemented
using a "leaky bucket" algorithm, which refills the bucket at the
pacing rate, allows transmission as long as there are enough tokens
in the bucket, and forces transmission to wait when all tokens are
consumed. The wait time is computed based on the pacing rate
and the number of desired tokens, and is implemented using
operating system commands such as <spanx style="verb">select()</spanx>, <spanx style="verb">poll()</spanx>,
<spanx style="verb">epoll()</spanx> or <spanx style="verb">sleep()</spanx>. In high CPU load conditions, we observe
that these commands often return after more than the specified
wait time, resulting in a lower sending rate than the desired
pacing rate.</t>

<t>This phenomenom is particularly visible in low-latency paths.
The generic solution would probably be to estimate how much slower
the actual pacing is compared to the desired rate, and increase the
programmed pacing rate by a value proportional to these measurements.
This generic solution is not yet specified. In between, implementations
had success with a simple fix: increase the pacing rate 3/64th in
"cruising" state when the RTT is less than 1ms. This definitely
improved performance in low-latency environment, in particular
loopback interfaces.</t>

</section>
<section anchor="nominal-max-rtt-on-low-latency-links"><name>Nominal max RTT on low latency links</name>

<t>When doing tests on low latency links, we observed on some systems
a lot of measurement jitter. The measured RTT is the sum of the
actual RTT and some system wakeup delay, which can vary between a
few microseconds and maybe 1 millisecond. The default algorithm
will adapt the nominal RTT after each roundtrip, which can lead
to excessively low values, causing a slowdown of the transmission.
A solution is to set a "floor" value to the nominal max RTT,
updating it to the maximum of the measured value and the floor.
Setting the floor value to 1ms did improve performance.</t>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<t>We do not believe that C4 introduce new security issues. Or maybe there are,
such as what happen if applications can be fooled in going to fast and
overwhelming the network, or going too slow and underwhelming the application.
Discuss!</t>

</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<t>This document has no IANA actions.</t>

</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

    <references title='Normative References' anchor="sec-normative-references">

&RFC2119;
&RFC8174;


    </references>

    <references title='Informative References' anchor="sec-informative-references">

&RFC9000;
&I-D.ietf-moq-transport;
&RFC9331;


    </references>

</references>


<?line 748?>

<section numbered="false" anchor="acknowledgments"><name>Acknowledgments</name>

<t>TODO acknowledge.</t>

</section>
<section numbered="false" anchor="changes-since-previous-versions"><name>Changes since previous versions</name>

<t>This section should be deleted before publication as an RFC</t>

<section numbered="false" anchor="changes-since-draft-huitema-ccwg-c4-spec-00"><name>Changes since draft-huitema-ccwg-c4-spec-00</name>

<t>Rewrote the description of the Initial state in <xref target="c4-initial"/>
to remove dependency on nominal max RTT.</t>

<t>Added the specification of reaction to ECN in <xref target="process-ecn"/>
and in <xref target="rate-reduction"/>. Update section <xref target="c4-pushing"/> to
modulate pushing rate based on observed rate of ECN/CE marks.</t>

<t>Added the RTT margin consideration in <xref target="set_pace"/>, and 
changed the computation of the "quantum" from:</t>

<figure><artwork><![CDATA[
quantum = max ( min (cwnd / 4, 64KB), 2*MTU)
]]></artwork></figure>

<t>to:</t>

<figure><artwork><![CDATA[
quantum = max ( min (pacing_rate*4_milliseconds, 64KB), 2*MTU)
]]></artwork></figure>

<t>The old formula caused long bursts of packets that would
trigger packet drops or ECN/CE marking by active queue management
algorithms.</t>

</section>
</section>


  </back>

<!-- ##markdown-source:
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

-->

</rfc>

