tcp_yeah.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* Modified Linux module source code from /home/weixl/linux-2.6.22.6 */
  2. #define NS_PROTOCOL "tcp_yeah.c"
  3. #include "../ns-linux-c.h"
  4. #include "../ns-linux-util.h"
  5. /*
  6.  *
  7.  *   YeAH TCP
  8.  *
  9.  * For further details look at:
  10.  *    http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf
  11.  *
  12.  */
  13. #include "tcp_vegas.h"
  14. #define TCP_YEAH_ALPHA       80 //lin number of packets queued at the bottleneck
  15. #define TCP_YEAH_GAMMA        1 //lin fraction of queue to be removed per rtt
  16. #define TCP_YEAH_DELTA        3 //log minimum fraction of cwnd to be removed on loss
  17. #define TCP_YEAH_EPSILON      1 //log maximum fraction to be removed on early decongestion
  18. #define TCP_YEAH_PHY          8 //lin maximum delta from base
  19. #define TCP_YEAH_RHO         16 //lin minumum number of consecutive rtt to consider competition on loss
  20. #define TCP_YEAH_ZETA        50 //lin minimum number of state switchs to reset reno_count
  21. #define TCP_SCALABLE_AI_CNT  100U
  22. /* YeAH variables */
  23. struct yeah {
  24. struct vegas vegas; /* must be first */
  25. /* YeAH */
  26. u32 lastQ;
  27. u32 doing_reno_now;
  28. u32 reno_count;
  29. u32 fast_count;
  30. u32 pkts_acked;
  31. };
  32. static void tcp_yeah_init(struct sock *sk)
  33. {
  34. struct tcp_sock *tp = tcp_sk(sk);
  35. struct yeah *yeah = inet_csk_ca(sk);
  36. tcp_vegas_init(sk);
  37. yeah->doing_reno_now = 0;
  38. yeah->lastQ = 0;
  39. yeah->reno_count = 2;
  40. /* Ensure the MD arithmetic works.  This is somewhat pedantic,
  41.  * since I don't think we will see a cwnd this large. :) */
  42. tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
  43. }
  44. static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
  45. {
  46. const struct inet_connection_sock *icsk = inet_csk(sk);
  47. struct yeah *yeah = inet_csk_ca(sk);
  48. if (icsk->icsk_ca_state == TCP_CA_Open)
  49. yeah->pkts_acked = pkts_acked;
  50. tcp_vegas_pkts_acked(sk, pkts_acked, last);
  51. }
  52. static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack,
  53. u32 seq_rtt, u32 in_flight, int flag)
  54. {
  55. struct tcp_sock *tp = tcp_sk(sk);
  56. struct yeah *yeah = inet_csk_ca(sk);
  57. if (!tcp_is_cwnd_limited(sk, in_flight))
  58. return;
  59. if (tp->snd_cwnd <= tp->snd_ssthresh)
  60. tcp_slow_start(tp);
  61. else if (!yeah->doing_reno_now) {
  62. /* Scalable */
  63. tp->snd_cwnd_cnt+=yeah->pkts_acked;
  64. if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
  65. if (tp->snd_cwnd < tp->snd_cwnd_clamp)
  66. tp->snd_cwnd++;
  67. tp->snd_cwnd_cnt = 0;
  68. }
  69. yeah->pkts_acked = 1;
  70. } else {
  71. /* Reno */
  72. if (tp->snd_cwnd_cnt < tp->snd_cwnd)
  73. tp->snd_cwnd_cnt++;
  74. if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
  75. tp->snd_cwnd++;
  76. tp->snd_cwnd_cnt = 0;
  77. }
  78. }
  79. /* The key players are v_vegas.beg_snd_una and v_beg_snd_nxt.
  80.  *
  81.  * These are so named because they represent the approximate values
  82.  * of snd_una and snd_nxt at the beginning of the current RTT. More
  83.  * precisely, they represent the amount of data sent during the RTT.
  84.  * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
  85.  * we will calculate that (v_beg_snd_nxt - v_vegas.beg_snd_una) outstanding
  86.  * bytes of data have been ACKed during the course of the RTT, giving
  87.  * an "actual" rate of:
  88.  *
  89.  *     (v_beg_snd_nxt - v_vegas.beg_snd_una) / (rtt duration)
  90.  *
  91.  * Unfortunately, v_vegas.beg_snd_una is not exactly equal to snd_una,
  92.  * because delayed ACKs can cover more than one segment, so they
  93.  * don't line up yeahly with the boundaries of RTTs.
  94.  *
  95.  * Another unfortunate fact of life is that delayed ACKs delay the
  96.  * advance of the left edge of our send window, so that the number
  97.  * of bytes we send in an RTT is often less than our cwnd will allow.
  98.  * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
  99.  */
  100. if (after(ack, yeah->vegas.beg_snd_nxt)) {
  101. /* We do the Vegas calculations only if we got enough RTT
  102.  * samples that we can be reasonably sure that we got
  103.  * at least one RTT sample that wasn't from a delayed ACK.
  104.  * If we only had 2 samples total,
  105.  * then that means we're getting only 1 ACK per RTT, which
  106.  * means they're almost certainly delayed ACKs.
  107.  * If  we have 3 samples, we should be OK.
  108.  */
  109. if (yeah->vegas.cntRTT > 2) {
  110. u32 rtt, queue;
  111. u64 bw;
  112. /* We have enough RTT samples, so, using the Vegas
  113.  * algorithm, we determine if we should increase or
  114.  * decrease cwnd, and by how much.
  115.  */
  116. /* Pluck out the RTT we are using for the Vegas
  117.  * calculations. This is the min RTT seen during the
  118.  * last RTT. Taking the min filters out the effects
  119.  * of delayed ACKs, at the cost of noticing congestion
  120.  * a bit later.
  121.  */
  122. rtt = yeah->vegas.minRTT;
  123. /* Compute excess number of packets above bandwidth
  124.  * Avoid doing full 64 bit divide.
  125.  */
  126. bw = tp->snd_cwnd;
  127. bw *= rtt - yeah->vegas.baseRTT;
  128. do_div(bw, rtt);
  129. queue = bw;
  130. if (queue > TCP_YEAH_ALPHA ||
  131.     rtt - yeah->vegas.baseRTT > (yeah->vegas.baseRTT / TCP_YEAH_PHY)) {
  132. if (queue > TCP_YEAH_ALPHA
  133.     && tp->snd_cwnd > yeah->reno_count) {
  134. u32 reduction = min(queue / TCP_YEAH_GAMMA ,
  135.     tp->snd_cwnd >> TCP_YEAH_EPSILON);
  136. tp->snd_cwnd -= reduction;
  137. tp->snd_cwnd = max(tp->snd_cwnd,
  138.    yeah->reno_count);
  139. tp->snd_ssthresh = tp->snd_cwnd;
  140. }
  141. if (yeah->reno_count <= 2)
  142. yeah->reno_count = max(tp->snd_cwnd>>1, 2U);
  143. else
  144. yeah->reno_count++;
  145. yeah->doing_reno_now = min(yeah->doing_reno_now + 1,
  146.    0xffffffU);
  147. } else {
  148. yeah->fast_count++;
  149. if (yeah->fast_count > TCP_YEAH_ZETA) {
  150. yeah->reno_count = 2;
  151. yeah->fast_count = 0;
  152. }
  153. yeah->doing_reno_now = 0;
  154. }
  155. yeah->lastQ = queue;
  156. }
  157. /* Save the extent of the current window so we can use this
  158.  * at the end of the next RTT.
  159.  */
  160. yeah->vegas.beg_snd_una  = yeah->vegas.beg_snd_nxt;
  161. yeah->vegas.beg_snd_nxt  = tp->snd_nxt;
  162. yeah->vegas.beg_snd_cwnd = tp->snd_cwnd;
  163. /* Wipe the slate clean for the next RTT. */
  164. yeah->vegas.cntRTT = 0;
  165. yeah->vegas.minRTT = 0x7fffffff;
  166. }
  167. }
  168. static u32 tcp_yeah_ssthresh(struct sock *sk) {
  169. const struct tcp_sock *tp = tcp_sk(sk);
  170. struct yeah *yeah = inet_csk_ca(sk);
  171. u32 reduction;
  172. if (yeah->doing_reno_now < TCP_YEAH_RHO) {
  173. reduction = yeah->lastQ;
  174. reduction = min( reduction, max(tp->snd_cwnd>>1, 2U) );
  175. reduction = max( reduction, tp->snd_cwnd >> TCP_YEAH_DELTA);
  176. } else
  177. reduction = max(tp->snd_cwnd>>1,2U);
  178. yeah->fast_count = 0;
  179. yeah->reno_count = max(yeah->reno_count>>1, 2U);
  180. return tp->snd_cwnd - reduction;
  181. }
  182. static struct tcp_congestion_ops tcp_yeah = {
  183. .flags = TCP_CONG_RTT_STAMP,
  184. .init = tcp_yeah_init,
  185. .ssthresh = tcp_yeah_ssthresh,
  186. .cong_avoid = tcp_yeah_cong_avoid,
  187. .min_cwnd = tcp_reno_min_cwnd,
  188. .set_state = tcp_vegas_state,
  189. .cwnd_event = tcp_vegas_cwnd_event,
  190. .get_info = tcp_vegas_get_info,
  191. .pkts_acked = tcp_yeah_pkts_acked,
  192. .owner = THIS_MODULE,
  193. .name = "yeah",
  194. };
  195. static int __init tcp_yeah_register(void)
  196. {
  197. BUG_ON(sizeof(struct yeah) > ICSK_CA_PRIV_SIZE);
  198. tcp_register_congestion_control(&tcp_yeah);
  199. return 0;
  200. }
  201. static void __exit tcp_yeah_unregister(void)
  202. {
  203. tcp_unregister_congestion_control(&tcp_yeah);
  204. }
  205. module_init(tcp_yeah_register);
  206. module_exit(tcp_yeah_unregister);
  207. MODULE_AUTHOR("Angelo P. Castellani");
  208. MODULE_LICENSE("GPL");
  209. MODULE_DESCRIPTION("YeAH TCP");
  210. #undef NS_PROTOCOL