Blame view

net/ipv4/tcp_veno.c 5.66 KB
76f101775   Bin Zhou   [TCP]: TCP Veno c...
1
2
3
4
5
6
7
8
  /*
   * TCP Veno congestion control
   *
   * This is based on the congestion detection/avoidance scheme described in
   *    C. P. Fu, S. C. Liew.
   *    "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
   *    IEEE Journal on Selected Areas in Communication,
   *    Feb. 2003.
631dd1a88   Justin P. Mattock   Update broken web...
9
   * 	See http://www.ie.cuhk.edu.hk/fileadmin/staff_upload/soung/Journal/J3.pdf
76f101775   Bin Zhou   [TCP]: TCP Veno c...
10
   */
76f101775   Bin Zhou   [TCP]: TCP Veno c...
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
  #include <linux/mm.h>
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/inet_diag.h>
  
  #include <net/tcp.h>
  
  /* Default values of the Veno variables, in fixed-point representation
   * with V_PARAM_SHIFT bits to the right of the binary point.
   */
  #define V_PARAM_SHIFT 1
  static const int beta = 3 << V_PARAM_SHIFT;
  
  /* Veno variables */
  struct veno {
  	u8 doing_veno_now;	/* if true, do veno for this rtt */
  	u16 cntrtt;		/* # of rtts measured within last rtt */
  	u32 minrtt;		/* min of rtts measured within last rtt (in usec) */
  	u32 basertt;		/* the min of all Veno rtt measurements seen (in usec) */
  	u32 inc;		/* decide whether to increase cwnd */
  	u32 diff;		/* calculate the diff rate */
  };
  
  /* There are several situations when we must "re-start" Veno:
   *
   *  o when a connection is established
   *  o after an RTO
   *  o after fast recovery
   *  o when we send a packet and there is no outstanding
   *    unacknowledged data (restarting an idle connection)
   *
   */
  static inline void veno_enable(struct sock *sk)
  {
  	struct veno *veno = inet_csk_ca(sk);
  
  	/* turn on Veno */
  	veno->doing_veno_now = 1;
  
  	veno->minrtt = 0x7fffffff;
  }
  
  static inline void veno_disable(struct sock *sk)
  {
  	struct veno *veno = inet_csk_ca(sk);
  
  	/* turn off Veno */
  	veno->doing_veno_now = 0;
  }
  
  static void tcp_veno_init(struct sock *sk)
  {
  	struct veno *veno = inet_csk_ca(sk);
  
  	veno->basertt = 0x7fffffff;
  	veno->inc = 1;
  	veno_enable(sk);
  }
  
  /* Do rtt sampling needed for Veno. */
756ee1729   Lawrence Brakmo   tcp: replace cnt ...
71
72
  static void tcp_veno_pkts_acked(struct sock *sk,
  				const struct ack_sample *sample)
76f101775   Bin Zhou   [TCP]: TCP Veno c...
73
74
  {
  	struct veno *veno = inet_csk_ca(sk);
164891aad   Stephen Hemminger   [TCP]: Congestion...
75
  	u32 vrtt;
756ee1729   Lawrence Brakmo   tcp: replace cnt ...
76
  	if (sample->rtt_us < 0)
b9ce204f0   Ilpo Järvinen   [TCP]: Congestion...
77
  		return;
164891aad   Stephen Hemminger   [TCP]: Congestion...
78
  	/* Never allow zero rtt or baseRTT */
756ee1729   Lawrence Brakmo   tcp: replace cnt ...
79
  	vrtt = sample->rtt_us + 1;
76f101775   Bin Zhou   [TCP]: TCP Veno c...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  
  	/* Filter to find propagation delay: */
  	if (vrtt < veno->basertt)
  		veno->basertt = vrtt;
  
  	/* Find the min rtt during the last rtt to find
  	 * the current prop. delay + queuing delay:
  	 */
  	veno->minrtt = min(veno->minrtt, vrtt);
  	veno->cntrtt++;
  }
  
  static void tcp_veno_state(struct sock *sk, u8 ca_state)
  {
  	if (ca_state == TCP_CA_Open)
  		veno_enable(sk);
  	else
  		veno_disable(sk);
  }
  
  /*
   * If the connection is idle and we are restarting,
   * then we don't want to do any Veno calculations
   * until we get fresh rtt samples.  So when we
   * restart, we reset our Veno state to a clean
   * state. After we get acks for this flight of
   * packets, _then_ we can make Veno calculations
   * again.
   */
  static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
  {
  	if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
  		tcp_veno_init(sk);
  }
249015515   Eric Dumazet   tcp: remove in_fl...
114
  static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked)
76f101775   Bin Zhou   [TCP]: TCP Veno c...
115
116
117
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct veno *veno = inet_csk_ca(sk);
ab59859de   Harvey Harrison   net: fix returnin...
118
  	if (!veno->doing_veno_now) {
249015515   Eric Dumazet   tcp: remove in_fl...
119
  		tcp_reno_cong_avoid(sk, ack, acked);
ab59859de   Harvey Harrison   net: fix returnin...
120
121
  		return;
  	}
76f101775   Bin Zhou   [TCP]: TCP Veno c...
122
123
  
  	/* limited by applications */
249015515   Eric Dumazet   tcp: remove in_fl...
124
  	if (!tcp_is_cwnd_limited(sk))
76f101775   Bin Zhou   [TCP]: TCP Veno c...
125
126
127
128
129
130
131
  		return;
  
  	/* We do the Veno calculations only if we got enough rtt samples */
  	if (veno->cntrtt <= 2) {
  		/* We don't have enough rtt samples to do the Veno
  		 * calculation, so we'll behave like Reno.
  		 */
249015515   Eric Dumazet   tcp: remove in_fl...
132
  		tcp_reno_cong_avoid(sk, ack, acked);
76f101775   Bin Zhou   [TCP]: TCP Veno c...
133
  	} else {
159131149   Lachlan Andrew   tcp: Overflow bug...
134
135
  		u64 target_cwnd;
  		u32 rtt;
76f101775   Bin Zhou   [TCP]: TCP Veno c...
136
137
138
139
140
141
  
  		/* We have enough rtt samples, so, using the Veno
  		 * algorithm, we determine the state of the network.
  		 */
  
  		rtt = veno->minrtt;
45a07695b   Christoph Paasch   tcp: Fix integer-...
142
  		target_cwnd = (u64)tp->snd_cwnd * veno->basertt;
159131149   Lachlan Andrew   tcp: Overflow bug...
143
144
  		target_cwnd <<= V_PARAM_SHIFT;
  		do_div(target_cwnd, rtt);
76f101775   Bin Zhou   [TCP]: TCP Veno c...
145
146
  
  		veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
071d5080e   Yuchung Cheng   tcp: add tcp_in_s...
147
  		if (tcp_in_slow_start(tp)) {
76f101775   Bin Zhou   [TCP]: TCP Veno c...
148
  			/* Slow start.  */
9f9843a75   Yuchung Cheng   tcp: properly han...
149
  			tcp_slow_start(tp, acked);
76f101775   Bin Zhou   [TCP]: TCP Veno c...
150
151
152
153
154
155
  		} else {
  			/* Congestion avoidance. */
  			if (veno->diff < beta) {
  				/* In the "non-congestive state", increase cwnd
  				 *  every rtt.
  				 */
e73ebb088   Neal Cardwell   tcp: stretch ACK ...
156
  				tcp_cong_avoid_ai(tp, tp->snd_cwnd, 1);
76f101775   Bin Zhou   [TCP]: TCP Veno c...
157
158
159
160
161
  			} else {
  				/* In the "congestive state", increase cwnd
  				 * every other rtt.
  				 */
  				if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
9d4fb27db   Joe Perches   net/ipv4: Move &&...
162
163
  					if (veno->inc &&
  					    tp->snd_cwnd < tp->snd_cwnd_clamp) {
76f101775   Bin Zhou   [TCP]: TCP Veno c...
164
165
166
167
168
169
170
171
  						tp->snd_cwnd++;
  						veno->inc = 0;
  					} else
  						veno->inc = 1;
  					tp->snd_cwnd_cnt = 0;
  				} else
  					tp->snd_cwnd_cnt++;
  			}
76f101775   Bin Zhou   [TCP]: TCP Veno c...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  		}
  		if (tp->snd_cwnd < 2)
  			tp->snd_cwnd = 2;
  		else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
  			tp->snd_cwnd = tp->snd_cwnd_clamp;
  	}
  	/* Wipe the slate clean for the next rtt. */
  	/* veno->cntrtt = 0; */
  	veno->minrtt = 0x7fffffff;
  }
  
  /* Veno MD phase */
  static u32 tcp_veno_ssthresh(struct sock *sk)
  {
  	const struct tcp_sock *tp = tcp_sk(sk);
  	struct veno *veno = inet_csk_ca(sk);
  
  	if (veno->diff < beta)
  		/* in "non-congestive state", cut cwnd by 1/5 */
  		return max(tp->snd_cwnd * 4 / 5, 2U);
  	else
  		/* in "congestive state", cut cwnd by 1/2 */
  		return max(tp->snd_cwnd >> 1U, 2U);
  }
a252bebe2   Stephen Hemminger   tcp: mark tcp_con...
196
  static struct tcp_congestion_ops tcp_veno __read_mostly = {
76f101775   Bin Zhou   [TCP]: TCP Veno c...
197
198
199
  	.init		= tcp_veno_init,
  	.ssthresh	= tcp_veno_ssthresh,
  	.cong_avoid	= tcp_veno_cong_avoid,
164891aad   Stephen Hemminger   [TCP]: Congestion...
200
  	.pkts_acked	= tcp_veno_pkts_acked,
76f101775   Bin Zhou   [TCP]: TCP Veno c...
201
202
203
204
205
206
207
208
209
  	.set_state	= tcp_veno_state,
  	.cwnd_event	= tcp_veno_cwnd_event,
  
  	.owner		= THIS_MODULE,
  	.name		= "veno",
  };
  
  static int __init tcp_veno_register(void)
  {
74975d40b   Alexey Dobriyan   [TCP] Congestion ...
210
  	BUILD_BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
76f101775   Bin Zhou   [TCP]: TCP Veno c...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  	tcp_register_congestion_control(&tcp_veno);
  	return 0;
  }
  
  static void __exit tcp_veno_unregister(void)
  {
  	tcp_unregister_congestion_control(&tcp_veno);
  }
  
  module_init(tcp_veno_register);
  module_exit(tcp_veno_unregister);
  
  MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("TCP Veno");