### tcp中RTO的計算以及linux下的實現

 1 2 `SRTT = ( ALPHA * SRTT ) + ((1-ALPHA) * RTT)` `  ` `RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]]`

 1 2 3 `Err ≡ m−a` `a←a+gErr` `v ← v+g(|Err|−v)`

 1 2 `2^na ← 2^na+Err ` `2^nv ← 2^nv+(|Err|−v)`

 1 2 3 4 5 6 7 8 9 `/∗ update Average estimator ∗/` `m −= (sa >> 3); ` `sa += m;` `/∗ update Deviation estimator ∗/` `if` `(m < 0)` `   ` `m = −m; ` `m −= (sv >> 2);` `sv += m;` `rto = (sa >> 3) + sv;`

 1 2 3 `SRTT <- R` `RTTVAR <- R/2 ` `RTO <- SRTT + max (G, K*RTTVAR)`

 1 2 3 `RTTVAR <- (1 - beta) * RTTVAR + beta * |SRTT - R'| ` `SRTT <- (1 - alpha) * SRTT + alpha * R'  ` `RTO <- SRTT + max (G, 4*RTTVAR) `

 1 `SRTT <- (1 - alpha) * SRTT + alpha * R'`

 1 `SRTT <- SRTT - SRTT*alpha + alpha*R` => SRTT <- SRTT + alpha*(R` - SRTT)`

linux下對應的計算是在tcp_rtt_estimator這個函數中，這個函數的第二個參數，就是當前最新的rtt值。linux的實現多了兩個東西，分別是mdev和medev_max, 其中mdev就是上面計算方法中的RTTVAR，而mdev_max則就是每次均差的最大值(linux最小是50毫秒).而在linux中RTTVAR也就等於mdev_max.

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 `    ` `u32 srtt;       ` `/* smoothed round trip time << 3  */` `    ` `u32 mdev;       ` `/* medium deviation         */` `    ` `u32 mdev_max;   ` `/* maximal mdev for the last rtt period */` `    ` `u32 rttvar;     ` `/* smoothed mdev_max            */` `    ` `u32 rtt_seq;    ` `/* sequence number to update rttvar */`   `static` `void` `tcp_rtt_estimator(` `struct` `sock *sk, ` `const` `__u32 mrtt)` `{` `    ` `struct` `tcp_sock *tp = tcp_sk(sk);` `    ` `long` `m = mrtt; ` `/* RTT */`   `    ` `/*  The following amusing code comes from Jacobson's` `     ` `*  article in SIGCOMM '88.  Note that rtt and mdev` `     ` `*  are scaled versions of rtt and mean deviation.` `     ` `*  This is designed to be as fast as possible` `     ` `*  m stands for "measurement".` `     ` `*` `     ` `*  On a 1990 paper the rto value is changed to:` `     ` `*  RTO = rtt + 4 * mdev` `     ` `*` `     ` `* Funny. This algorithm seems to be very broken.` `     ` `* These formulae increase RTO, when it should be decreased, increase` `     ` `* too slowly, when it should be increased quickly, decrease too quickly` `     ` `* etc. I guess in BSD RTO takes ONE value, so that it is absolutely` `     ` `* does not matter how to _calculate_ it. Seems, it was trap` `     ` `* that VJ failed to avoid. 8)` `     ` `*/` `    ` `if` `(m == 0)` `        ` `m = 1;` `    ` `if` `(tp->srtt != 0) {` `//開始更新a也就是srtt.可以看到因子為1/8.` `        ` `m -= (tp->srtt >> 3);  ` `/* m is now error in rtt est */` `        ` `tp->srtt += m;       ` `/* rtt = 7/8 rtt + 1/8 new */` `//開始更新mean deviation.` `        ` `if` `(m < 0) {` `            ` `m = -m;     ` `/* m is now abs(error) */` `            ` `m -= (tp->mdev >> 2);   ` `/* similar update on mdev */` `            ` `/* This is similar to one of Eifel findings.` `             ` `* Eifel blocks mdev updates when rtt decreases.` `             ` `* This solution is a bit different: we use finer gain` `             ` `* for mdev in this case (alpha*beta).` `             ` `* Like Eifel it also prevents growth of rto,` `             ` `* but also it limits too fast rto decreases,` `             ` `* happening in pure Eifel.` `             ` `*/` `            ` `if` `(m > 0)` `                ` `m >>= 3;` `        ` `} ` `else` `{` `            ` `m -= (tp->mdev >> 2);   ` `/* similar update on mdev */` `        ` `}` `        ` `tp->mdev += m;           ` `/* mdev = 3/4 mdev + 1/4 new */` `//找到最大值付給rttvar` `        ` `if` `(tp->mdev > tp->mdev_max) {` `            ` `tp->mdev_max = tp->mdev;` `            ` `if` `(tp->mdev_max > tp->rttvar)` `                ` `tp->rttvar = tp->mdev_max;` `        ` `}`   `//本次RTT的估算結束` `        ` `if` `(after(tp->snd_una, tp->rtt_seq)) {` `//調節rttvar` `            ` `if` `(tp->mdev_max < tp->rttvar)` `                ` `tp->rttvar -= (tp->rttvar - tp->mdev_max) >> 2;` `            ` `tp->rtt_seq = tp->snd_nxt;` `//設置最小值` `            ` `tp->mdev_max = tcp_rto_min(sk);` `        ` `}` `    ` `} ` `else` `{` `//第一次進來的情況` `        ` `/* no previous measure. */` `        ` `tp->srtt = m << 3; ` `/* take the measured time to be rtt */` `        ` `tp->mdev = m << 1; ` `/* make sure rto = 3*rtt */` `        ` `tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));` `        ` `tp->rtt_seq = tp->snd_nxt;` `    ` `}` `}`

 1 2 3 4 `static` `inline` `u32 __tcp_set_rto(` `const` `struct` `tcp_sock *tp)` `{` `    ` `return` `(tp->srtt >> 3) + tp->rttvar;` `}`

http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/4/html/Release_Notes/U7/ppc/ar01s04.html