<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" []>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>
<?rfc strict="no"?>
<?rfc rfcedstyle="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>

<rfc category="exp" docName="draft-ietf-core-fasor-01" ipr="trust200902">
  <front>
    <title abbrev="Fast-Slow RTO and CC Algorithm">Fast-Slow
    Retransmission Timeout and Congestion Control Algorithm for CoAP</title>

    <author fullname="Ilpo Jarvinen" initials="I" surname="Jarvinen">
      <organization>University of Helsinki</organization>
      <address>
        <postal>
          <street>P.O. Box 68</street>
          <city>FI-00014 UNIVERSITY OF HELSINKI</city>
          <country>Finland</country>
        </postal>
        <email>ilpo.jarvinen@cs.helsinki.fi</email>
      </address>
    </author>

    <author fullname="Markku Kojo" initials="M" surname="Kojo">
      <organization>University of Helsinki</organization>
      <address>
        <postal>
          <street>P.O. Box 68</street>
          <city>FI-00014 UNIVERSITY OF HELSINKI</city>
          <country>Finland</country>
        </postal>
        <email>markku.kojo@cs.helsinki.fi</email>
      </address>
    </author>

    <author fullname="Iivo Raitahila" initials="I" surname="Raitahila">
      <organization>University of Helsinki</organization>
      <address>
        <postal>
          <street></street>
          <city>Helsinki</city>
          <country>Finland</country>
        </postal>
        <email>iivo.raitahila@alumni.helsinki.fi</email>
      </address>
    </author>

    <author fullname="Zhen Cao" initials="Z" surname="Cao">
      <organization>Huawei</organization>
      <address>
        <postal>
          <street></street>
          <city>Beijing</city>
          <country>China</country>
        </postal>
        <email>zhencao.ietf@gmail.com</email>
      </address>
    </author>

    <!-- month and day will be generated automatically by XML2RFC; be sure the year is current.-->
    <date  year="2020" />

    <area>Applications and Real-Time Area</area>
    <workgroup>CoRE Working Group</workgroup>
    <keyword>Network Management</keyword>

<abstract>
<t>This document specifies an alternative retransmission timeout and
congestion control back off algorithm for
the CoAP protocol, called Fast-Slow RTO (FASOR).</t>

<t>The algorithm specified in this document employs
an appropriate and large enough back off of Retransmission Timeout (RTO)
as the major congestion control mechanism to allow acquiring unambiguous
RTT samples with high probability
and to prevent building a persistent queue when retransmitting.
The algorithm also aims to retransmit quickly
using an accurately managed retransmission timeout when
link-errors are occuring, basing RTO calculation
on unambiguous round-trip time (RTT) samples.
</t>
</abstract>
 
   </front>

  <middle>
    <section title="Introduction">
      <t>
        CoAP senders use retransmission timeout (RTO) to infer losses that have
        occurred in the network. For such a heuristic to be correct, the RTT
        estimate used for calculating the retransmission timeout must match
        to the real end-to-end path characteristics. Otherwise, unnecessary
        retransmission may occur. Both default RTO mechanism for CoAP
        <xref target="RFC7252"/> and CoCoA <xref target="I-D.ietf-core-cocoa"/>
        have issues in dealing with unnecessary retransmissions and in the
        worst-case the situation can persist causing congestion collapse
        <xref target="JRCK18a"/>.
      </t>

      <t>
        This document specifies FASOR retransmission timeout and congestion
        control algorithm <xref target="JRCK18b"/>. FASOR algorithm ensures
        unnecessary
        retransmissions that a sender may have sent due to an inaccurate RTT
        estimate will not persist avoiding the threat of congestion
        collapse. FASOR also aims to quickly restore the accuracy of the
        RTT estimate. Armed with an accurate RTT estimate, FASOR not only
        handles congestion robustly but also can quickly infer losses due
        to link errors.
      </t>

    </section>

    <section title="Conventions">
      <t>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 BCP 14, RFC 2119 <xref
      target="RFC2119"></xref>.</t>
      
    </section>

    <!-- ********************************************* -->

    <section title="Problems with Existing CoAP Congestion Control Algorithms">
      <t>
        Correctly inferring losses requires the retransmission timeout (RTO)
        to be longer than the real RTT in the network. Under certain
        circumstances the RTO may be incorrectly small. If the real
        end-to-end RTT is larger than the retransmission timeout, it is
        impossible for the sender to avoid making unnecessary retransmissions
        that duplicate data still existing in the network because the sender
        cannot receive any feedback in time. 
        Unnecessary retransmissions
        cause two basic problems. First, they increase the perceived
        end-to-end RTT if the bottleneck has buffering capacity, and second,
        they prevent getting unambiguous RTT samples.
        Making
        unnecessary retransmissions is also a pre-condition for the congestion
        collapse <xref target="RFC0896"/>, which may occur in the worst case 
        if retransmissions are not well controlled <xref target="JRCK18a"/>.
        Therefore, the sender retransmission timeout algorithm should actively
        attempt to prevent unnecessary retransmissions from persisting under any
        circumstance.
      </t>

      <t>
        Karn's algorithm <xref target="KP87"/> has prevented unnecessary
        retransmission from turning into congestion collapse for
        decades due to robust RTT estimation and retransmission timeout
        backoff handling.
        The recent CoAP congestion control algorithms, however,
        diverge from the principles of Karn's algorithm in significant
        ways and may pose a threat to the stability of the Internet
        due to those differences.
      </t>

      <t>
        The default RTO mechanism for CoAP <xref target="RFC7252"/> uses
        only an initial RTO dithered between 2 and 3 seconds, while
        CoCoA <xref target="I-D.ietf-core-cocoa"/> measures RTT
        both from unambiguous and ambiguous RTT samples and applies a
        modified version of the TCP RTO algorithm <xref target="RFC6298"/>.

        The algorithm in RFC 7252 lacks solution to
        persistent congestion.
        The binary exponential back off used for the retransmission timeout
        does not properly address unnecessary retransmissions
        when RTT is larger than the default RTO (ACK_TIMEOUT). If the
        CoAP sender performs exchanges over an end-to-end
        path with such a high RTT, it persistently keeps making unnecessary
        retransmissions for every exchange wasting some fraction of the
        used resources (network capacity, battery power).
      </t>

      <t>
        CoCoA <xref target="I-D.ietf-core-cocoa"/> attempts to improve
        scenarios with link-error related losses and solve persistent
        congestion
        by basing its RTO value on an estimated
        RTT. However, there are couple
        of exceptions when the RTT estimation is not available:<list>
          <t>- At the beginning of a flow where initial RTO of 2 seconds
             is used.</t>
          <t>- When RTT suddenly jumps high enough to trigger the rule in
             CoCoA that prevents taking RTT samples when more than two
             retransmissions are needed. 
             This may also occur when the packet drop rate on the path is high enough.</t>
        </list>
	When RTT estimate is too small, unnecessary retransmission will
	occur also with CoCoA.
<!-- 
        Combination of these two cases occurs with 12 seconds or higher
        RTT. 
-->
        CoCoA being unable to take RTT samples at all is a particularly
        problematic phenomenon as it is similarly
        persisting state as with the algorithm outlined in RFC 7252
        and the network remains in a congestion collapsed state due
        to persisting unnecessary retransmissions.
      </t>
    
    </section>

    <section title="FASOR Algorithm">
        <t>
        FASOR <xref target="JRCK18b"/> is composed of three key
        components: RTO computation,
        Slow RTO, and novel retransmission timeout back off logic.
        </t>
      <section title="Computing Normal RTO (FastRTO)">

        <t>
        The FASOR algorithm measures the RTT for an CoAP message exchange over an end-to-end path
        and computes the RTO value using
        the TCP RTO algorithm specified in <xref target="RFC6298"/>.
        We call this normal RTO or FastRTO.
        In contrast to the TCP RTO mechanism, FASOR SHOULD NOT use
        1 second lower-bound when setting the RTO because RTO is
        only a backup mechanisms for loss detection with TCP, whereas with CoAP
        RTO is the primary and only loss detection mechanism. A lower-bound of
        1 second would impact timeliness of the loss detection in
        low RTT environments. The RTO value MAY be upper-bounded by at least 60 seconds.

        A CoAP sender using the FASOR algorithm SHOULD set initial RTO
        to 2 seconds. The computed RTO value as well as the initial RTO
        value is subject to dithering; they are dithered between RTO + 1/4 x
        SRTT and RTO + SRTT. For dithering initial RTO, SRTT is unset;
        therefore, SRTT is replaced with initial RTO / 3 which is derived
        from the RTO formula and equals to
        a hypothetical initial RTT that would yield the initial RTO
        using the SRTT and RTTVAR initialization rule of RFC 6298.
        That is, for initial RTO of 2 seconds we use SRTT value of 2/3 seconds.  
        </t>

        <t>
        FastRTO is updated only with unambiguous RTT samples.
        Therefore, it closely tracks the actual RTT of the network and can
        quickly trigger a retransmission when the network state is not dubious.
        Retransmitting without extra delay is very useful when the
        end-to-end path is subject to losses that are unrelated to
        congestion.

        When the first unambiguous RTT sample is received, the RTT estimator
        is initialized with that sample as specified in
        <xref target="RFC6298"/> except RTTVAR that is set to R/2K.
        </t>

      </section>
      <section title="Slow RTO" anchor="sec_slowrto">
        <t>
        We introduce Slow RTO as a 
        safe way to ensure that only a unique copy of message is sent
        before at least one RTT has elapsed. To achieve this the sender must ensure that
        its retransmission timeout is set to a value that is larger than
        the path end-to-end RTT that may be inflated by the unnecessary
        retransmission themselves. 

        Therefore, whenever a message needs to be retransmitted, we
        measure Slow RTO as the elapsed time required for getting an acknowledgement.
        That is, Slow RTO is measured starting from the original transmission of the
        request message until the receipt of the acknowledgement, regardless
        of the number of retransmissions.
        In this way, Slow RTO always covers the worst-case RTT during which a
        number of unnecessary retransmissions were made but the
        acknowledgement is received for the original transmission. 

        In contrast to computing normal RTO, Slow RTO is not smoothed because it is
        derived from the sending pattern of the retransmissions (that may
        turn out unnecessary). In order to drain the potential unnecessary 
        retransmissions successfully from the network, it makes sense to wait for the time used for sending
        them rather than some smoothed value. 
        However, Slow RTO is multiplied by a factor to allow some growth in load
        without making Slow RTO too aggressive (by default the factor of 1.5 is used).
        
        FASOR
        then applies Slow RTO as one of the backed off timer values used
        with the next request message.
        </t>
        
        <t>
        Slow RTO allows rapidly converging
        towards stable operating point because 1) it lets the duplicate copies
        sent earlier to drain from the network reducing the perceived
        end-to-end RTT, and 2) allows enough time to acquire an unambiguous
        RTT sample for
        the RTO computation. Robustly acquiring the RTT sample ensures that
        the next RTO is set according to the recent measurement and further
        unnecessary retransmissions are avoided.

        Slow RTO
        itself is a form of back off because it includes the
        accumulated time from the retransmission timeout back off of the previous
        exchange. FASOR uses this for its advantage as the time included
        into Slow RTO is what is needed to drain all unnecessary
        retransmissions possibly made during the previous exchange.
        Assuming a stable RTT and that all of the retransmissions were
        unnecessary, the time to drain them is the time elapsed from the
        original transmission to the sending time of the last
        retransmission plus one RTT. When the 
        acknowledgement for the original transmission arrives,
        one RTT has already elapsed, leaving only the sending time
        difference still unaccounted for which is at minimum the
        value for Slow RTO (when an RTT sample arrives
        immediately
        after the last retransmission). Even if RTT would be increasing,
        the draining still occurs
        rapidly due to exponentially backed off frequency in sending the
        unnecessary retransmissions.
        </t>

      </section>

      <section title="Retransmission Timeout Back Off Logic">
      
        <section title="Overview">
       
      
        <t>
        FASOR uses normal RTO as the base for binary exponential back off
        when no retransmission were needed for
        the previous CoAP message exchange.
        When retransmission were needed for the previous CoAP message exchange,
        the algorithm rules, however, are more
        complicated than with the traditional RTO back off because Slow
        RTO is injected into the back off series to reduce high impact
        of using Slow RTO. FASOR logic chooses
        from three possible back off series alternatives:
          <list>
          <t>FAST back off: Perform traditional RTO back off with the normal RTO
             as the base. Applied when the previous message was not retransmitted.</t>
          <t>FAST_SLOW_FAST back off: First perform a probe using the normal RTO
             for the original transmission of the request message
             to improve cases with losses unrelated to congestion.
             If the probe for the original transmission of the request message
             is successful without retransmissions, continue with FAST
             back off for the next message exchange.
             If the request message needs to be retransmitted, 
             continue by using Slow RTO for the first retransmission in order to 
             respond to congestion and drain the
             network from the unnecessary retransmissions that were
             potentially sent for the previous exchange. If still
             further RTOs are needed, continue by backing off the
             normal RTO further on each timeout. FAST_SLOW_FAST back off is applied just once
             when the previous request message using FAST back off required one or more retransmissions.</t>
          <t>SLOW_FAST back off: Perform Slow RTO first for the original 
             transmisssion to respond to congestion and to acquire an
             unambiguous RTT sample with high probability. Then, 
             if the original request needs to be retransmitted,
             continue with the normal RTO-based RTO back off
             serie by backing off the normal RTO on each timeout. 
             SLOW_FAST back off is applied
             when the previous request message using FAST_SLOW_FAST or 
             SLOW_FAST 
             back off required one or more retransmissions.
             Once an acknowledgement for the original transmission with
             unambigous RTT sample is received, continue with FAST
             back off for the next message exchange.
            </t>
        </list>
        For the initial message, FAST is used with INITIAL_RTO
        as the FastRTO value. From there on, state is updated when an
        acknowledgement arrives.
        Following unambiguous RTT samples, FASOR always
        uses FAST. Whenever retransmissions are needed, the back off
        series selection is first downgraded to FAST_SLOW_FAST back off 
        and then to SLOW_FAST back off if further retransmission are needed
        in FAST_SLOW_FAST.
        </t>

        <t>
        When Slow RTO is used as the first RTO value, the sender
        is likely to acquire unambiguous RTT sample even when the network
        has high delay due to congestion because Slow RTO is based on a
        very recent measurement of the worst-case RTT. However, using
        Slow RTO may
        negatively impact the
        performance when losses unrelated to congestion are occurring.
        Due to its potential high cost, FASOR algorithm attempts to avoid
        using Slow RTO unnecessarily.
        </t>

        <t>
        The CoAP protocol is often used by devices that are connected
        through a wireless network where non-congestion related losses
        are much more frequent than in their wired counterparts. This has
        implications for the retransmission timeout algorithm. While it
        would be possible to implement FASOR such that it immediately
        uses Slow RTO when a dubious network state is detected, which
        would handle congestion very well, it would
        do significant harm for performance when RTOs occur due to
        non-congestion related losses.
<!--    (see "Slow" variant in ADDMEref).   -->
        Instead, FASOR uses first normal RTO for one transmission and only
        responds using Slow RTO if RTO expires also for that
        request message. Such a pattern
        quickly probes if the losses were unrelated to congestion and
        only slightly delays response if real congestion event is taking
        place. To ensure that an unambiguous RTT sample is also acquired
        on a congested network path,
        FASOR then needs to use Slow RTO for the original transmission of
        the subsequent packet if the probe was not successful.
        </t>
        
        
        </section>
        
      <section title="Retransmission State Machine">
      
      <t>
       FASOR consists of the three states discussed above while making
       retranmission decisions, 
   FAST, FAST_SLOW_FAST and SLOW_FAST. 

         The state machine of the FASOR algorithm is depicted in
         <xref target="fig_statemachine"/>.

      </t>

<figure anchor="fig_statemachine" title="State Machine of FASOR">
            <artwork><![CDATA[
     +-------------------b----------------+
     |                                    |
     v                                    |
+--FAST--a-->FAST_SLOW_FAST-----a----->SLOW_FAST--+
|   ^ ^             |                         ^   |
|   | |             |                         |   |
+-b-+ +------b------+                         +-a-+
   
   a: retransmission acknowledged, ambiguous RTT sample acquired; 
   b: no retransmission, umambiguous RTT sample acquired;  
]]></artwork>

          </figure>
      
      <t>
      In the FAST state, if the original transmission of the message has not
      been acknowledged by the receiver
   within the time defined by FastRTO, the sender will retransmit it. If there is
   still no acknowledgement of the retransmitted packet within 2*FastRTO, the sender
   performs the second retransmission and if necessary, each further
   retransmission applying binary exponential back off of FastRTO. 
   The retransmission interval in this state is 
   defined as FastRTO, 2^1 * FastRTO, ..., 2^i * FastRTO. 
      </t>
      
      <t>
        When there is an acknowledgement after any retransmission,
        the sender will calculate SlowRTO value based on the algorithm
        defined in <xref target="sec_slowrto"/>. 
      </t>

      <t>
         When these is an acknowledgement after any retransmission,
         the sender will also switch to
   the second state, FAST_FLOW_FAST.  In this state, the retransmission interval is
   defined as FastRTO, Max(SlowRTO, 2*FastRTO), FastRTO * 2^1, ..., 2^i * FastRTO. 
   The state will be switched back to the FAST state once an acknowledgement
   is returned within FastRTO, i.e., no retransmission happens for a message. This is
   reasonable because it shows the network has recovered from congestion or bloated queue. 
   </t>
   
   <t>
   If some retransmission has been made before the acknowledged arrives
   in the FAST_SLOW_FAST
   state, the sender
   updates the SlowRTO value, and moves to the third state, SLOW_FAST.  The 
   retransmission interval in the SLOW_FAST state is defined as 
   SlowRTO, FastRTO, FastRTO * 2^1, ..., 2^i * FastRTO. 
   </t>
   
   <t>
   In SLOW_FAST state, the sender switches back to the FAST state
   if an unambiguous
   acknowledgement arrives. Otherwise,
   the sender stays in the SLOW_FAST state if retransmission happens again.  
      </t>

      </section>
      
      </section>

      <section title="Retransmission Count Option">

        <t> 
        When retransmissions are needed to deliver a CoAP message, it is
        not possible to measure RTT for the RTO computation as the RTT
        sample becomes ambiguous. Therefore, it would be beneficial to
        be able to distinguish whether an acknowledgement arrives for
        the original transmission of the message or for a retransmission
        of it. This would allow reliably acquiring an RTT sample for
        every CoAP message exchange and thereby compute a more accurate RTO
        even during periods of congestion and loss.
        </t>

        <t> 
        The Retransmission Count Option is used to distinguish whether an
        Acknowledgement message arrives for the original transmission or
        one of the retransmissions of a Confirmable message. However,
        the Retransmission Count Option cannot be used with an Empty
        Acknowledgement (or Reset) message because the CoAP protocol
        specification <xref target="RFC7252"/> does not allow adding
        options to an Empty message. Therefore, Retransmission Count Option
        is useful only for the common case of Piggybacked Response. In
        case of Empty Acknowledgements the operation of FASOR is the
        same as without the option. This restriction with Empty
        Acknowledgements may limit the usefulness
        of the Retransmission Count Option in deployment scenarios where
        the receiver is a proxy that will typically respond with an
        Empty Acknowledgement when it receives a request message.
        </t>

        <texttable anchor="table_rexmit_opt" title="Retransmission Count Option">
          <ttcol align='center'>No.</ttcol>
          <ttcol align='center'>C</ttcol>
          <ttcol align='center'>U</ttcol>
          <ttcol align='center'>N</ttcol>
          <ttcol align='center'>R</ttcol>
          <ttcol align='center'>Name</ttcol>
          <ttcol align='center'>Format</ttcol>
          <ttcol align='center'>Length</ttcol>
          <ttcol align='center'>Default</ttcol>
          <c>TBD</c>
          <c></c>
          <c></c>
          <c>X</c>
          <c></c>
          <c>Rexmit-Cnt</c>
          <c>uint</c>
          <c>0-1</c>
          <c>0</c>
          <postamble>C=Critical, U=Unsafe, N=NoCacheKey, R=Repeatable</postamble>
        </texttable>

        <t>
        Implementation of the Retransmission Count option is optional and it is
        identified as elective. However, when it is present in a CoAP
        message and a CoAP endpoint processes it, it MUST be processed
        as described in this document. The Retransmission Count option MUST NOT
        occur more than once in a single message. 
        </t>

        <t>
         The value of the Retransmission Count option is a variable-size (0 to 1
         byte) unsigned integer. The default value for the 
         option is the number 0 and it is represented with an empty
         option value (a zero-length sequence of bytes). However, when a
         client intends to use Retransmit Count option, it MUST reserve
         space for it by limiting the request message size also when
         the value is empty in order to fit the full-sized option into
         retransmissions.
        </t>

        <t>
        The Retransmission Count option can be present in both the request and
        response message. When the option is present in a
        request it indicates the ordinal number of the transmission for
        the request message.
        </t>

        <t> 
        If the server supports (implements) the Retransmission Count option and the option is
        present in a request, the server MUST echo the option value in
        its Piggybacked Response unmodified. If the server replies with
        an Empty Acknowledgement the server MUST silently ignore the
        option and MUST NOT include it in a later separate response to
        that request.
        </t>

        <t>
        When Piggybacked Response carrying the Retransmission Count option
        arrives, the client uses the option to match the response
        message to the corresponding transmission of the request. In
        order to measure a correct RTT, the client must store the
        timestamp for the original transmission of the request as well
        as the timestamp for each retransmission, if any, of the
        request. The resulting RTT sample is used for the RTO computation.
        If the client retransmitted the request without the option but the
        response includes the option, the client MUST silently ignore
        the option.
        </t>

        <t>
        The original transmission of a request is indicated with the
        number 0, except when sending the first request to a new
        destination endpoint (i.e., an endpoint not already in
        the memory). The first original transmission of the
        request to a new endpoint carries the number 255 (0xFF) and is
        interpreted the same as an original transmission carrying the
        number 0.
        Once the first Piggybacked Response from the new
        endpoint arrives the client learns whether or not the other
        endpoint implements the option. If the first response includes
        the echoed option, the client learns that the other endpoint
        supports the option and may continue including the option to
        each retransmitted request. From this point on the original
        transmissions of requests implicitly include the option number 0
        and a zero-byte integer will be sent according to the CoAP
        uint-encoding rules. If the first Piggybacked Response does not include the
        option, the client SHOULD stop including the option into the
        requests to that endpoint.
        Retransmissions, if any, carry the ordinal number of
        the retransmission. That is, the client increments the
        retransmission count by one for each retransmission of
        the message.
        </t>
<!--
        <t>
        This means that an original transmission of a reguest message
        always carries the option either explicitly or implicitly.
        </t>
-->
        <t>
        When the Retransmission Count option is in use, the client bases the 
        retransmission timeout for the normal RTO in the back off
        series as follows:
         <list>
          <t>
          max(RTO, Previous-RTT-Sample)
          </t>
         </list>
        Previous-RTT-Sample is the RTT sample acquired from the
        previous message exchange. If no RTT sample was available with
        the previous message exchange (e.g., the server replied with
        an Empty Acknowledgement), RTO computed earlier is used like in
        case the Retransmission Count option is not in use.
        </t>
<!-- 
        <list style="hanging" hangIndent="6">
           <t hangText="Retransmission Count:">
           Text
           </t>
       </list>
 -->

      </section>

      <section title="Alternatives for Exchanging Retransmission Count Information">
        <t>        
        An alternative way of exchanging the retransmission count
        information between a client and server is to encode it in the
        Token. The Token is a client-local identifier and a client
        solely decides how it generates the Token. Therefore, including
        a varying Token value to retransmissions of the same request
        is all possible as long as the client can use the Token to
        differentiate between requests and match a response to the
        corresponding request. The server is required to make no
        assumptions about the content or structure of a Token and
        always echo the Token unmodified in its response.
        </t>        
        <t>        
        How exactly a client encodes the retransmission count into a
        Token is an implementation issue. Note that the original
        transmission of a request may carry a zero-length Token given
        that the rules for generating a Token as specified in 
        RFC 7252 <xref target="RFC7252"/> are followed. This allows
        reducing the overhead of including the Token into the
        reguests in such cases where Token could otherwise be omitted.
        However, similar to Retransmit Count option the maximum request
        message size MUST be limited to accommodate the Token with
        retransmit count into the retransmissions of the request.
        </t>        
      </section> 

    </section>

    <section title="Security Considerations">
    </section>

    <section title="IANA Considerations">
      <t>This memo includes no request to IANA.</t>
    </section>
  </middle>

  <back>

    <!-- References Section -->

    <references title="Normative References">
      <?rfc include="reference.RFC.2119.xml"?>
      <?rfc include="reference.RFC.6298.xml"?>
      <?rfc include="reference.RFC.7252.xml"?>
    </references>

    <references title="Informative References">
      <?rfc include="reference.RFC.0896.xml"?>
      <?rfc include="reference.I-D.ietf-core-cocoa.xml"?>
      <reference anchor="KP87">
        <front>
          <title>Improving Round-trip Time Estimates in Reliable
                 Transport Protocols</title>
          <author initials="P" surname="Karn"/>
          <author initials="C" surname="Partridge"/>
          <date month="August" year="1987"/>
        </front>
        <seriesInfo name=""
                    value="SIGCOMM'87 Proceedings of the ACM Workshop on
                           Frontiers in Computer Communications Technology"/>
      </reference>
      <reference anchor="JRCK18a">
        <front>
          <title>Is CoAP Congestion Safe?</title>
          <author initials="I" surname="Jarvinen" fullname="Ilpo Jarvinen"/>
          <author initials="I" surname="Raitahila" fullname="Iivo Raitahila"/>
          <author initials="Z" surname="Cao" fullname="Zhen Cao"/>
          <author initials="M" surname="Kojo" fullname="Markku Kojo"/>
          <date month="July" year="2018"/>
        </front>
        <seriesInfo name=""
                    value="Applied Networking Research Workshop (ANRW'18)"/>
      </reference>
      <reference anchor="JRCK18b">
        <front>
          <title>FASOR Retransmission Timeout and Congestion Control Mechanism for CoAP</title>
          <author initials="I" surname="Jarvinen" fullname="Ilpo Jarvinen"/>
          <author initials="I" surname="Raitahila" fullname="Iivo Raitahila"/>
          <author initials="Z" surname="Cao" fullname="Zhen Cao"/>
          <author initials="M" surname="Kojo" fullname="Markku Kojo"/>
          <date month="December" year="2018"/>
        </front>
        <seriesInfo name=""
                    value="Proceedings of IEEE Global Communications Conference (Globecom 2018)"/>
      </reference>
    </references>

    <section anchor="app-additional" title="Pseudocode for Basic FASOR without Dithering">
        <figure anchor="fig_pseudocode">
      <artwork><![CDATA[
var state = NORMAL_RTO

rfc6298_init(var fastrto, 2 secs)

var slowrto
SLOWRTO_FACTOR = 1.5

var original_sendtime
var retransmit_count

/*
 * Sending Original Copy and Retransmitting 'req'
 */
send_request(req) {
  original_sendtime = time.now
  retransmit_count = 0

  arm_rto(calculate_rto())
  send(req)
}

rto_for(req) {
  retransmit_count += 1

  arm_rto(calculate_rto())
  send(req)
}

/*
 * ACK Processings
 */
ack() {
  sample = time.now - original_sendtime
  if (retransmit_count == 0)
    unambiguous_ack(sample)
  else
    ambiguous_ack(sample)
}

unambiguous_ack(sample) {
  k = 4                               // RFC6298 default K = 4
  if (rfc6298_is_first_sample(fastrto))
    k = 1
  rfc6298_update(fastrto, k, sample)  // Normal RFC6298 processing
  state = NORMAL_RTO
}

ambiguous_nextstate = {
  [NORMAL_RTO] = FAST_SLOW_FAST_RTO,
  [FAST_SLOW_FAST_RTO] = SLOW_FAST_RTO,
  [SLOW_FAST_RTO] = SLOW_FAST_RTO
}

ambiguous_ack(sample) {
  slowrto = sample * SLOWRTO_FACTOR
  state = ambiguous_nextstate[state]
}

/*
 * RTO Calculations
 */
calculate_rto() {
  return <state>_rtoseries()
}

normal_rtoseries() {
  switch (retransmit_count) {
    case 0: return fastrto_series_init()
    default: return fastrto_series_backoff()
  }
}

fastslowfast_rtoseries() {
  switch (retransmit_count) {
    case 0: return fastrto_series_init()
    case 1: return MAX(slowrto, 2*fastrto)
    default: return fastrto_series_backoff()
  }
}

slowfast_rtoseries() {
  switch (retransmit_count) {
    case 0: return slowrto
    case 1: return fastrto_series_init()
    default: return fastrto_series_backoff()
  }
}

var backoff_series_timer

fastrto_series_init() {
  backoff_series_timer = fastrto
  return backoff_series_timer
}

fastrto_series_backoff() {
  backoff_series_timer *= 2
  return backoff_series_timer
}
]]></artwork>
      </figure>
    </section>
  </back>
</rfc>
