tcp_yeah.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <linux/mm.h>
  2. #include <linux/module.h>
  3. #include <linux/skbuff.h>
  4. #include <linux/inet_diag.h>
  5. #include <asm/div64.h>
  6. #include <net/tcp.h>
  7. /* Vegas variables */
  8. struct vegas {
  9. u32 beg_snd_nxt; /* right edge during last RTT */
  10. u32 beg_snd_una; /* left edge during last RTT */
  11. u32 beg_snd_cwnd; /* saves the size of the cwnd */
  12. u8 doing_vegas_now;/* if true, do vegas for this RTT */
  13. u16 cntRTT; /* # of RTTs measured within last RTT */
  14. u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
  15. u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
  16. };
  17. /* There are several situations when we must "re-start" Vegas:
  18. *
  19. * o when a connection is established
  20. * o after an RTO
  21. * o after fast recovery
  22. * o when we send a packet and there is no outstanding
  23. * unacknowledged data (restarting an idle connection)
  24. *
  25. * In these circumstances we cannot do a Vegas calculation at the
  26. * end of the first RTT, because any calculation we do is using
  27. * stale info -- both the saved cwnd and congestion feedback are
  28. * stale.
  29. *
  30. * Instead we must wait until the completion of an RTT during
  31. * which we actually receive ACKs.
  32. */
  33. static inline void vegas_enable(struct sock *sk)
  34. {
  35. const struct tcp_sock *tp = tcp_sk(sk);
  36. struct vegas *vegas = inet_csk_ca(sk);
  37. /* Begin taking Vegas samples next time we send something. */
  38. vegas->doing_vegas_now = 1;
  39. /* Set the beginning of the next send window. */
  40. vegas->beg_snd_nxt = tp->snd_nxt;
  41. vegas->cntRTT = 0;
  42. vegas->minRTT = 0x7fffffff;
  43. }
  44. /* Stop taking Vegas samples for now. */
  45. static inline void vegas_disable(struct sock *sk)
  46. {
  47. struct vegas *vegas = inet_csk_ca(sk);
  48. vegas->doing_vegas_now = 0;
  49. }
  50. static void tcp_vegas_init(struct sock *sk)
  51. {
  52. struct vegas *vegas = inet_csk_ca(sk);
  53. vegas->baseRTT = 0x7fffffff;
  54. vegas_enable(sk);
  55. }
  56. static void tcp_vegas_state(struct sock *sk, u8 ca_state)
  57. {
  58. if (ca_state == TCP_CA_Open)
  59. vegas_enable(sk);
  60. else
  61. vegas_disable(sk);
  62. }
  63. /* Do RTT sampling needed for Vegas.
  64. * Basically we:
  65. * o min-filter RTT samples from within an RTT to get the current
  66. * propagation delay + queuing delay (we are min-filtering to try to
  67. * avoid the effects of delayed ACKs)
  68. * o min-filter RTT samples from a much longer window (forever for now)
  69. * to find the propagation delay (baseRTT)
  70. */
  71. static void tcp_vegas_rtt_calc(struct sock *sk, u32 usrtt)
  72. {
  73. struct vegas *vegas = inet_csk_ca(sk);
  74. u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
  75. /* Filter to find propagation delay: */
  76. if (vrtt < vegas->baseRTT)
  77. vegas->baseRTT = vrtt;
  78. /* Find the min RTT during the last RTT to find
  79. * the current prop. delay + queuing delay:
  80. */
  81. vegas->minRTT = min(vegas->minRTT, vrtt);
  82. vegas->cntRTT++;
  83. }
  84. /*
  85. * If the connection is idle and we are restarting,
  86. * then we don't want to do any Vegas calculations
  87. * until we get fresh RTT samples. So when we
  88. * restart, we reset our Vegas state to a clean
  89. * slate. After we get acks for this flight of
  90. * packets, _then_ we can make Vegas calculations
  91. * again.
  92. */
  93. static void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event)
  94. {
  95. if (event == CA_EVENT_CWND_RESTART ||
  96. event == CA_EVENT_TX_START)
  97. tcp_vegas_init(sk);
  98. }
  99. /* Extract info for Tcp socket info provided via netlink. */
  100. static void tcp_vegas_get_info(struct sock *sk, u32 ext,
  101. struct sk_buff *skb)
  102. {
  103. const struct vegas *ca = inet_csk_ca(sk);
  104. if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
  105. struct tcpvegas_info *info;
  106. info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
  107. sizeof(*info)));
  108. info->tcpv_enabled = ca->doing_vegas_now;
  109. info->tcpv_rttcnt = ca->cntRTT;
  110. info->tcpv_rtt = ca->baseRTT;
  111. info->tcpv_minrtt = ca->minRTT;
  112. rtattr_failure: ;
  113. }
  114. }