Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* RTT/RTO calculation.
0003  *
0004  * Adapted from TCP for AF_RXRPC by David Howells (dhowells@redhat.com)
0005  *
0006  * https://tools.ietf.org/html/rfc6298
0007  * https://tools.ietf.org/html/rfc1122#section-4.2.3.1
0008  * http://ccr.sigcomm.org/archive/1995/jan95/ccr-9501-partridge87.pdf
0009  */
0010 
0011 #include <linux/net.h>
0012 #include "ar-internal.h"
0013 
0014 #define RXRPC_RTO_MAX   ((unsigned)(120 * HZ))
0015 #define RXRPC_TIMEOUT_INIT ((unsigned)(1*HZ))   /* RFC6298 2.1 initial RTO value    */
0016 #define rxrpc_jiffies32 ((u32)jiffies)      /* As rxrpc_jiffies32 */
0017 
0018 static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer)
0019 {
0020     return 200;
0021 }
0022 
0023 static u32 __rxrpc_set_rto(const struct rxrpc_peer *peer)
0024 {
0025     return usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us);
0026 }
0027 
0028 static u32 rxrpc_bound_rto(u32 rto)
0029 {
0030     return min(rto, RXRPC_RTO_MAX);
0031 }
0032 
0033 /*
0034  * Called to compute a smoothed rtt estimate. The data fed to this
0035  * routine either comes from timestamps, or from segments that were
0036  * known _not_ to have been retransmitted [see Karn/Partridge
0037  * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
0038  * piece by Van Jacobson.
0039  * NOTE: the next three routines used to be one big routine.
0040  * To save cycles in the RFC 1323 implementation it was better to break
0041  * it up into three procedures. -- erics
0042  */
0043 static void rxrpc_rtt_estimator(struct rxrpc_peer *peer, long sample_rtt_us)
0044 {
0045     long m = sample_rtt_us; /* RTT */
0046     u32 srtt = peer->srtt_us;
0047 
0048     /*  The following amusing code comes from Jacobson's
0049      *  article in SIGCOMM '88.  Note that rtt and mdev
0050      *  are scaled versions of rtt and mean deviation.
0051      *  This is designed to be as fast as possible
0052      *  m stands for "measurement".
0053      *
0054      *  On a 1990 paper the rto value is changed to:
0055      *  RTO = rtt + 4 * mdev
0056      *
0057      * Funny. This algorithm seems to be very broken.
0058      * These formulae increase RTO, when it should be decreased, increase
0059      * too slowly, when it should be increased quickly, decrease too quickly
0060      * etc. I guess in BSD RTO takes ONE value, so that it is absolutely
0061      * does not matter how to _calculate_ it. Seems, it was trap
0062      * that VJ failed to avoid. 8)
0063      */
0064     if (srtt != 0) {
0065         m -= (srtt >> 3);   /* m is now error in rtt est */
0066         srtt += m;      /* rtt = 7/8 rtt + 1/8 new */
0067         if (m < 0) {
0068             m = -m;     /* m is now abs(error) */
0069             m -= (peer->mdev_us >> 2);   /* similar update on mdev */
0070             /* This is similar to one of Eifel findings.
0071              * Eifel blocks mdev updates when rtt decreases.
0072              * This solution is a bit different: we use finer gain
0073              * for mdev in this case (alpha*beta).
0074              * Like Eifel it also prevents growth of rto,
0075              * but also it limits too fast rto decreases,
0076              * happening in pure Eifel.
0077              */
0078             if (m > 0)
0079                 m >>= 3;
0080         } else {
0081             m -= (peer->mdev_us >> 2);   /* similar update on mdev */
0082         }
0083 
0084         peer->mdev_us += m;     /* mdev = 3/4 mdev + 1/4 new */
0085         if (peer->mdev_us > peer->mdev_max_us) {
0086             peer->mdev_max_us = peer->mdev_us;
0087             if (peer->mdev_max_us > peer->rttvar_us)
0088                 peer->rttvar_us = peer->mdev_max_us;
0089         }
0090     } else {
0091         /* no previous measure. */
0092         srtt = m << 3;      /* take the measured time to be rtt */
0093         peer->mdev_us = m << 1; /* make sure rto = 3*rtt */
0094         peer->rttvar_us = max(peer->mdev_us, rxrpc_rto_min_us(peer));
0095         peer->mdev_max_us = peer->rttvar_us;
0096     }
0097 
0098     peer->srtt_us = max(1U, srtt);
0099 }
0100 
0101 /*
0102  * Calculate rto without backoff.  This is the second half of Van Jacobson's
0103  * routine referred to above.
0104  */
0105 static void rxrpc_set_rto(struct rxrpc_peer *peer)
0106 {
0107     u32 rto;
0108 
0109     /* 1. If rtt variance happened to be less 50msec, it is hallucination.
0110      *    It cannot be less due to utterly erratic ACK generation made
0111      *    at least by solaris and freebsd. "Erratic ACKs" has _nothing_
0112      *    to do with delayed acks, because at cwnd>2 true delack timeout
0113      *    is invisible. Actually, Linux-2.4 also generates erratic
0114      *    ACKs in some circumstances.
0115      */
0116     rto = __rxrpc_set_rto(peer);
0117 
0118     /* 2. Fixups made earlier cannot be right.
0119      *    If we do not estimate RTO correctly without them,
0120      *    all the algo is pure shit and should be replaced
0121      *    with correct one. It is exactly, which we pretend to do.
0122      */
0123 
0124     /* NOTE: clamping at RXRPC_RTO_MIN is not required, current algo
0125      * guarantees that rto is higher.
0126      */
0127     peer->rto_j = rxrpc_bound_rto(rto);
0128 }
0129 
0130 static void rxrpc_ack_update_rtt(struct rxrpc_peer *peer, long rtt_us)
0131 {
0132     if (rtt_us < 0)
0133         return;
0134 
0135     //rxrpc_update_rtt_min(peer, rtt_us);
0136     rxrpc_rtt_estimator(peer, rtt_us);
0137     rxrpc_set_rto(peer);
0138 
0139     /* RFC6298: only reset backoff on valid RTT measurement. */
0140     peer->backoff = 0;
0141 }
0142 
0143 /*
0144  * Add RTT information to cache.  This is called in softirq mode and has
0145  * exclusive access to the peer RTT data.
0146  */
0147 void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
0148             int rtt_slot,
0149             rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
0150             ktime_t send_time, ktime_t resp_time)
0151 {
0152     struct rxrpc_peer *peer = call->peer;
0153     s64 rtt_us;
0154 
0155     rtt_us = ktime_to_us(ktime_sub(resp_time, send_time));
0156     if (rtt_us < 0)
0157         return;
0158 
0159     spin_lock(&peer->rtt_input_lock);
0160     rxrpc_ack_update_rtt(peer, rtt_us);
0161     if (peer->rtt_count < 3)
0162         peer->rtt_count++;
0163     spin_unlock(&peer->rtt_input_lock);
0164 
0165     trace_rxrpc_rtt_rx(call, why, rtt_slot, send_serial, resp_serial,
0166                peer->srtt_us >> 3, peer->rto_j);
0167 }
0168 
0169 /*
0170  * Get the retransmission timeout to set in jiffies, backing it off each time
0171  * we retransmit.
0172  */
0173 unsigned long rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans)
0174 {
0175     u64 timo_j;
0176     u8 backoff = READ_ONCE(peer->backoff);
0177 
0178     timo_j = peer->rto_j;
0179     timo_j <<= backoff;
0180     if (retrans && timo_j * 2 <= RXRPC_RTO_MAX)
0181         WRITE_ONCE(peer->backoff, backoff + 1);
0182 
0183     if (timo_j < 1)
0184         timo_j = 1;
0185 
0186     return timo_j;
0187 }
0188 
0189 void rxrpc_peer_init_rtt(struct rxrpc_peer *peer)
0190 {
0191     peer->rto_j = RXRPC_TIMEOUT_INIT;
0192     peer->mdev_us   = jiffies_to_usecs(RXRPC_TIMEOUT_INIT);
0193     peer->backoff   = 0;
0194     //minmax_reset(&peer->rtt_min, rxrpc_jiffies32, ~0U);
0195 }