tcp_highspeed.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Sally Floyd's High Speed TCP (RFC 3649) congestion control
  4. *
  5. * See https://www.icir.org/floyd/hstcp.html
  6. *
  7. * John Heffner <jheffner@psc.edu>
  8. */
  9. #include <linux/module.h>
  10. #include <net/tcp.h>
  11. /* From AIMD tables from RFC 3649 appendix B,
  12. * with fixed-point MD scaled <<8.
  13. */
  14. static const struct hstcp_aimd_val {
  15. unsigned int cwnd;
  16. unsigned int md;
  17. } hstcp_aimd_vals[] = {
  18. { 38, 128, /* 0.50 */ },
  19. { 118, 112, /* 0.44 */ },
  20. { 221, 104, /* 0.41 */ },
  21. { 347, 98, /* 0.38 */ },
  22. { 495, 93, /* 0.37 */ },
  23. { 663, 89, /* 0.35 */ },
  24. { 851, 86, /* 0.34 */ },
  25. { 1058, 83, /* 0.33 */ },
  26. { 1284, 81, /* 0.32 */ },
  27. { 1529, 78, /* 0.31 */ },
  28. { 1793, 76, /* 0.30 */ },
  29. { 2076, 74, /* 0.29 */ },
  30. { 2378, 72, /* 0.28 */ },
  31. { 2699, 71, /* 0.28 */ },
  32. { 3039, 69, /* 0.27 */ },
  33. { 3399, 68, /* 0.27 */ },
  34. { 3778, 66, /* 0.26 */ },
  35. { 4177, 65, /* 0.26 */ },
  36. { 4596, 64, /* 0.25 */ },
  37. { 5036, 62, /* 0.25 */ },
  38. { 5497, 61, /* 0.24 */ },
  39. { 5979, 60, /* 0.24 */ },
  40. { 6483, 59, /* 0.23 */ },
  41. { 7009, 58, /* 0.23 */ },
  42. { 7558, 57, /* 0.22 */ },
  43. { 8130, 56, /* 0.22 */ },
  44. { 8726, 55, /* 0.22 */ },
  45. { 9346, 54, /* 0.21 */ },
  46. { 9991, 53, /* 0.21 */ },
  47. { 10661, 52, /* 0.21 */ },
  48. { 11358, 52, /* 0.20 */ },
  49. { 12082, 51, /* 0.20 */ },
  50. { 12834, 50, /* 0.20 */ },
  51. { 13614, 49, /* 0.19 */ },
  52. { 14424, 48, /* 0.19 */ },
  53. { 15265, 48, /* 0.19 */ },
  54. { 16137, 47, /* 0.19 */ },
  55. { 17042, 46, /* 0.18 */ },
  56. { 17981, 45, /* 0.18 */ },
  57. { 18955, 45, /* 0.18 */ },
  58. { 19965, 44, /* 0.17 */ },
  59. { 21013, 43, /* 0.17 */ },
  60. { 22101, 43, /* 0.17 */ },
  61. { 23230, 42, /* 0.17 */ },
  62. { 24402, 41, /* 0.16 */ },
  63. { 25618, 41, /* 0.16 */ },
  64. { 26881, 40, /* 0.16 */ },
  65. { 28193, 39, /* 0.16 */ },
  66. { 29557, 39, /* 0.15 */ },
  67. { 30975, 38, /* 0.15 */ },
  68. { 32450, 38, /* 0.15 */ },
  69. { 33986, 37, /* 0.15 */ },
  70. { 35586, 36, /* 0.14 */ },
  71. { 37253, 36, /* 0.14 */ },
  72. { 38992, 35, /* 0.14 */ },
  73. { 40808, 35, /* 0.14 */ },
  74. { 42707, 34, /* 0.13 */ },
  75. { 44694, 33, /* 0.13 */ },
  76. { 46776, 33, /* 0.13 */ },
  77. { 48961, 32, /* 0.13 */ },
  78. { 51258, 32, /* 0.13 */ },
  79. { 53677, 31, /* 0.12 */ },
  80. { 56230, 30, /* 0.12 */ },
  81. { 58932, 30, /* 0.12 */ },
  82. { 61799, 29, /* 0.12 */ },
  83. { 64851, 28, /* 0.11 */ },
  84. { 68113, 28, /* 0.11 */ },
  85. { 71617, 27, /* 0.11 */ },
  86. { 75401, 26, /* 0.10 */ },
  87. { 79517, 26, /* 0.10 */ },
  88. { 84035, 25, /* 0.10 */ },
  89. { 89053, 24, /* 0.10 */ },
  90. };
  91. #define HSTCP_AIMD_MAX ARRAY_SIZE(hstcp_aimd_vals)
  92. struct hstcp {
  93. u32 ai;
  94. };
  95. static void hstcp_init(struct sock *sk)
  96. {
  97. struct tcp_sock *tp = tcp_sk(sk);
  98. struct hstcp *ca = inet_csk_ca(sk);
  99. ca->ai = 0;
  100. /* Ensure the MD arithmetic works. This is somewhat pedantic,
  101. * since I don't think we will see a cwnd this large. :) */
  102. tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
  103. }
  104. static void hstcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
  105. {
  106. struct tcp_sock *tp = tcp_sk(sk);
  107. struct hstcp *ca = inet_csk_ca(sk);
  108. if (!tcp_is_cwnd_limited(sk))
  109. return;
  110. if (tcp_in_slow_start(tp))
  111. tcp_slow_start(tp, acked);
  112. else {
  113. /* Update AIMD parameters.
  114. *
  115. * We want to guarantee that:
  116. * hstcp_aimd_vals[ca->ai-1].cwnd <
  117. * snd_cwnd <=
  118. * hstcp_aimd_vals[ca->ai].cwnd
  119. */
  120. if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
  121. while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
  122. ca->ai < HSTCP_AIMD_MAX - 1)
  123. ca->ai++;
  124. } else if (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd) {
  125. while (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd)
  126. ca->ai--;
  127. }
  128. /* Do additive increase */
  129. if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
  130. /* cwnd = cwnd + a(w) / cwnd */
  131. tp->snd_cwnd_cnt += ca->ai + 1;
  132. if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
  133. tp->snd_cwnd_cnt -= tp->snd_cwnd;
  134. tp->snd_cwnd++;
  135. }
  136. }
  137. }
  138. }
  139. static u32 hstcp_ssthresh(struct sock *sk)
  140. {
  141. const struct tcp_sock *tp = tcp_sk(sk);
  142. struct hstcp *ca = inet_csk_ca(sk);
  143. /* Do multiplicative decrease */
  144. return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
  145. }
  146. static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
  147. .init = hstcp_init,
  148. .ssthresh = hstcp_ssthresh,
  149. .undo_cwnd = tcp_reno_undo_cwnd,
  150. .cong_avoid = hstcp_cong_avoid,
  151. .owner = THIS_MODULE,
  152. .name = "highspeed"
  153. };
  154. static int __init hstcp_register(void)
  155. {
  156. BUILD_BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
  157. return tcp_register_congestion_control(&tcp_highspeed);
  158. }
  159. static void __exit hstcp_unregister(void)
  160. {
  161. tcp_unregister_congestion_control(&tcp_highspeed);
  162. }
  163. module_init(hstcp_register);
  164. module_exit(hstcp_unregister);
  165. MODULE_AUTHOR("John Heffner");
  166. MODULE_LICENSE("GPL");
  167. MODULE_DESCRIPTION("High Speed TCP");