diff options
Diffstat (limited to 'net/mac80211/rc80211_pid_algo.c')
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c new file mode 100644 index 000000000000..3fac3a5d7e00 --- /dev/null +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -0,0 +1,444 @@ | |||
1 | /* | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
3 | * Copyright 2005, Devicescape Software, Inc. | ||
4 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | ||
5 | * Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | |||
16 | #include <net/mac80211.h> | ||
17 | #include "ieee80211_rate.h" | ||
18 | |||
19 | #include "rc80211_pid.h" | ||
20 | |||
21 | |||
22 | /* This is an implementation of a TX rate control algorithm that uses a PID | ||
23 | * controller. Given a target failed frames rate, the controller decides about | ||
24 | * TX rate changes to meet the target failed frames rate. | ||
25 | * | ||
26 | * The controller basically computes the following: | ||
27 | * | ||
28 | * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening) | ||
29 | * | ||
30 | * where | ||
31 | * adj adjustment value that is used to switch TX rate (see below) | ||
32 | * err current error: target vs. current failed frames percentage | ||
33 | * last_err last error | ||
34 | * err_avg average (i.e. poor man's integral) of recent errors | ||
35 | * sharpening non-zero when fast response is needed (i.e. right after | ||
36 | * association or no frames sent for a long time), heading | ||
37 | * to zero over time | ||
38 | * CP Proportional coefficient | ||
39 | * CI Integral coefficient | ||
40 | * CD Derivative coefficient | ||
41 | * | ||
42 | * CP, CI, CD are subject to careful tuning. | ||
43 | * | ||
44 | * The integral component uses a exponential moving average approach instead of | ||
45 | * an actual sliding window. The advantage is that we don't need to keep an | ||
46 | * array of the last N error values and computation is easier. | ||
47 | * | ||
48 | * Once we have the adj value, we map it to a rate by means of a learning | ||
49 | * algorithm. This algorithm keeps the state of the percentual failed frames | ||
50 | * difference between rates. The behaviour of the lowest available rate is kept | ||
51 | * as a reference value, and every time we switch between two rates, we compute | ||
52 | * the difference between the failed frames each rate exhibited. By doing so, | ||
53 | * we compare behaviours which different rates exhibited in adjacent timeslices, | ||
54 | * thus the comparison is minimally affected by external conditions. This | ||
55 | * difference gets propagated to the whole set of measurements, so that the | ||
56 | * reference is always the same. Periodically, we normalize this set so that | ||
57 | * recent events weigh the most. By comparing the adj value with this set, we | ||
58 | * avoid pejorative switches to lower rates and allow for switches to higher | ||
59 | * rates if they behaved well. | ||
60 | * | ||
61 | * Note that for the computations we use a fixed-point representation to avoid | ||
62 | * floating point arithmetic. Hence, all values are shifted left by | ||
63 | * RC_PID_ARITH_SHIFT. | ||
64 | */ | ||
65 | |||
66 | |||
67 | /* Shift the adjustment so that we won't switch to a lower rate if it exhibited | ||
68 | * a worse failed frames behaviour and we'll choose the highest rate whose | ||
69 | * failed frames behaviour is not worse than the one of the original rate | ||
70 | * target. While at it, check that the adjustment is within the ranges. Then, | ||
71 | * provide the new rate index. */ | ||
72 | static int rate_control_pid_shift_adjust(struct rc_pid_rateinfo *r, | ||
73 | int adj, int cur, int l) | ||
74 | { | ||
75 | int i, j, k, tmp; | ||
76 | |||
77 | if (cur + adj < 0) | ||
78 | return 0; | ||
79 | if (cur + adj >= l) | ||
80 | return l - 1; | ||
81 | |||
82 | i = r[cur + adj].rev_index; | ||
83 | |||
84 | j = r[cur].rev_index; | ||
85 | |||
86 | if (adj < 0) { | ||
87 | tmp = i; | ||
88 | for (k = j; k >= i; k--) | ||
89 | if (r[k].diff <= r[j].diff) | ||
90 | tmp = k; | ||
91 | return r[tmp].index; | ||
92 | } else if (adj > 0) { | ||
93 | tmp = i; | ||
94 | for (k = i + 1; k + i < l; k++) | ||
95 | if (r[k].diff <= r[i].diff) | ||
96 | tmp = k; | ||
97 | return r[tmp].index; | ||
98 | } | ||
99 | return cur + adj; | ||
100 | } | ||
101 | |||
102 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | ||
103 | struct sta_info *sta, int adj, | ||
104 | struct rc_pid_rateinfo *rinfo) | ||
105 | { | ||
106 | struct ieee80211_sub_if_data *sdata; | ||
107 | struct ieee80211_hw_mode *mode; | ||
108 | int newidx; | ||
109 | int maxrate; | ||
110 | int back = (adj > 0) ? 1 : -1; | ||
111 | |||
112 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
113 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { | ||
114 | /* forced unicast rate - do not change STA rate */ | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | mode = local->oper_hw_mode; | ||
119 | maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; | ||
120 | |||
121 | newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate, | ||
122 | mode->num_rates); | ||
123 | |||
124 | while (newidx != sta->txrate) { | ||
125 | if (rate_supported(sta, mode, newidx) && | ||
126 | (maxrate < 0 || newidx <= maxrate)) { | ||
127 | sta->txrate = newidx; | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | newidx += back; | ||
132 | } | ||
133 | |||
134 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
135 | rate_control_pid_event_rate_change( | ||
136 | &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, | ||
137 | newidx, mode->rates[newidx].rate); | ||
138 | #endif | ||
139 | } | ||
140 | |||
141 | /* Normalize the failed frames per-rate differences. */ | ||
142 | static void rate_control_pid_normalize(struct rc_pid_rateinfo *r, int l) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | if (r[0].diff > RC_PID_NORM_OFFSET) | ||
147 | r[0].diff -= RC_PID_NORM_OFFSET; | ||
148 | else if (r[0].diff < -RC_PID_NORM_OFFSET) | ||
149 | r[0].diff += RC_PID_NORM_OFFSET; | ||
150 | for (i = 0; i < l - 1; i++) | ||
151 | if (r[i + 1].diff > r[i].diff + RC_PID_NORM_OFFSET) | ||
152 | r[i + 1].diff -= RC_PID_NORM_OFFSET; | ||
153 | else if (r[i + 1].diff <= r[i].diff) | ||
154 | r[i + 1].diff += RC_PID_NORM_OFFSET; | ||
155 | } | ||
156 | |||
157 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | ||
158 | struct ieee80211_local *local, | ||
159 | struct sta_info *sta) | ||
160 | { | ||
161 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
162 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | ||
163 | struct ieee80211_hw_mode *mode; | ||
164 | u32 pf; | ||
165 | s32 err_avg; | ||
166 | s32 err_prop; | ||
167 | s32 err_int; | ||
168 | s32 err_der; | ||
169 | int adj, i, j, tmp; | ||
170 | |||
171 | mode = local->oper_hw_mode; | ||
172 | spinfo = sta->rate_ctrl_priv; | ||
173 | |||
174 | /* In case nothing happened during the previous control interval, turn | ||
175 | * the sharpening factor on. */ | ||
176 | if (jiffies - spinfo->last_sample > 2 * RC_PID_INTERVAL) | ||
177 | spinfo->sharp_cnt = RC_PID_SHARPENING_DURATION; | ||
178 | |||
179 | spinfo->last_sample = jiffies; | ||
180 | |||
181 | /* This should never happen, but in case, we assume the old sample is | ||
182 | * still a good measurement and copy it. */ | ||
183 | if (unlikely(spinfo->tx_num_xmit == 0)) | ||
184 | pf = spinfo->last_pf; | ||
185 | else { | ||
186 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | ||
187 | pf <<= RC_PID_ARITH_SHIFT; | ||
188 | } | ||
189 | |||
190 | spinfo->tx_num_xmit = 0; | ||
191 | spinfo->tx_num_failed = 0; | ||
192 | |||
193 | /* If we just switched rate, update the rate behaviour info. */ | ||
194 | if (pinfo->oldrate != sta->txrate) { | ||
195 | |||
196 | i = rinfo[pinfo->oldrate].rev_index; | ||
197 | j = rinfo[sta->txrate].rev_index; | ||
198 | |||
199 | tmp = (pf - spinfo->last_pf); | ||
200 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); | ||
201 | |||
202 | rinfo[j].diff = rinfo[i].diff + tmp; | ||
203 | pinfo->oldrate = sta->txrate; | ||
204 | } | ||
205 | rate_control_pid_normalize(rinfo, mode->num_rates); | ||
206 | |||
207 | /* Compute the proportional, integral and derivative errors. */ | ||
208 | err_prop = RC_PID_TARGET_PF - pf; | ||
209 | |||
210 | err_avg = spinfo->err_avg_sc >> RC_PID_SMOOTHING_SHIFT; | ||
211 | spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; | ||
212 | err_int = spinfo->err_avg_sc >> RC_PID_SMOOTHING_SHIFT; | ||
213 | |||
214 | err_der = pf - spinfo->last_pf | ||
215 | * (1 + RC_PID_SHARPENING_FACTOR * spinfo->sharp_cnt); | ||
216 | spinfo->last_pf = pf; | ||
217 | if (spinfo->sharp_cnt) | ||
218 | spinfo->sharp_cnt--; | ||
219 | |||
220 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
221 | rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int, | ||
222 | err_der); | ||
223 | #endif | ||
224 | |||
225 | /* Compute the controller output. */ | ||
226 | adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i | ||
227 | + err_der * pinfo->coeff_d); | ||
228 | adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT); | ||
229 | |||
230 | /* Change rate. */ | ||
231 | if (adj) | ||
232 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | ||
233 | } | ||
234 | |||
235 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | ||
236 | struct sk_buff *skb, | ||
237 | struct ieee80211_tx_status *status) | ||
238 | { | ||
239 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
240 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
241 | struct rc_pid_info *pinfo = priv; | ||
242 | struct sta_info *sta; | ||
243 | struct rc_pid_sta_info *spinfo; | ||
244 | |||
245 | sta = sta_info_get(local, hdr->addr1); | ||
246 | |||
247 | if (!sta) | ||
248 | return; | ||
249 | |||
250 | /* Ignore all frames that were sent with a different rate than the rate | ||
251 | * we currently advise mac80211 to use. */ | ||
252 | if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate]) | ||
253 | return; | ||
254 | |||
255 | spinfo = sta->rate_ctrl_priv; | ||
256 | spinfo->tx_num_xmit++; | ||
257 | |||
258 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
259 | rate_control_pid_event_tx_status(&spinfo->events, status); | ||
260 | #endif | ||
261 | |||
262 | /* We count frames that totally failed to be transmitted as two bad | ||
263 | * frames, those that made it out but had some retries as one good and | ||
264 | * one bad frame. */ | ||
265 | if (status->excessive_retries) { | ||
266 | spinfo->tx_num_failed += 2; | ||
267 | spinfo->tx_num_xmit++; | ||
268 | } else if (status->retry_count) { | ||
269 | spinfo->tx_num_failed++; | ||
270 | spinfo->tx_num_xmit++; | ||
271 | } | ||
272 | |||
273 | if (status->excessive_retries) { | ||
274 | sta->tx_retry_failed++; | ||
275 | sta->tx_num_consecutive_failures++; | ||
276 | sta->tx_num_mpdu_fail++; | ||
277 | } else { | ||
278 | sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; | ||
279 | sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; | ||
280 | sta->last_ack_rssi[2] = status->ack_signal; | ||
281 | sta->tx_num_consecutive_failures = 0; | ||
282 | sta->tx_num_mpdu_ok++; | ||
283 | } | ||
284 | sta->tx_retry_count += status->retry_count; | ||
285 | sta->tx_num_mpdu_fail += status->retry_count; | ||
286 | |||
287 | /* Update PID controller state. */ | ||
288 | if (time_after(jiffies, spinfo->last_sample + RC_PID_INTERVAL)) | ||
289 | rate_control_pid_sample(pinfo, local, sta); | ||
290 | |||
291 | sta_info_put(sta); | ||
292 | } | ||
293 | |||
294 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | ||
295 | struct ieee80211_hw_mode *mode, | ||
296 | struct sk_buff *skb, | ||
297 | struct rate_selection *sel) | ||
298 | { | ||
299 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
300 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
301 | struct sta_info *sta; | ||
302 | int rateidx; | ||
303 | |||
304 | sta = sta_info_get(local, hdr->addr1); | ||
305 | |||
306 | if (!sta) { | ||
307 | sel->rate = rate_lowest(local, mode, NULL); | ||
308 | sta_info_put(sta); | ||
309 | return; | ||
310 | } | ||
311 | |||
312 | rateidx = sta->txrate; | ||
313 | |||
314 | if (rateidx >= mode->num_rates) | ||
315 | rateidx = mode->num_rates - 1; | ||
316 | |||
317 | sta_info_put(sta); | ||
318 | |||
319 | sel->rate = &mode->rates[rateidx]; | ||
320 | |||
321 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
322 | rate_control_pid_event_tx_rate( | ||
323 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
324 | rateidx, mode->rates[rateidx].rate); | ||
325 | #endif | ||
326 | } | ||
327 | |||
328 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | ||
329 | struct ieee80211_local *local, | ||
330 | struct sta_info *sta) | ||
331 | { | ||
332 | /* TODO: This routine should consider using RSSI from previous packets | ||
333 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | ||
334 | * Until that method is implemented, we will use the lowest supported | ||
335 | * rate as a workaround. */ | ||
336 | sta->txrate = rate_lowest_index(local, local->oper_hw_mode, sta); | ||
337 | } | ||
338 | |||
339 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | ||
340 | { | ||
341 | struct rc_pid_info *pinfo; | ||
342 | struct rc_pid_rateinfo *rinfo; | ||
343 | struct ieee80211_hw_mode *mode; | ||
344 | int i, j, tmp; | ||
345 | bool s; | ||
346 | |||
347 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | ||
348 | if (!pinfo) | ||
349 | return NULL; | ||
350 | |||
351 | /* We can safely assume that oper_hw_mode won't change unless we get | ||
352 | * reinitialized. */ | ||
353 | mode = local->oper_hw_mode; | ||
354 | rinfo = kmalloc(sizeof(*rinfo) * mode->num_rates, GFP_ATOMIC); | ||
355 | if (!rinfo) { | ||
356 | kfree(pinfo); | ||
357 | return NULL; | ||
358 | } | ||
359 | |||
360 | /* Sort the rates. This is optimized for the most common case (i.e. | ||
361 | * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed | ||
362 | * mapping too. */ | ||
363 | for (i = 0; i < mode->num_rates; i++) { | ||
364 | rinfo[i].index = i; | ||
365 | rinfo[i].rev_index = i; | ||
366 | if (RC_PID_FAST_START) | ||
367 | rinfo[i].diff = 0; | ||
368 | else | ||
369 | rinfo[i].diff = i * RC_PID_NORM_OFFSET; | ||
370 | } | ||
371 | for (i = 1; i < mode->num_rates; i++) { | ||
372 | s = 0; | ||
373 | for (j = 0; j < mode->num_rates - i; j++) | ||
374 | if (unlikely(mode->rates[rinfo[j].index].rate > | ||
375 | mode->rates[rinfo[j + 1].index].rate)) { | ||
376 | tmp = rinfo[j].index; | ||
377 | rinfo[j].index = rinfo[j + 1].index; | ||
378 | rinfo[j + 1].index = tmp; | ||
379 | rinfo[rinfo[j].index].rev_index = j; | ||
380 | rinfo[rinfo[j + 1].index].rev_index = j + 1; | ||
381 | s = 1; | ||
382 | } | ||
383 | if (!s) | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | pinfo->target = RC_PID_TARGET_PF; | ||
388 | pinfo->coeff_p = RC_PID_COEFF_P; | ||
389 | pinfo->coeff_i = RC_PID_COEFF_I; | ||
390 | pinfo->coeff_d = RC_PID_COEFF_D; | ||
391 | pinfo->rinfo = rinfo; | ||
392 | pinfo->oldrate = 0; | ||
393 | |||
394 | return pinfo; | ||
395 | } | ||
396 | |||
397 | static void rate_control_pid_free(void *priv) | ||
398 | { | ||
399 | struct rc_pid_info *pinfo = priv; | ||
400 | kfree(pinfo->rinfo); | ||
401 | kfree(pinfo); | ||
402 | } | ||
403 | |||
404 | static void rate_control_pid_clear(void *priv) | ||
405 | { | ||
406 | } | ||
407 | |||
408 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | ||
409 | { | ||
410 | struct rc_pid_sta_info *spinfo; | ||
411 | |||
412 | spinfo = kzalloc(sizeof(*spinfo), gfp); | ||
413 | if (spinfo == NULL) | ||
414 | return NULL; | ||
415 | |||
416 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
417 | spin_lock_init(&spinfo->events.lock); | ||
418 | init_waitqueue_head(&spinfo->events.waitqueue); | ||
419 | #endif | ||
420 | |||
421 | return spinfo; | ||
422 | } | ||
423 | |||
424 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | ||
425 | { | ||
426 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
427 | kfree(spinfo); | ||
428 | } | ||
429 | |||
430 | struct rate_control_ops mac80211_rcpid = { | ||
431 | .name = "pid", | ||
432 | .tx_status = rate_control_pid_tx_status, | ||
433 | .get_rate = rate_control_pid_get_rate, | ||
434 | .rate_init = rate_control_pid_rate_init, | ||
435 | .clear = rate_control_pid_clear, | ||
436 | .alloc = rate_control_pid_alloc, | ||
437 | .free = rate_control_pid_free, | ||
438 | .alloc_sta = rate_control_pid_alloc_sta, | ||
439 | .free_sta = rate_control_pid_free_sta, | ||
440 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
441 | .add_sta_debugfs = rate_control_pid_add_sta_debugfs, | ||
442 | .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs, | ||
443 | #endif | ||
444 | }; | ||