Blame view

net/ipv4/tcp_highspeed.c 4.92 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
a628d29b5   John Heffner   [TCP]: Add High S...
2
3
4
  /*
   * Sally Floyd's High Speed TCP (RFC 3649) congestion control
   *
7a6498ebc   Alexander A. Klimov   Replace HTTP link...
5
   * See https://www.icir.org/floyd/hstcp.html
a628d29b5   John Heffner   [TCP]: Add High S...
6
7
8
   *
   * John Heffner <jheffner@psc.edu>
   */
a628d29b5   John Heffner   [TCP]: Add High S...
9
10
  #include <linux/module.h>
  #include <net/tcp.h>
a628d29b5   John Heffner   [TCP]: Add High S...
11
12
13
14
  /* From AIMD tables from RFC 3649 appendix B,
   * with fixed-point MD scaled <<8.
   */
  static const struct hstcp_aimd_val {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
15
16
  	unsigned int cwnd;
  	unsigned int md;
a628d29b5   John Heffner   [TCP]: Add High S...
17
  } hstcp_aimd_vals[] = {
688d1945b   stephen hemminger   tcp: whitespace f...
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
77
78
79
80
81
82
83
84
85
86
87
88
89
  	{     38,  128, /*  0.50 */ },
  	{    118,  112, /*  0.44 */ },
  	{    221,  104, /*  0.41 */ },
  	{    347,   98, /*  0.38 */ },
  	{    495,   93, /*  0.37 */ },
  	{    663,   89, /*  0.35 */ },
  	{    851,   86, /*  0.34 */ },
  	{   1058,   83, /*  0.33 */ },
  	{   1284,   81, /*  0.32 */ },
  	{   1529,   78, /*  0.31 */ },
  	{   1793,   76, /*  0.30 */ },
  	{   2076,   74, /*  0.29 */ },
  	{   2378,   72, /*  0.28 */ },
  	{   2699,   71, /*  0.28 */ },
  	{   3039,   69, /*  0.27 */ },
  	{   3399,   68, /*  0.27 */ },
  	{   3778,   66, /*  0.26 */ },
  	{   4177,   65, /*  0.26 */ },
  	{   4596,   64, /*  0.25 */ },
  	{   5036,   62, /*  0.25 */ },
  	{   5497,   61, /*  0.24 */ },
  	{   5979,   60, /*  0.24 */ },
  	{   6483,   59, /*  0.23 */ },
  	{   7009,   58, /*  0.23 */ },
  	{   7558,   57, /*  0.22 */ },
  	{   8130,   56, /*  0.22 */ },
  	{   8726,   55, /*  0.22 */ },
  	{   9346,   54, /*  0.21 */ },
  	{   9991,   53, /*  0.21 */ },
  	{  10661,   52, /*  0.21 */ },
  	{  11358,   52, /*  0.20 */ },
  	{  12082,   51, /*  0.20 */ },
  	{  12834,   50, /*  0.20 */ },
  	{  13614,   49, /*  0.19 */ },
  	{  14424,   48, /*  0.19 */ },
  	{  15265,   48, /*  0.19 */ },
  	{  16137,   47, /*  0.19 */ },
  	{  17042,   46, /*  0.18 */ },
  	{  17981,   45, /*  0.18 */ },
  	{  18955,   45, /*  0.18 */ },
  	{  19965,   44, /*  0.17 */ },
  	{  21013,   43, /*  0.17 */ },
  	{  22101,   43, /*  0.17 */ },
  	{  23230,   42, /*  0.17 */ },
  	{  24402,   41, /*  0.16 */ },
  	{  25618,   41, /*  0.16 */ },
  	{  26881,   40, /*  0.16 */ },
  	{  28193,   39, /*  0.16 */ },
  	{  29557,   39, /*  0.15 */ },
  	{  30975,   38, /*  0.15 */ },
  	{  32450,   38, /*  0.15 */ },
  	{  33986,   37, /*  0.15 */ },
  	{  35586,   36, /*  0.14 */ },
  	{  37253,   36, /*  0.14 */ },
  	{  38992,   35, /*  0.14 */ },
  	{  40808,   35, /*  0.14 */ },
  	{  42707,   34, /*  0.13 */ },
  	{  44694,   33, /*  0.13 */ },
  	{  46776,   33, /*  0.13 */ },
  	{  48961,   32, /*  0.13 */ },
  	{  51258,   32, /*  0.13 */ },
  	{  53677,   31, /*  0.12 */ },
  	{  56230,   30, /*  0.12 */ },
  	{  58932,   30, /*  0.12 */ },
  	{  61799,   29, /*  0.12 */ },
  	{  64851,   28, /*  0.11 */ },
  	{  68113,   28, /*  0.11 */ },
  	{  71617,   27, /*  0.11 */ },
  	{  75401,   26, /*  0.10 */ },
  	{  79517,   26, /*  0.10 */ },
  	{  84035,   25, /*  0.10 */ },
  	{  89053,   24, /*  0.10 */ },
a628d29b5   John Heffner   [TCP]: Add High S...
90
91
92
93
94
95
96
  };
  
  #define HSTCP_AIMD_MAX	ARRAY_SIZE(hstcp_aimd_vals)
  
  struct hstcp {
  	u32	ai;
  };
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
97
  static void hstcp_init(struct sock *sk)
a628d29b5   John Heffner   [TCP]: Add High S...
98
  {
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
99
100
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct hstcp *ca = inet_csk_ca(sk);
a628d29b5   John Heffner   [TCP]: Add High S...
101
102
103
104
105
106
107
  
  	ca->ai = 0;
  
  	/* Ensure the MD arithmetic works.  This is somewhat pedantic,
  	 * since I don't think we will see a cwnd this large. :) */
  	tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
  }
249015515   Eric Dumazet   tcp: remove in_fl...
108
  static void hstcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
a628d29b5   John Heffner   [TCP]: Add High S...
109
  {
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
110
111
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct hstcp *ca = inet_csk_ca(sk);
a628d29b5   John Heffner   [TCP]: Add High S...
112

249015515   Eric Dumazet   tcp: remove in_fl...
113
  	if (!tcp_is_cwnd_limited(sk))
a628d29b5   John Heffner   [TCP]: Add High S...
114
  		return;
071d5080e   Yuchung Cheng   tcp: add tcp_in_s...
115
  	if (tcp_in_slow_start(tp))
9f9843a75   Yuchung Cheng   tcp: properly han...
116
  		tcp_slow_start(tp, acked);
03fba0479   Ilpo Järvinen   [TCP] Highspeed: ...
117
  	else {
6150c22e2   Xiaoliang (David) Wei   [TCP] tcp_highspe...
118
119
120
121
122
123
124
  		/* Update AIMD parameters.
  		 *
  		 * We want to guarantee that:
  		 *     hstcp_aimd_vals[ca->ai-1].cwnd <
  		 *     snd_cwnd <=
  		 *     hstcp_aimd_vals[ca->ai].cwnd
  		 */
a628d29b5   John Heffner   [TCP]: Add High S...
125
126
  		if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
  			while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
4a1ff6e2b   Patrick McHardy   [TCP]: tcp_highsp...
127
  			       ca->ai < HSTCP_AIMD_MAX - 1)
a628d29b5   John Heffner   [TCP]: Add High S...
128
  				ca->ai++;
6150c22e2   Xiaoliang (David) Wei   [TCP] tcp_highspe...
129
130
  		} else if (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd) {
  			while (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd)
a628d29b5   John Heffner   [TCP]: Add High S...
131
132
133
134
135
  				ca->ai--;
  		}
  
  		/* Do additive increase */
  		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
fb80a6e1a   Stephen Hemminger   [TCP] tcp_highspe...
136
137
  			/* cwnd = cwnd + a(w) / cwnd */
  			tp->snd_cwnd_cnt += ca->ai + 1;
a628d29b5   John Heffner   [TCP]: Add High S...
138
  			if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
a628d29b5   John Heffner   [TCP]: Add High S...
139
  				tp->snd_cwnd_cnt -= tp->snd_cwnd;
5528e568a   John Heffner   [TCP]: Fix snd_cw...
140
  				tp->snd_cwnd++;
a628d29b5   John Heffner   [TCP]: Add High S...
141
142
143
144
  			}
  		}
  	}
  }
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
145
  static u32 hstcp_ssthresh(struct sock *sk)
a628d29b5   John Heffner   [TCP]: Add High S...
146
  {
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
147
  	const struct tcp_sock *tp = tcp_sk(sk);
85f7e7508   Florian Westphal   tcp: add cwnd_und...
148
  	struct hstcp *ca = inet_csk_ca(sk);
a628d29b5   John Heffner   [TCP]: Add High S...
149
150
151
152
  
  	/* Do multiplicative decrease */
  	return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
  }
a252bebe2   Stephen Hemminger   tcp: mark tcp_con...
153
  static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
a628d29b5   John Heffner   [TCP]: Add High S...
154
155
  	.init		= hstcp_init,
  	.ssthresh	= hstcp_ssthresh,
f1722a1be   Yuchung Cheng   tcp: consolidate ...
156
  	.undo_cwnd	= tcp_reno_undo_cwnd,
a628d29b5   John Heffner   [TCP]: Add High S...
157
  	.cong_avoid	= hstcp_cong_avoid,
a628d29b5   John Heffner   [TCP]: Add High S...
158
159
160
161
162
163
164
  
  	.owner		= THIS_MODULE,
  	.name		= "highspeed"
  };
  
  static int __init hstcp_register(void)
  {
74975d40b   Alexey Dobriyan   [TCP] Congestion ...
165
  	BUILD_BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
a628d29b5   John Heffner   [TCP]: Add High S...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  	return tcp_register_congestion_control(&tcp_highspeed);
  }
  
  static void __exit hstcp_unregister(void)
  {
  	tcp_unregister_congestion_control(&tcp_highspeed);
  }
  
  module_init(hstcp_register);
  module_exit(hstcp_unregister);
  
  MODULE_AUTHOR("John Heffner");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("High Speed TCP");