Attachment 'net80211-ratectl-ath-final.diff'
Download 1 Index: sys/dev/ral/rt2560.c
2 ===================================================================
3 --- sys/dev/ral/rt2560.c (revision 254826)
4 +++ sys/dev/ral/rt2560.c (working copy)
5 @@ -426,7 +426,8 @@
6 vap->iv_newstate = rt2560_newstate;
7 vap->iv_update_beacon = rt2560_beacon_update;
8
9 - ieee80211_ratectl_init(vap);
10 + /* XXX TODO fill the cap */
11 + ieee80211_ratectl_init(vap, 0);
12 /* complete setup */
13 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
14 if (TAILQ_FIRST(&ic->ic_vaps) == vap)
15 @@ -955,9 +956,13 @@
16
17 DPRINTFN(sc, 10, "%s\n", "data frame sent successfully");
18 if (data->rix != IEEE80211_FIXED_RATE_NONE)
19 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
20 +#if 0
21 ieee80211_ratectl_tx_complete(vap, ni,
22 IEEE80211_RATECTL_TX_SUCCESS,
23 &retrycnt, NULL);
24 +#endif
25 +
26 ifp->if_opackets++;
27 break;
28
29 @@ -967,9 +972,12 @@
30 DPRINTFN(sc, 9, "data frame sent after %u retries\n",
31 retrycnt);
32 if (data->rix != IEEE80211_FIXED_RATE_NONE)
33 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
34 +#if 0
35 ieee80211_ratectl_tx_complete(vap, ni,
36 IEEE80211_RATECTL_TX_SUCCESS,
37 &retrycnt, NULL);
38 +#endif
39 ifp->if_opackets++;
40 break;
41
42 @@ -979,9 +987,12 @@
43 DPRINTFN(sc, 9, "data frame failed after %d retries\n",
44 retrycnt);
45 if (data->rix != IEEE80211_FIXED_RATE_NONE)
46 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
47 +#if 0
48 ieee80211_ratectl_tx_complete(vap, ni,
49 IEEE80211_RATECTL_TX_FAILURE,
50 &retrycnt, NULL);
51 +#endif
52 ifp->if_oerrors++;
53 break;
54
55 Index: sys/dev/ral/rt2661.c
56 ===================================================================
57 --- sys/dev/ral/rt2661.c (revision 254826)
58 +++ sys/dev/ral/rt2661.c (working copy)
59 @@ -423,7 +423,8 @@
60 vap->iv_update_beacon = rt2661_beacon_update;
61 #endif
62
63 - ieee80211_ratectl_init(vap);
64 + /* XXX TODO fill the cap */
65 + ieee80211_ratectl_init(vap, 0);
66 /* complete setup */
67 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
68 if (TAILQ_FIRST(&ic->ic_vaps) == vap)
69 @@ -905,9 +906,12 @@
70 DPRINTFN(sc, 10, "data frame sent successfully after "
71 "%d retries\n", retrycnt);
72 if (data->rix != IEEE80211_FIXED_RATE_NONE)
73 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
74 +#if 0
75 ieee80211_ratectl_tx_complete(vap, ni,
76 IEEE80211_RATECTL_TX_SUCCESS,
77 &retrycnt, NULL);
78 +#endif
79 ifp->if_opackets++;
80 break;
81
82 @@ -917,9 +921,12 @@
83 DPRINTFN(sc, 9, "%s\n",
84 "sending data frame failed (too much retries)");
85 if (data->rix != IEEE80211_FIXED_RATE_NONE)
86 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
87 +#if 0
88 ieee80211_ratectl_tx_complete(vap, ni,
89 IEEE80211_RATECTL_TX_FAILURE,
90 &retrycnt, NULL);
91 +#endif
92 ifp->if_oerrors++;
93 break;
94
95 Index: sys/dev/ral/rt2860.c
96 ===================================================================
97 --- sys/dev/ral/rt2860.c (revision 254826)
98 +++ sys/dev/ral/rt2860.c (working copy)
99 @@ -484,7 +484,8 @@
100 /* HW supports up to 255 STAs (0-254) in HostAP and IBSS modes */
101 vap->iv_max_aid = min(IEEE80211_AID_MAX, RT2860_WCID_MAX);
102
103 - ieee80211_ratectl_init(vap);
104 + /* XXX TODO fill the cap */
105 + ieee80211_ratectl_init(vap, 0);
106 /* complete setup */
107 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
108 if (TAILQ_FIRST(&ic->ic_vaps) == vap)
109 @@ -1121,11 +1122,17 @@
110 retrycnt = 1;
111 else
112 retrycnt = 0;
113 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
114 +#if 0
115 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
116 IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL);
117 +#endif
118 } else {
119 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
120 +#if 0
121 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
122 IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL);
123 +#endif
124 ifp->if_oerrors++;
125 }
126 }
127 Index: sys/dev/ath/if_ath_tx.c
128 ===================================================================
129 --- sys/dev/ath/if_ath_tx.c (revision 254826)
130 +++ sys/dev/ath/if_ath_tx.c (working copy)
131 @@ -72,6 +72,8 @@
132
133 #include <net80211/ieee80211_var.h>
134 #include <net80211/ieee80211_regdomain.h>
135 +
136 +#include <net80211/ieee80211_ratectl.h>
137 #ifdef IEEE80211_SUPPORT_SUPERG
138 #include <net80211/ieee80211_superg.h>
139 #endif
140 @@ -1387,6 +1389,9 @@
141 static void
142 ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf)
143 {
144 + struct ieee80211_node *ni = bf->bf_node;
145 + struct ieee80211_rc_info *rc_info = NULL;
146 + struct ieee80211_rc_series *rc = NULL;
147 uint8_t rate, rix;
148 int try0;
149
150 @@ -1395,7 +1400,7 @@
151
152 /* Get rid of any previous state */
153 bzero(bf->bf_state.bfs_rc, sizeof(bf->bf_state.bfs_rc));
154 -
155 +#if 0
156 ATH_NODE_LOCK(ATH_NODE(bf->bf_node));
157 ath_rate_findrate(sc, ATH_NODE(bf->bf_node), bf->bf_state.bfs_shpream,
158 bf->bf_state.bfs_pktlen, &rix, &try0, &rate);
159 @@ -1409,7 +1414,25 @@
160 ath_rate_getxtxrates(sc, ATH_NODE(bf->bf_node), rix,
161 bf->bf_state.bfs_rc);
162 ATH_NODE_UNLOCK(ATH_NODE(bf->bf_node));
163 +#endif
164
165 + /* net80211 ratectl */
166 + rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
167 + rc = rc_info->iri_rc;
168 +
169 + rc_info->iri_flags = 0;
170 + if (bf->bf_state.bfs_shpream)
171 + rc_info->iri_flags |= IEEE80211_RATECTL_INFO_SP;
172 + if (bf->bf_state.bfs_aggr)
173 + rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
174 + rc_info->iri_framelen = bf->bf_state.bfs_pktlen;
175 +
176 + ieee80211_ratectl_rates(ni, rc_info);
177 +
178 + rix = rc[0].rix;
179 + try0 = rc[0].tries;
180 + rate = ni->ni_txrate;
181 +
182 sc->sc_txrix = rix; /* for LED blinking */
183 sc->sc_lastdatarix = rix; /* for fast frames */
184 bf->bf_state.bfs_try0 = try0;
185 @@ -1530,7 +1553,8 @@
186 * frames that must go out - eg management/raw frames.
187 */
188 bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
189 -
190 +
191 + bf->bf_state.bfs_aggr = 0;
192 /* Setup the descriptor before handoff */
193 ath_tx_do_ratelookup(sc, bf);
194 ath_tx_calc_duration(sc, bf);
195 @@ -4058,6 +4082,7 @@
196 int tid = bf->bf_state.bfs_tid;
197 struct ath_tid *atid = &an->an_tid[tid];
198 struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
199 + struct ieee80211_rc_info *rc_info = NULL;
200
201 /* The TID state is protected behind the TXQ lock */
202 ATH_TX_LOCK(sc);
203 @@ -4108,9 +4133,23 @@
204 * during a hw queue drain and the frame wanted an ACK.
205 */
206 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
207 + {
208 +#if 0
209 ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
210 ts, bf->bf_state.bfs_pktlen,
211 1, (ts->ts_status == 0) ? 0 : 1);
212 +#endif
213 +
214 + /* net80211 ratectl */
215 + rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
216 + ieee80211_ratectl_rc_info_set(rc_info,
217 + 1, (ts->ts_status == 0 ? 0 : 1),
218 + bf->bf_state.bfs_pktlen,
219 + ts->ts_shortretry, ts->ts_longretry,
220 + ts->ts_finaltsi, ts->ts_rate);
221 + rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;
222 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
223 + }
224
225 ath_tx_default_comp(sc, bf, fail);
226 }
227 @@ -4475,6 +4514,8 @@
228 int drops = 0;
229 struct ieee80211_tx_ampdu *tap;
230 ath_bufhead bf_cq;
231 + struct ath_tx_status ts = bf_first->bf_status.ds_txstat;
232 + struct ieee80211_rc_info *rc_info = NULL;
233
234 TAILQ_INIT(&bf_q);
235 TAILQ_INIT(&bf_cq);
236 @@ -4485,10 +4526,23 @@
237 * XXX use the length in the first frame in the series;
238 * XXX just so things are consistent for now.
239 */
240 +#if 0
241 ath_tx_update_ratectrl(sc, ni, bf_first->bf_state.bfs_rc,
242 &bf_first->bf_status.ds_txstat,
243 bf_first->bf_state.bfs_pktlen,
244 bf_first->bf_state.bfs_nframes, bf_first->bf_state.bfs_nframes);
245 +#endif
246 +
247 + /* net80211 ratectl */
248 + rc_info = ieee80211_ratectl_rc_info_get(ni, bf_first->bf_m);
249 + ieee80211_ratectl_rc_info_set(rc_info,
250 + bf_first->bf_state.bfs_nframes,
251 + bf_first->bf_state.bfs_nframes,
252 + bf_first->bf_state.bfs_pktlen,
253 + ts.ts_shortretry, ts.ts_longretry,
254 + ts.ts_finaltsi, ts.ts_rate);
255 + rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
256 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
257
258 ATH_TX_LOCK(sc);
259 tap = ath_tx_get_tx_tid(an, tid->tid);
260 @@ -4626,9 +4680,12 @@
261 int nframes = 0, nbad = 0, nf;
262 int pktlen;
263 /* XXX there's too much on the stack? */
264 +#if 0
265 struct ath_rc_series rc[ATH_RC_NUM];
266 +#endif
267 int txseq;
268 -
269 + struct ieee80211_rc_info *rc_info = NULL;
270 + struct mbuf *m;
271 DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called; hwq_depth=%d\n",
272 __func__, atid->hwq_depth);
273
274 @@ -4748,7 +4805,7 @@
275 isaggr = bf_first->bf_state.bfs_aggr;
276 ba[0] = ts.ts_ba_low;
277 ba[1] = ts.ts_ba_high;
278 -
279 +#if 0
280 /*
281 * Copy the TX completion status and the rate control
282 * series from the first descriptor, as it may be freed
283 @@ -4756,6 +4813,11 @@
284 * into things.
285 */
286 memcpy(rc, bf_first->bf_state.bfs_rc, sizeof(rc));
287 +#endif
288 + /*
289 + * Get the mbuf here, as bf_first will be set to NULL later.
290 + */
291 + m = bf_first->bf_m;
292
293 DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
294 "%s: txa_start=%d, tx_ok=%d, status=%.8x, flags=%.8x, "
295 @@ -4873,8 +4935,20 @@
296 * control code.
297 */
298 if (fail == 0)
299 + {
300 +#if 0
301 ath_tx_update_ratectrl(sc, ni, rc, &ts, pktlen, nframes,
302 nbad);
303 +#endif
304 + /* net80211 ratectl */
305 + rc_info = ieee80211_ratectl_rc_info_get(ni, m);
306 + ieee80211_ratectl_rc_info_set(rc_info,
307 + nframes, nbad, pktlen,
308 + ts.ts_shortretry, ts.ts_longretry,
309 + ts.ts_finaltsi, ts.ts_rate);
310 + rc_info->iri_flags |= IEEE80211_RATECTL_INFO_AGGR;
311 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
312 + }
313
314 /*
315 * send bar if we dropped any frames
316 @@ -4948,6 +5022,7 @@
317 struct ath_tid *atid = &an->an_tid[tid];
318 struct ath_tx_status ts;
319 int drops = 0;
320 + struct ieee80211_rc_info *rc_info = NULL;
321
322 /*
323 * Take a copy of this; filtering/cloning the frame may free the
324 @@ -4962,11 +5037,22 @@
325 * Do it outside of the TXQ lock.
326 */
327 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
328 + {
329 +#if 0
330 ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,
331 &bf->bf_status.ds_txstat,
332 bf->bf_state.bfs_pktlen,
333 1, (ts.ts_status == 0) ? 0 : 1);
334 -
335 +#endif
336 + rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
337 + ieee80211_ratectl_rc_info_set(rc_info,
338 + 1, (ts.ts_status == 0 ? 0 : 1),
339 + bf->bf_state.bfs_pktlen,
340 + ts.ts_shortretry, ts.ts_longretry,
341 + ts.ts_finaltsi, ts.ts_rate);
342 + rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;
343 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
344 + }
345 /*
346 * This is called early so atid->hwq_depth can be tracked.
347 * This unfortunately means that it's released and regrabbed
348 @@ -5183,6 +5269,15 @@
349 }
350
351 /*
352 + * If non-aggregate scenario appears, this will be
353 + * turned off.
354 + *
355 + * This flag is used by ath_tx_do_ratelookup() to
356 + * distinguish aggr/non-aggr scenario.
357 + */
358 + bf->bf_state.bfs_aggr = 1;
359 +
360 + /*
361 * If the packet doesn't fall within the BAW (eg a NULL
362 * data frame), schedule it directly; continue.
363 */
364 @@ -5425,6 +5520,7 @@
365 /* Update CLRDMASK just before this frame is queued */
366 ath_tx_update_clrdmask(sc, tid, bf);
367
368 + bf->bf_state.bfs_aggr = 0;
369 /* Program descriptors + rate control */
370 ath_tx_do_ratelookup(sc, bf);
371 ath_tx_calc_duration(sc, bf);
372 Index: sys/dev/ath/if_ath_tx_ht.c
373 ===================================================================
374 --- sys/dev/ath/if_ath_tx_ht.c (revision 254826)
375 +++ sys/dev/ath/if_ath_tx_ht.c (working copy)
376 @@ -64,6 +64,8 @@
377
378 #include <net80211/ieee80211_var.h>
379 #include <net80211/ieee80211_regdomain.h>
380 +
381 +#include <net80211/ieee80211_ratectl.h>
382 #ifdef IEEE80211_SUPPORT_SUPERG
383 #include <net80211/ieee80211_superg.h>
384 #endif
385 @@ -221,13 +223,47 @@
386 void
387 ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
388 {
389 - struct ieee80211_node *ni = bf->bf_node;
390 - struct ieee80211com *ic = ni->ni_ic;
391 + // struct ieee80211_node *ni = bf->bf_node;
392 + // struct ieee80211com *ic = ni->ni_ic;
393 const HAL_RATE_TABLE *rt = sc->sc_currates;
394 - struct ath_rc_series *rc = bf->bf_state.bfs_rc;
395 + struct ath_rc_series *ath_rc = bf->bf_state.bfs_rc;
396 + struct ieee80211_rc_info *rc_info = NULL;
397 + struct ieee80211_rc_series *rc = NULL;
398 + struct m_tag *mtag;
399 uint8_t rate;
400 int i;
401
402 + mtag = m_tag_locate(bf->bf_m, MTAG_ABI_NET80211,
403 + NET80211_TAG_RATECTL, NULL);
404 + if (NULL == mtag)
405 + return;
406 +
407 + rc_info = (struct ieee80211_rc_info*)(mtag + 1);
408 + rc = rc_info->iri_rc;
409 +
410 + for (i = 0; i < IEEE80211_RATECTL_NUM; i++) {
411 + if (rc[i].tries == 0)
412 + continue;
413 +
414 + rate = rt->info[rc[i].rix].rateCode;
415 + if (rc[i].flags & IEEE80211_RATECTL_FLAG_SP)
416 + rate |= rt->info[rc[i].rix].shortPreamble;
417 +
418 + rc[i].ratecode = rate;
419 +
420 + ath_rc[i].rix = rc[i].rix;
421 + ath_rc[i].tries = rc[i].tries;
422 + ath_rc[i].flags = rc[i].flags;
423 + ath_rc[i].ratecode = rc[i].ratecode;
424 + ath_rc[i].tx_power_cap = rc[i].tx_power_cap;
425 + ath_rc[i].max4msframelen = rc[i].max4msframelen;
426 +
427 + DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
428 + "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
429 + __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
430 + }
431 +
432 +#if 0
433 for (i = 0; i < ATH_RC_NUM; i++) {
434 rc[i].flags = 0;
435 if (rc[i].tries == 0)
436 @@ -325,6 +361,7 @@
437 "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
438 __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
439 }
440 +#endif
441 }
442
443 /*
444 Index: sys/dev/ath/if_ath.c
445 ===================================================================
446 --- sys/dev/ath/if_ath.c (revision 254826)
447 +++ sys/dev/ath/if_ath.c (working copy)
448 @@ -82,6 +82,8 @@
449
450 #include <net80211/ieee80211_var.h>
451 #include <net80211/ieee80211_regdomain.h>
452 +
453 +#include <net80211/ieee80211_ratectl.h>
454 #ifdef IEEE80211_SUPPORT_SUPERG
455 #include <net80211/ieee80211_superg.h>
456 #endif
457 @@ -322,6 +324,7 @@
458 sc->sc_ah = ah;
459 sc->sc_invalid = 0; /* ready to go, enable interrupt handling */
460 #ifdef ATH_DEBUG
461 + ath_debug |= ATH_DEBUG_NODE;
462 sc->sc_debug = ath_debug;
463 #endif
464
465 @@ -1380,6 +1383,16 @@
466 }
467 ATH_UNLOCK(sc);
468
469 + uint32_t caps = 0;
470 + if (sc->sc_mrretry)
471 + caps |= IEEE80211_RATECTL_CAP_MRR;
472 + if (sc->sc_mrrprot)
473 + caps |= IEEE80211_RATECTL_CAP_MRRPROT;
474 + if (sc->sc_txchainmask > 1)
475 + caps |= IEEE80211_RATECTL_CAP_MULTXCHAIN;
476 +
477 + ieee80211_ratectl_init(vap, caps);
478 +
479 /* complete setup */
480 ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
481 return vap;
482 @@ -1414,6 +1427,7 @@
483 ath_stoprecv(sc, 1); /* stop recv side */
484 }
485
486 + ieee80211_ratectl_deinit(vap);
487 ieee80211_vap_detach(vap);
488
489 /*
490 @@ -4042,6 +4056,7 @@
491 {
492 struct ieee80211_node *ni = bf->bf_node;
493 struct ath_node *an = NULL;
494 + struct ieee80211_rc_info *rc_info = NULL;
495
496 ATH_TX_UNLOCK_ASSERT(sc);
497 ATH_TXQ_UNLOCK_ASSERT(txq);
498 @@ -4068,10 +4083,21 @@
499 * XXX assume this isn't an aggregate
500 * frame.
501 */
502 +#if 0
503 ath_tx_update_ratectrl(sc, ni,
504 bf->bf_state.bfs_rc, ts,
505 bf->bf_state.bfs_pktlen, 1,
506 (ts->ts_status == 0 ? 0 : 1));
507 +#endif
508 + /* net80211 ratectl */
509 + rc_info = ieee80211_ratectl_rc_info_get(ni, bf->bf_m);
510 + ieee80211_ratectl_rc_info_set(rc_info,
511 + 1, (ts->ts_status == 0 ? 0 : 1),
512 + bf->bf_state.bfs_pktlen,
513 + ts->ts_shortretry, ts->ts_longretry,
514 + ts->ts_finaltsi, ts->ts_rate);
515 + rc_info->iri_flags &= ~IEEE80211_RATECTL_INFO_AGGR;
516 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, rc_info);
517 }
518 ath_tx_default_comp(sc, bf, 0);
519 } else
520 @@ -5574,9 +5600,15 @@
521
522 an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
523 an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate);
524 -
525 +#if 0
526 ath_rate_newassoc(sc, an, isnew);
527 +#endif
528
529 + DPRINTF(sc, ATH_DEBUG_NODE, "%s: newassoc is new: %d\n",
530 + __func__, isnew);
531 + if (isnew)
532 + ieee80211_ratectl_node_init(ni);
533 +
534 if (isnew &&
535 (vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
536 ni->ni_ucastkey.wk_keyix == IEEE80211_KEYIX_NONE)
537 Index: sys/dev/ath/if_ath_sysctl.c
538 ===================================================================
539 --- sys/dev/ath/if_ath_sysctl.c (revision 254826)
540 +++ sys/dev/ath/if_ath_sysctl.c (working copy)
541 @@ -71,6 +71,7 @@
542
543 #include <net80211/ieee80211_var.h>
544 #include <net80211/ieee80211_regdomain.h>
545 +#include <net80211/ieee80211_ratectl.h>
546 #ifdef IEEE80211_SUPPORT_SUPERG
547 #include <net80211/ieee80211_superg.h>
548 #endif
549 @@ -602,6 +603,28 @@
550 }
551 #endif /* ATH_DEBUG_ALQ */
552
553 +static int
554 +ath_sysctl_ratectl_stats(SYSCTL_HANDLER_ARGS)
555 +{
556 + struct ath_softc *sc = arg1;
557 + struct ieee80211com *ic = sc->sc_ifp->if_l2com;
558 + struct ieee80211vap *vap;
559 + int error, v;
560 +
561 + v = 0;
562 + error = sysctl_handle_int(oidp, &v, 0, req);
563 + if (error || !req->newptr)
564 + return error;
565 +
566 + printf("\n[%s]: per-device net80211 ratectl statistics\n",
567 + ic->ic_ifp->if_xname);
568 + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
569 + ieee80211_ratectl_stats(vap);
570 + }
571 +
572 + return 0;
573 +}
574 +
575 void
576 ath_sysctlattach(struct ath_softc *sc)
577 {
578 @@ -792,6 +815,10 @@
579 #ifdef ATH_DEBUG_ALQ
580 ath_sysctl_alq_attach(sc);
581 #endif
582 +
583 + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
584 + "ratectl_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
585 + ath_sysctl_ratectl_stats, "I", "per-device net80211 ratectl statistics");
586 }
587
588 static int
589 Index: sys/dev/iwn/if_iwn.c
590 ===================================================================
591 --- sys/dev/iwn/if_iwn.c (revision 254826)
592 +++ sys/dev/iwn/if_iwn.c (working copy)
593 @@ -876,7 +876,8 @@
594 ivp->iv_newstate = vap->iv_newstate;
595 vap->iv_newstate = iwn_newstate;
596
597 - ieee80211_ratectl_init(vap);
598 + /* XXX TODO fill the cap */
599 + ieee80211_ratectl_init(vap, 0);
600 /* Complete setup. */
601 ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status);
602 ic->ic_opmode = opmode;
603 @@ -2499,7 +2500,8 @@
604 uint64_t bitmap;
605 uint16_t ssn;
606 uint8_t tid;
607 - int ackfailcnt = 0, i, lastidx, qid, *res, shift;
608 + /* int failcnt = 0; */
609 + int i, lastidx, qid, *res, shift;
610
611 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
612
613 @@ -2563,12 +2565,18 @@
614 for (i = 0; bitmap; i++) {
615 if ((bitmap & 1) == 0) {
616 ifp->if_oerrors++;
617 +#if 0
618 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
619 IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
620 +#endif
621 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
622 } else {
623 ifp->if_opackets++;
624 +#if 0
625 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
626 IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
627 +#endif
628 + ieee80211_ratectl_tx_complete(ni->ni_vap, ni, NULL); /* just make it compiled. qcc */
629 }
630 bitmap >>= 1;
631 }
632 @@ -2807,12 +2815,18 @@
633 */
634 if (status & IWN_TX_FAIL) {
635 ifp->if_oerrors++;
636 +#if 0
637 ieee80211_ratectl_tx_complete(vap, ni,
638 IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
639 +#endif
640 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
641 } else {
642 ifp->if_opackets++;
643 +#if 0
644 ieee80211_ratectl_tx_complete(vap, ni,
645 IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
646 +#endif
647 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
648 }
649 m_freem(m);
650 ieee80211_free_node(ni);
651 Index: sys/dev/bwi/if_bwi.c
652 ===================================================================
653 --- sys/dev/bwi/if_bwi.c (revision 254826)
654 +++ sys/dev/bwi/if_bwi.c (working copy)
655 @@ -617,7 +617,8 @@
656 #if 0
657 vap->iv_update_beacon = bwi_beacon_update;
658 #endif
659 - ieee80211_ratectl_init(vap);
660 + /* XXX TODO fill the cap */
661 + ieee80211_ratectl_init(vap, 0);
662
663 /* complete setup */
664 ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
665 @@ -3377,9 +3378,12 @@
666 * well so to avoid over-aggressive downshifting we
667 * treat any number of retries as "1".
668 */
669 +#if 0
670 ieee80211_ratectl_tx_complete(vap, ni,
671 (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
672 IEEE80211_RATECTL_TX_FAILURE, &acked, NULL);
673 +#endif
674 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
675 }
676
677 /*
678 Index: sys/dev/bwn/if_bwn.c
679 ===================================================================
680 --- sys/dev/bwn/if_bwn.c (revision 254826)
681 +++ sys/dev/bwn/if_bwn.c (working copy)
682 @@ -2970,7 +2970,8 @@
683 /* override max aid so sta's cannot assoc when we're out of sta id's */
684 vap->iv_max_aid = BWN_STAID_MAX;
685
686 - ieee80211_ratectl_init(vap);
687 + /* XXX TODO fill the cap */
688 + ieee80211_ratectl_init(vap, 0);
689
690 /* complete setup */
691 ieee80211_vap_attach(vap, ieee80211_media_change,
692 @@ -8991,8 +8992,9 @@
693 struct bwn_stats *stats = &mac->mac_stats;
694 struct ieee80211_node *ni;
695 struct ieee80211vap *vap;
696 - int retrycnt = 0, slot;
697 -
698 + /*int retrycnt = 0, slot;*/
699 + int slot;
700 +
701 BWN_ASSERT_LOCKED(mac->mac_sc);
702
703 if (status->im)
704 @@ -9020,11 +9022,14 @@
705 if (meta->mt_islast) {
706 ni = meta->mt_ni;
707 vap = ni->ni_vap;
708 +#if 0
709 ieee80211_ratectl_tx_complete(vap, ni,
710 status->ack ?
711 IEEE80211_RATECTL_TX_SUCCESS :
712 IEEE80211_RATECTL_TX_FAILURE,
713 &retrycnt, 0);
714 +#endif
715 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
716 break;
717 }
718 slot = bwn_dma_nextslot(dr, slot);
719 @@ -9041,11 +9046,14 @@
720 }
721 ni = tp->tp_ni;
722 vap = ni->ni_vap;
723 +#if 0
724 ieee80211_ratectl_tx_complete(vap, ni,
725 status->ack ?
726 IEEE80211_RATECTL_TX_SUCCESS :
727 IEEE80211_RATECTL_TX_FAILURE,
728 &retrycnt, 0);
729 +#endif
730 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
731 }
732 bwn_pio_handle_txeof(mac, status);
733 }
734 Index: sys/dev/usb/wlan/if_zyd.c
735 ===================================================================
736 --- sys/dev/usb/wlan/if_zyd.c (revision 254826)
737 +++ sys/dev/usb/wlan/if_zyd.c (working copy)
738 @@ -496,7 +496,8 @@
739 zvp->newstate = vap->iv_newstate;
740 vap->iv_newstate = zyd_newstate;
741
742 - ieee80211_ratectl_init(vap);
743 + /* XXX TODO fill the cap */
744 + ieee80211_ratectl_init(vap, 0);
745 ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
746
747 /* complete setup */
748 @@ -664,12 +665,15 @@
749 */
750 ni = ieee80211_find_txnode(vap, retry->macaddr);
751 if (ni != NULL) {
752 - int retrycnt =
753 - (int)(le16toh(retry->count) & 0xff);
754 + /*int retrycnt =
755 + (int)(le16toh(retry->count) & 0xff);*/
756
757 +#if 0
758 ieee80211_ratectl_tx_complete(vap, ni,
759 IEEE80211_RATECTL_TX_FAILURE,
760 &retrycnt, NULL);
761 +#endif
762 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
763 ieee80211_free_node(ni);
764 }
765 if (le16toh(retry->count) & 0x100)
766 Index: sys/dev/usb/wlan/if_ural.c
767 ===================================================================
768 --- sys/dev/usb/wlan/if_ural.c (revision 254826)
769 +++ sys/dev/usb/wlan/if_ural.c (working copy)
770 @@ -598,7 +598,8 @@
771
772 usb_callout_init_mtx(&uvp->ratectl_ch, &sc->sc_mtx, 0);
773 TASK_INIT(&uvp->ratectl_task, 0, ural_ratectl_task, uvp);
774 - ieee80211_ratectl_init(vap);
775 + /* XXX TODO fill the cap */
776 + ieee80211_ratectl_init(vap, 0);
777 ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
778
779 /* complete setup */
780 Index: sys/dev/usb/wlan/if_rum.c
781 ===================================================================
782 --- sys/dev/usb/wlan/if_rum.c (revision 254826)
783 +++ sys/dev/usb/wlan/if_rum.c (working copy)
784 @@ -613,7 +613,8 @@
785
786 usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0);
787 TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp);
788 - ieee80211_ratectl_init(vap);
789 + /* XXX TODO fill the cap */
790 + ieee80211_ratectl_init(vap, 0);
791 ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
792 /* complete setup */
793 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
794 Index: sys/dev/usb/wlan/if_run.c
795 ===================================================================
796 --- sys/dev/usb/wlan/if_run.c (revision 254826)
797 +++ sys/dev/usb/wlan/if_run.c (working copy)
798 @@ -820,7 +820,8 @@
799 rvp->newstate = vap->iv_newstate;
800 vap->iv_newstate = run_newstate;
801
802 - ieee80211_ratectl_init(vap);
803 + /* XXX TODO fill the cap */
804 + ieee80211_ratectl_init(vap, 0);
805 ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
806
807 /* complete setup */
808 Index: sys/dev/wpi/if_wpi.c
809 ===================================================================
810 --- sys/dev/wpi/if_wpi.c (revision 254826)
811 +++ sys/dev/wpi/if_wpi.c (working copy)
812 @@ -782,7 +782,8 @@
813 wvp->newstate = vap->iv_newstate;
814 vap->iv_newstate = wpi_newstate;
815
816 - ieee80211_ratectl_init(vap);
817 + /* XXX TODO fill the cap */
818 + ieee80211_ratectl_init(vap, 0);
819 /* complete setup */
820 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
821 ic->ic_opmode = opmode;
822 @@ -1596,8 +1597,11 @@
823 DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries));
824 retrycnt = 1;
825 }
826 +#if 0
827 ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS,
828 &retrycnt, NULL);
829 +#endif
830 + ieee80211_ratectl_tx_complete(vap, ni, NULL); /* just make it compiled. qcc */
831
832 /* XXX oerrors should only count errors !maxtries */
833 if ((le32toh(stat->status) & 0xff) != 1)
834 Index: sys/conf/files
835 ===================================================================
836 --- sys/conf/files (revision 254826)
837 +++ sys/conf/files (working copy)
838 @@ -3100,6 +3100,7 @@
839 net80211/ieee80211_ratectl_none.c optional wlan
840 net80211/ieee80211_regdomain.c optional wlan
841 net80211/ieee80211_rssadapt.c optional wlan wlan_rssadapt
842 +net80211/ieee80211_sample.c optional wlan | wlan_sample
843 net80211/ieee80211_scan.c optional wlan
844 net80211/ieee80211_scan_sta.c optional wlan
845 net80211/ieee80211_sta.c optional wlan
846 Index: sys/net80211/ieee80211_ratectl_none.c
847 ===================================================================
848 --- sys/net80211/ieee80211_ratectl_none.c (revision 254826)
849 +++ sys/net80211/ieee80211_ratectl_none.c (working copy)
850 @@ -44,10 +44,26 @@
851
852 #include <net80211/ieee80211_var.h>
853 #include <net80211/ieee80211_ratectl.h>
854 +#include <net80211/ieee80211_ratectl_none.h>
855
856 static void
857 -none_init(struct ieee80211vap *vap)
858 +none_init(struct ieee80211vap *vap, uint32_t capabilities)
859 {
860 + struct ieee80211_node *none;
861 +
862 + KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__));
863 +
864 + none = vap->iv_rs = malloc(sizeof(struct ieee80211_none),
865 + M_80211_RATECTL, M_NOWAIT|M_ZERO);
866 + if (none == NULL) {
867 + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
868 + return;
869 + }
870 +
871 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
872 + irs->irs_capabilities = capabilities;
873 +
874 + /* ... */
875 }
876
877 static void
878 @@ -59,6 +75,25 @@
879 static void
880 none_node_init(struct ieee80211_node *ni)
881 {
882 + struct ieee80211vap *vap = ni->ni_vap;
883 + struct ieee80211_none *none = vap->iv_rs;
884 + struct ieee80211_none_node *non;
885 +
886 + if (ni->ni_rctls == NULL) {
887 + ni->ni_rctls = non = malloc(sizeof(struct ieee80211_none_node),
888 + M_80211_RATECTL, M_NOWAIT|M_ZERO);
889 + if (non == NULL) {
890 + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
891 + "structure\n");
892 + return;
893 + }
894 + } else
895 + non = ni->ni_rctls;
896 +
897 + non->non_none = none;
898 +
899 + /* ... */
900 +
901 ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
902 }
903
904 @@ -77,9 +112,13 @@
905 }
906
907 static void
908 +none_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
909 +{
910 +}
911 +
912 +static void
913 none_tx_complete(const struct ieee80211vap *vap,
914 - const struct ieee80211_node *ni, int ok,
915 - void *arg1, void *arg2 __unused)
916 + const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
917 {
918 }
919
920 @@ -94,6 +133,16 @@
921 {
922 }
923
924 +static void
925 +none_stats(const struct ieee80211vap *vap)
926 +{
927 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
928 + printf("tx count: %d (ok count: %d, fail count: %d)\n"
929 + "retry count: %d (short retry: %d, long retry: %d)\n",
930 + irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
931 + irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
932 + /* ... */
933 +}
934 /* number of references from net80211 layer */
935 static int nrefs = 0;
936
937 @@ -106,9 +155,11 @@
938 .ir_node_init = none_node_init,
939 .ir_node_deinit = none_node_deinit,
940 .ir_rate = none_rate,
941 + .ir_rates = none_rates,
942 .ir_tx_complete = none_tx_complete,
943 .ir_tx_update = none_tx_update,
944 .ir_setinterval = none_setinterval,
945 + .ir_stats = none_stats,
946 };
947 IEEE80211_RATECTL_MODULE(ratectl_none, 1);
948 IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none);
949 Index: sys/net80211/ieee80211_ratectl.c
950 ===================================================================
951 --- sys/net80211/ieee80211_ratectl.c (revision 254826)
952 +++ sys/net80211/ieee80211_ratectl.c (working copy)
953 @@ -1,5 +1,6 @@
954 /*-
955 * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
956 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
957 * All rights reserved.
958 *
959 * Redistribution and use in source and binary forms, with or without
960 @@ -49,6 +50,40 @@
961
962 MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control");
963
964 +enum {
965 + MCS_HT20,
966 + MCS_HT20_SGI,
967 + MCS_HT40,
968 + MCS_HT40_SGI,
969 +};
970 +
971 +int max_4ms_framelen[4][32] = {
972 + [MCS_HT20] = {
973 + 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
974 + 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
975 + 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
976 + 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
977 + },
978 + [MCS_HT20_SGI] = {
979 + 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
980 + 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
981 + 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
982 + 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
983 + },
984 + [MCS_HT40] = {
985 + 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
986 + 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
987 + 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
988 + 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
989 + },
990 + [MCS_HT40_SGI] = {
991 + 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
992 + 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
993 + 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
994 + 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
995 + }
996 +};
997 +
998 void
999 ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl)
1000 {
1001 @@ -65,12 +100,36 @@
1002 ratectls[type] = NULL;
1003 }
1004
1005 +static int
1006 +ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)
1007 +{
1008 + struct ieee80211vap *vap = arg1;
1009 + int error, v;
1010 +
1011 + v = 0;
1012 + error = sysctl_handle_int(oidp, &v, 0, req);
1013 + if (error || !req->newptr)
1014 + return error;
1015 +
1016 + ieee80211_ratectl_stats(vap);
1017 + return 0;
1018 +}
1019 +
1020 void
1021 -ieee80211_ratectl_init(struct ieee80211vap *vap)
1022 +ieee80211_ratectl_init(struct ieee80211vap *vap, uint32_t capabilities)
1023 {
1024 if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
1025 ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
1026 - vap->iv_rate->ir_init(vap);
1027 + vap->iv_rate->ir_init(vap, capabilities);
1028 +
1029 + SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid),
1030 + OID_AUTO, "ratectl_stats", CTLTYPE_INT | CTLFLAG_RW,
1031 + vap, 0, ratectl_sysctl_stats, "I",
1032 + "per-vap net80211 ratectl statistics");
1033 +
1034 + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1035 + "%s: ratectl initialized. caps=0x%08x\n",
1036 + __func__, capabilities);
1037 }
1038
1039 void
1040 @@ -90,3 +149,110 @@
1041 }
1042 vap->iv_rate = ratectls[type];
1043 }
1044 +
1045 +void
1046 +ieee80211_ratectl_complete_rcflags(struct ieee80211_node *ni,
1047 + struct ieee80211_rc_info *rc_info)
1048 +{
1049 + struct ieee80211vap *vap = ni->ni_vap;
1050 + struct ieee80211_rc_series *rc = rc_info->iri_rc;
1051 + const struct ieee80211_rate_table * rt = NULL;
1052 + uint8_t rate;
1053 + int i;
1054 +
1055 + rt = ieee80211_get_ratetable(ni->ni_ic->ic_curchan);
1056 +
1057 + /* Make sure that rate control code doesn't mess it up.
1058 + * If enable rts/cts and is pre-802.11n, blank tries 1, 2, 3
1059 + */
1060 +
1061 + if (! IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
1062 + {
1063 + for (i = 1; i < IEEE80211_RATECTL_NUM; i++)
1064 + {
1065 + if (rc[0].flags & IEEE80211_RATECTL_FLAG_RTSCTS)
1066 + rc[i].tries = 0;
1067 + rc[i].flags &= ~IEEE80211_RATECTL_FLAG_RTSCTS;
1068 + }
1069 + }
1070 +
1071 + for (i = 0; i < IEEE80211_RATECTL_NUM; i++) {
1072 +
1073 + if (rc[i].tries == 0)
1074 + continue;
1075 +
1076 + rate = rt->info[rc[i].rix].dot11Rate;
1077 +
1078 + /* Only enable dual-stream, shortgi, 2040 if HT is set */
1079 +
1080 + if (IS_HT_RATE(rate)) {
1081 + rc[i].flags |= IEEE80211_RATECTL_FLAG_HT;
1082 +
1083 + if (ieee80211_ratectl_hascap_cw40(ni))
1084 + rc[i].flags |= IEEE80211_RATECTL_FLAG_CW40;
1085 +
1086 + if (ieee80211_ratectl_hascap_shortgi(ni))
1087 + rc[i].flags |= IEEE80211_RATECTL_FLAG_SGI;
1088 + /*
1089 + * If we have STBC TX enabled and the receiver
1090 + * can receive (at least) 1 stream STBC, AND it's
1091 + * MCS 0-7, AND we have at least two chains enabled,
1092 + * enable STBC.
1093 + */
1094 + if (ieee80211_ratectl_hascap_stbc(ni) &&
1095 + (rate & IEEE80211_RATE_VAL) < 8 &&
1096 + HT_RC_2_STREAMS(rate) == 1)
1097 + rc[i].flags |= IEEE80211_RATECTL_FLAG_STBC;
1098 +
1099 + /*
1100 + * Dual / Triple stream rate?
1101 + */
1102 + if (HT_RC_2_STREAMS(rate) == 2)
1103 + rc[i].flags |= IEEE80211_RATECTL_FLAG_DS;
1104 + else if (HT_RC_2_STREAMS(rate) == 3)
1105 + rc[i].flags |= IEEE80211_RATECTL_FLAG_TS;
1106 +
1107 + /*
1108 + * Calculate the maximum 4ms frame length based
1109 + * on the MCS rate, SGI and channel width flags.
1110 + */
1111 + if (HT_RC_2_MCS(rate) < 32) {
1112 + int j;
1113 + if (rc[i].flags & IEEE80211_RATECTL_FLAG_CW40) {
1114 + if (rc[i].flags & IEEE80211_RATECTL_FLAG_SGI)
1115 + j = MCS_HT40_SGI;
1116 + else
1117 + j = MCS_HT40;
1118 + } else {
1119 + if (rc[i].flags & IEEE80211_RATECTL_FLAG_SGI)
1120 + j = MCS_HT20_SGI;
1121 + else
1122 + j = MCS_HT20;
1123 + }
1124 + rc[i].max4msframelen =
1125 + max_4ms_framelen[j][HT_RC_2_MCS(rate)];
1126 + }
1127 + } else {
1128 + rc[i].max4msframelen = 0;
1129 +
1130 + /*
1131 + * Only enable short preamble for legacy rates
1132 + */
1133 + if (rc_info->iri_flags & IEEE80211_RATECTL_INFO_SP)
1134 + rc[i].flags |= IEEE80211_RATECTL_FLAG_SP;
1135 + }
1136 +
1137 + /*
1138 + * Calculate the maximum TX power cap for the current
1139 + * node.
1140 + * Rate control algo can't control TX power by now.
1141 + */
1142 + rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
1143 +
1144 + }
1145 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1146 + "%s: flags: rc[0]:0x%08x, rc[1]:0x%08x, "
1147 + "rc[2]:0x%08x, rc[3]:0x%08x\n", __func__,
1148 + rc[0].flags, rc[1].flags, rc[2].flags, rc[3].flags);
1149 +}
1150 +
1151 Index: sys/net80211/ieee80211_ratectl.h
1152 ===================================================================
1153 --- sys/net80211/ieee80211_ratectl.h (revision 254826)
1154 +++ sys/net80211/ieee80211_ratectl.h (working copy)
1155 @@ -1,5 +1,6 @@
1156 /*-
1157 * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
1158 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
1159 * All rights reserved.
1160 *
1161 * Redistribution and use in source and binary forms, with or without
1162 @@ -24,6 +25,8 @@
1163 *
1164 * $FreeBSD$
1165 */
1166 +#ifndef _NET80211_IEEE80211_RATECTL_H_
1167 +#define _NET80211_IEEE80211_RATECTL_H_
1168
1169 enum ieee80211_ratealgs {
1170 IEEE80211_RATECTL_AMRR = 0,
1171 @@ -37,28 +40,115 @@
1172 #define IEEE80211_RATECTL_TX_SUCCESS 1
1173 #define IEEE80211_RATECTL_TX_FAILURE 0
1174
1175 +#define IEEE80211_RATECTL_TRUE 1
1176 +#define IEEE80211_RATECTL_FALSE 0
1177 +
1178 +#define IEEE80211_RATECTL_NUM 4
1179 +#define IEEE80211_RATECTL_TXMAXTRY 11
1180 +
1181 +#define IEEE80211_RATECTL_FLAG_DS 0x01 /* dual-stream rate */
1182 +#define IEEE80211_RATECTL_FLAG_CW40 0x02 /* use HT40 */
1183 +#define IEEE80211_RATECTL_FLAG_SGI 0x04 /* use short-GI */
1184 +#define IEEE80211_RATECTL_FLAG_HT 0x08 /* use HT */
1185 +#define IEEE80211_RATECTL_FLAG_RTSCTS 0x10 /* enable RTS/CTS protection */
1186 +#define IEEE80211_RATECTL_FLAG_STBC 0x20 /* enable STBC */
1187 +#define IEEE80211_RATECTL_FLAG_TS 0x40 /* triple-stream rate */
1188 +#define IEEE80211_RATECTL_FLAG_SP 0x80 /* short preamble */
1189 +
1190 +/* Hardware CAPs offered to rate control algo */
1191 +#define IEEE80211_RATECTL_CAP_MRR 0x01 /* support MRR */
1192 +#define IEEE80211_RATECTL_CAP_MRRPROT 0x02 /* support MRR + protect */
1193 +#define IEEE80211_RATECTL_CAP_MULTXCHAIN 0x04 /* has more than 1 txchain */
1194 +
1195 +#define IS_VAP_HT(vap) ((vap)->iv_htcaps & IEEE80211_HTC_HT)
1196 +#define IS_HT_RATE(_rate) ((_rate) & 0x80)
1197 +#define HT_RC_2_MCS(_rc) ((_rc) & 0x7f)
1198 +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
1199 +
1200 +extern int max_4ms_framelen[4][32];
1201 +
1202 +struct ieee80211_rc_series {
1203 + uint8_t rix; /* ratetable index, not rate code */
1204 + uint8_t ratecode; /* hardware rate code */
1205 + uint8_t tries;
1206 + uint8_t tx_power_cap;
1207 + uint16_t flags;
1208 + uint16_t max4msframelen;
1209 +};
1210 +
1211 +struct ieee80211_rc_info {
1212 + struct ieee80211_rc_series iri_rc[IEEE80211_RATECTL_NUM];
1213 + uint32_t iri_framelen;
1214 + uint16_t iri_flags; /* See below */
1215 + uint16_t iri_maxaggrsize; /* Maximum aggregate size */
1216 +
1217 + /* TX info */
1218 + uint8_t iri_txcnt; /* TX count */
1219 + uint8_t iri_failcnt; /* TX retry-fail count */
1220 + uint8_t iri_okcnt; /* TX ok with or without retry */
1221 + uint8_t iri_retrycnt; /* TX retry count */
1222 + uint8_t iri_shortretry;
1223 + uint8_t iri_longretry;
1224 + uint8_t iri_finaltsi;
1225 + uint8_t iri_txrate; /* HW tx rate */
1226 +};
1227 +
1228 +/* ieee80211_rc_info flags */
1229 +#define IEEE80211_RATECTL_INFO_SP 0x01 /* short preamble */
1230 +#define IEEE80211_RATECTL_INFO_AGGR 0x02 /* aggregation scenario */
1231 +
1232 +#define NET80211_TAG_RATECTL 1 /* net80211 ratectl state */
1233 +
1234 +/*
1235 + * net80211 ratectl statistics.
1236 + * per vap ratectl seeting must start with this common state.
1237 + */
1238 +struct ieee80211_rc_stat {
1239 + uint32_t irs_capabilities; /* hardware capabilities offered to rc */
1240 +
1241 + /* ratectl statistics */
1242 + uint32_t irs_txcnt;
1243 + uint32_t irs_failcnt;
1244 + uint32_t irs_retrycnt;
1245 + uint32_t irs_shortretry;
1246 + uint32_t irs_longretry;
1247 +};
1248 +
1249 +#define IEEE80211_RATECTL_STAT(_vap) \
1250 + ((struct ieee80211_rc_stat *)((_vap)->iv_rs))
1251 +
1252 +#define IEEE80211_RATECTL_HASCAP_MRR(_vap) \
1253 + (IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MRR)
1254 +#define IEEE80211_RATECTL_HASCAP_MRRPROT(_vap) \
1255 + (IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MRRPROT)
1256 +#define IEEE80211_RATECTL_HASCAP_MULTXCHAIN(_vap) \
1257 + (IEEE80211_RATECTL_STAT(_vap)->irs_capabilities & IEEE80211_RATECTL_CAP_MULTXCHAIN)
1258 +
1259 struct ieee80211_ratectl {
1260 const char *ir_name;
1261 int (*ir_attach)(const struct ieee80211vap *);
1262 void (*ir_detach)(const struct ieee80211vap *);
1263 - void (*ir_init)(struct ieee80211vap *);
1264 + void (*ir_init)(struct ieee80211vap *, uint32_t);
1265 void (*ir_deinit)(struct ieee80211vap *);
1266 void (*ir_node_init)(struct ieee80211_node *);
1267 void (*ir_node_deinit)(struct ieee80211_node *);
1268 int (*ir_rate)(struct ieee80211_node *, void *, uint32_t);
1269 + void (*ir_rates)(struct ieee80211_node *, struct ieee80211_rc_info *);
1270 void (*ir_tx_complete)(const struct ieee80211vap *,
1271 - const struct ieee80211_node *, int,
1272 - void *, void *);
1273 + const struct ieee80211_node *, struct ieee80211_rc_info *);
1274 void (*ir_tx_update)(const struct ieee80211vap *,
1275 const struct ieee80211_node *,
1276 void *, void *, void *);
1277 void (*ir_setinterval)(const struct ieee80211vap *, int);
1278 + void (*ir_stats)(const struct ieee80211vap *);
1279 };
1280
1281 void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
1282 void ieee80211_ratectl_unregister(int);
1283 -void ieee80211_ratectl_init(struct ieee80211vap *);
1284 +void ieee80211_ratectl_init(struct ieee80211vap *, uint32_t);
1285 void ieee80211_ratectl_set(struct ieee80211vap *, int);
1286 +void ieee80211_ratectl_complete_rcflags(struct ieee80211_node *,
1287 + struct ieee80211_rc_info*);
1288
1289 MALLOC_DECLARE(M_80211_RATECTL);
1290
1291 @@ -74,6 +164,8 @@
1292 const struct ieee80211vap *vap = ni->ni_vap;
1293
1294 vap->iv_rate->ir_node_init(ni);
1295 + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1296 + "%s: net80211 ratectl node inited.\n", __func__);
1297 }
1298
1299 static void __inline
1300 @@ -82,6 +174,8 @@
1301 const struct ieee80211vap *vap = ni->ni_vap;
1302
1303 vap->iv_rate->ir_node_deinit(ni);
1304 + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1305 + "%s: net80211 ratectl node deinited.\n", __func__);
1306 }
1307
1308 static int __inline
1309 @@ -93,10 +187,26 @@
1310 }
1311
1312 static void __inline
1313 +ieee80211_ratectl_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1314 +{
1315 + const struct ieee80211vap *vap = ni->ni_vap;
1316 +
1317 + if (rc_info->iri_flags & IEEE80211_RATECTL_INFO_AGGR)
1318 + rc_info->iri_framelen = 0;
1319 +
1320 + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
1321 + "%s: find rate sets for %saggregation scenario.\n", __func__,
1322 + (rc_info->iri_flags & IEEE80211_RATECTL_INFO_AGGR)? "" : "non-");
1323 +
1324 + vap->iv_rate->ir_rates(ni, rc_info);
1325 + ieee80211_ratectl_complete_rcflags(ni, rc_info);
1326 +}
1327 +
1328 +static void __inline
1329 ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
1330 - const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
1331 + const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1332 {
1333 - vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2);
1334 + vap->iv_rate->ir_tx_complete(vap, ni, rc_info);
1335 }
1336
1337 static void __inline
1338 @@ -115,3 +225,135 @@
1339 return;
1340 vap->iv_rate->ir_setinterval(vap, msecs);
1341 }
1342 +
1343 +static void __inline
1344 +ieee80211_ratectl_stats(const struct ieee80211vap *vap)
1345 +{
1346 + printf("\n[%s]: net80211 ratectl statistics (%s)\n",
1347 + vap->iv_ifp->if_xname, vap->iv_rate->ir_name);
1348 + if (vap->iv_rate->ir_stats == NULL)
1349 + return;
1350 + vap->iv_rate->ir_stats(vap);
1351 +}
1352 +
1353 +static int __inline
1354 +ieee80211_ratectl_hascap_cw40(const struct ieee80211_node *ni)
1355 +{
1356 + return ni->ni_chw == 40;
1357 +}
1358 +
1359 +static int __inline
1360 +ieee80211_ratectl_hascap_shortgi(const struct ieee80211_node *ni)
1361 +{
1362 + struct ieee80211com *ic = ni->ni_ic;
1363 +
1364 + if (ni->ni_chw == 40 &&
1365 + ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
1366 + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
1367 + return IEEE80211_RATECTL_TRUE;
1368 +
1369 + if (ni->ni_chw == 20 &&
1370 + ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
1371 + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
1372 + return IEEE80211_RATECTL_TRUE;
1373 +
1374 + return IEEE80211_RATECTL_FALSE;
1375 +}
1376 +
1377 +static int __inline
1378 +ieee80211_ratectl_hascap_stbc(const struct ieee80211_node *ni)
1379 +{
1380 + struct ieee80211com *ic = ni->ni_ic;
1381 +
1382 + if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
1383 + ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
1384 + IEEE80211_RATECTL_HASCAP_MULTXCHAIN(ni->ni_vap))
1385 + return IEEE80211_RATECTL_TRUE;
1386 +
1387 + return IEEE80211_RATECTL_FALSE;
1388 +}
1389 +
1390 +static int __inline
1391 +ieee80211_ratectl_node_is11n(const struct ieee80211_node *ni)
1392 +{
1393 + if (ni->ni_chan == NULL)
1394 + return (0);
1395 + if (ni->ni_chan == IEEE80211_CHAN_ANYC)
1396 + return (0);
1397 + return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
1398 +}
1399 +
1400 +__inline static const struct ieee80211_rateset *
1401 +ieee80211_ratectl_get_rateset(const struct ieee80211_node *ni)
1402 +{
1403 + const struct ieee80211_rateset *rs = NULL;
1404 + /* 11n or not? Pick the right rateset */
1405 + if (ieee80211_ratectl_node_is11n(ni)) {
1406 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1407 + "%s: 11n node", __func__);
1408 + rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1409 + } else {
1410 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1411 + "%s: non-11n node", __func__);
1412 + rs = &ni->ni_rates;
1413 + }
1414 + return rs;
1415 +}
1416 +
1417 +static void __inline
1418 +ieee80211_ratectl_update_stat(const struct ieee80211vap *vap,
1419 + const struct ieee80211_rc_info *rc_info)
1420 +{
1421 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1422 + irs->irs_txcnt += rc_info->iri_txcnt;
1423 + irs->irs_failcnt += rc_info->iri_failcnt;
1424 + irs->irs_retrycnt += rc_info->iri_retrycnt;
1425 + irs->irs_shortretry += rc_info->iri_shortretry;
1426 + irs->irs_longretry += rc_info->iri_longretry;
1427 +}
1428 +
1429 +static void __inline
1430 +ieee80211_ratectl_rc_info_set(struct ieee80211_rc_info *rc_info,
1431 + uint8_t txcnt, uint8_t failcnt, uint32_t framelen,
1432 + uint8_t shortretry, uint8_t longretry,
1433 + uint8_t finaltsi, uint8_t txrate)
1434 +{
1435 + rc_info->iri_txcnt = txcnt;
1436 + rc_info->iri_failcnt = failcnt;
1437 + rc_info->iri_okcnt = txcnt - failcnt;
1438 + rc_info->iri_framelen = framelen;
1439 + rc_info->iri_shortretry = shortretry;
1440 + rc_info->iri_longretry = longretry;
1441 + rc_info->iri_retrycnt = shortretry + longretry;
1442 + rc_info->iri_finaltsi = finaltsi;
1443 + rc_info->iri_txrate = txrate;
1444 +}
1445 +
1446 +__inline static struct ieee80211_rc_info *
1447 +ieee80211_ratectl_rc_info_get(struct ieee80211_node *ni,
1448 + struct mbuf *m)
1449 +{
1450 + struct m_tag *mtag;
1451 +
1452 + mtag = m_tag_locate(m, MTAG_ABI_NET80211,
1453 + NET80211_TAG_RATECTL, NULL);
1454 +
1455 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1456 + "%s: %sratectl mbuf tag found.\n", __func__,
1457 + (NULL == mtag? "no ":""));
1458 +again:
1459 + if (NULL == mtag) {
1460 + mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_RATECTL,
1461 + sizeof(struct ieee80211_rc_info), M_NOWAIT);
1462 + if (NULL == mtag) {
1463 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1464 + "%s: can't alloc mbuf tag for ratectl.\n", __func__);
1465 + goto again;
1466 + }
1467 + bzero(mtag + 1, mtag->m_tag_len);
1468 + m_tag_prepend(m, mtag);
1469 + }
1470 + return (struct ieee80211_rc_info*)(mtag + 1);
1471 +}
1472 +
1473 +#endif
1474 Index: sys/net80211/ieee80211_sample_txsched.h
1475 ===================================================================
1476 --- sys/net80211/ieee80211_sample_txsched.h (revision 0)
1477 +++ sys/net80211/ieee80211_sample_txsched.h (revision 257398)
1478 @@ -0,0 +1,241 @@
1479 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/tx_schedules.h 240384 2012-08-15 07:50:42Z adrian $*/
1480 +
1481 +/*-
1482 + * Copyright (c) 2005 John Bicket
1483 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
1484 + * All rights reserved.
1485 + *
1486 + * Redistribution and use in source and binary forms, with or without
1487 + * modification, are permitted provided that the following conditions
1488 + * are met:
1489 + * 1. Redistributions of source code must retain the above copyright
1490 + * notice, this list of conditions and the following disclaimer,
1491 + * without modification.
1492 + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1493 + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1494 + * redistribution must be conditioned upon including a substantially
1495 + * similar Disclaimer requirement for further binary redistribution.
1496 + * 3. Neither the names of the above-listed copyright holders nor the names
1497 + * of any contributors may be used to endorse or promote products derived
1498 + * from this software without specific prior written permission.
1499 + *
1500 + * Alternatively, this software may be distributed under the terms of the
1501 + * GNU General Public License ("GPL") version 2 as published by the Free
1502 + * Software Foundation.
1503 + *
1504 + * NO WARRANTY
1505 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1506 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1507 + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
1508 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1509 + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
1510 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1511 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1512 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
1513 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1514 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1515 + * THE POSSIBILITY OF SUCH DAMAGES.
1516 + *
1517 + */
1518 +#ifndef _NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_
1519 +#define _NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_
1520 +
1521 +#include <sys/cdefs.h>
1522 +
1523 +#define A(_r) \
1524 + (((_r) == 6) ? 0 : (((_r) == 9) ? 1 : (((_r) == 12) ? 2 : \
1525 + (((_r) == 18) ? 3 : (((_r) == 24) ? 4 : (((_r) == 36) ? 5 : \
1526 + (((_r) == 48) ? 6 : (((_r) == 54) ? 7 : 0))))))))
1527 +static const struct txschedule series_11a[] = {
1528 + { 3,A( 6), 3,A( 6), 0,A( 6), 0,A( 6) }, /* 6Mb/s */
1529 + { 4,A( 9), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 9Mb/s */
1530 + { 4,A(12), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 12Mb/s */
1531 + { 4,A(18), 3,A( 12), 4,A( 6), 2,A( 6) }, /* 18Mb/s */
1532 + { 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) }, /* 24Mb/s */
1533 + { 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) }, /* 36Mb/s */
1534 + { 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) }, /* 48Mb/s */
1535 + { 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) } /* 54Mb/s */
1536 +};
1537 +
1538 +#define NA1(_r) \
1539 + (((_r) == 6.5) ? 8 : (((_r) == 13) ? 9 : (((_r) == 19.5)? 10 : \
1540 + (((_r) == 26) ? 11 : (((_r) == 39) ? 12 : (((_r) == 52) ? 13 : \
1541 + (((_r) == 58.5)? 14 : (((_r) == 65) ? 15 : 0))))))))
1542 +#define NA2(_r) \
1543 + (((_r) == 13) ? 16 : (((_r) == 26) ? 17 : (((_r) == 39) ? 18 : \
1544 + (((_r) == 52) ? 19 : (((_r) == 78) ? 20 : (((_r) == 104)? 21 : \
1545 + (((_r) == 117)? 22 : (((_r) == 130)? 23 : 0))))))))
1546 +#define NA3(_r) \
1547 + (((_r) == 19.5) ? 24 : (((_r) == 39) ? 25 : (((_r) == 58.5) ? 26 : \
1548 + (((_r) == 78) ? 27 : (((_r) == 117) ? 28 : (((_r) == 156) ? 29 : \
1549 + (((_r) == 175.5) ? 30 : (((_r) == 195)? 31 : 0))))))))
1550 +static const struct txschedule series_11na[] = {
1551 + { 3,A( 6), 3,A( 6), 0,A( 6), 0,A( 6) }, /* 6Mb/s */
1552 + { 4,A( 9), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 9Mb/s */
1553 + { 4,A(12), 3,A( 6), 4,A( 6), 0,A( 6) }, /* 12Mb/s */
1554 + { 4,A(18), 3,A( 12), 4,A( 6), 2,A( 6) }, /* 18Mb/s */
1555 + { 4,A(24), 3,A( 18), 4,A( 12), 2,A( 6) }, /* 24Mb/s */
1556 + { 4,A(36), 3,A( 24), 4,A( 18), 2,A( 6) }, /* 36Mb/s */
1557 + { 4,A(48), 3,A( 36), 4,A( 24), 2,A(12) }, /* 48Mb/s */
1558 + { 4,A(54), 3,A( 48), 4,A( 36), 2,A(24) }, /* 54Mb/s */
1559 +
1560 + /* 1 stream rates */
1561 +
1562 + { 3,NA1( 6.5), 3,NA1( 6.5), 0,NA1( 6.5), 0,NA1(6.5) }, /* 6.5Mb/s */
1563 + { 4,NA1( 13), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) }, /* 13Mb/s */
1564 + { 4,NA1(19.5), 3,NA1( 6.5), 4,NA1( 6.5), 0,NA1(6.5) }, /*19.5Mb/s */
1565 + { 4,NA1( 26), 3,NA1(19.5), 4,NA1( 6.5), 2,NA1(6.5) }, /* 26Mb/s */
1566 + { 4,NA1( 39), 3,NA1( 26), 4,NA1(19.5), 2,NA1(6.5) }, /* 39Mb/s */
1567 + { 4,NA1( 52), 3,NA1( 39), 4,NA1( 26), 2,NA1(6.5) }, /* 52Mb/s */
1568 + { 4,NA1(58.5), 3,NA1( 52), 4,NA1( 39), 2,NA1( 13) }, /*58.5Mb/s */
1569 + { 4,NA1( 65), 3,NA1(58.5), 4,NA1( 52), 2,NA1( 13) }, /* 65Mb/s */
1570 +
1571 + /* 2 stream rates */
1572 +
1573 + { 3,NA2( 13), 3,NA2( 13), 0,NA2( 13), 0,NA2( 13) }, /* 13Mb/s */
1574 + { 4,NA2( 26), 3,NA2( 13), 4,NA2( 13), 0,NA2( 13) }, /* 26Mb/s */
1575 + { 4,NA2( 39), 3,NA2( 26), 4,NA2( 13), 2,NA2( 13) }, /* 39Mb/s */
1576 + { 4,NA2( 52), 3,NA2( 39), 4,NA2( 26), 2,NA2( 13) }, /* 52Mb/s */
1577 + { 4,NA2( 78), 3,NA2( 52), 4,NA2( 39), 2,NA2( 13) }, /* 78Mb/s */
1578 + { 4,NA2( 104), 3,NA2( 78), 4,NA2( 52), 2,NA2( 13) }, /* 104Mb/s */
1579 + { 4,NA2( 117), 3,NA2( 104), 4,NA2( 78), 2,NA2( 26) }, /* 117Mb/s */
1580 + { 4,NA2( 130), 3,NA2( 117), 4,NA2( 104), 2,NA2( 26) }, /* 130Mb/s */
1581 +
1582 + /* 3 stream rates */
1583 +
1584 + { 3,NA3(19.5), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) }, /* 19Mb/s */
1585 + { 3,NA3( 39), 3,NA3(19.5), 0,NA3(19.5), 0,NA3(19.5) }, /* 39Mb/s */
1586 + { 3,NA3(58.5), 3,NA3( 39), 0,NA3(19.5), 0,NA3(19.5) }, /* 58Mb/s */
1587 + { 3,NA3( 78), 3,NA3(58.5), 0,NA3( 39), 0,NA3(19.5) }, /* 78Mb/s */
1588 + { 3,NA3( 117), 3,NA3( 78), 0,NA3(58.5), 0,NA3(19.5) }, /* 117Mb/s */
1589 + { 3,NA3( 156), 3,NA3( 117), 0,NA3( 78), 0,NA3(19.5) }, /* 156Mb/s */
1590 + { 3,NA3(175.5), 3,NA3( 156), 0,NA3( 117), 0,NA3( 39) }, /* 175Mb/s */
1591 + { 3,NA3( 195), 3,NA3( 195), 0,NA3( 156), 0,NA3(58.5) }, /* 195Mb/s */
1592 +};
1593 +#undef A
1594 +#undef NA3
1595 +#undef NA2
1596 +#undef NA1
1597 +
1598 +#define G(_r) \
1599 + (((_r) == 1) ? 0 : (((_r) == 2) ? 1 : (((_r) == 5.5) ? 2 : \
1600 + (((_r) == 11) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \
1601 + (((_r) == 12) ? 6 : (((_r) == 18) ? 7 : (((_r) == 24) ? 8 : \
1602 + (((_r) == 36) ? 9 : (((_r) == 48) ? 10 : (((_r) == 54) ? 11 : 0))))))))))))
1603 +static const struct txschedule series_11g[] = {
1604 + { 3,G( 1), 3,G( 1), 0,G( 1), 0,G( 1) }, /* 1Mb/s */
1605 + { 4,G( 2), 3,G( 1), 4,G( 1), 0,G( 1) }, /* 2Mb/s */
1606 + { 4,G(5.5),3,G( 2), 4,G( 1), 2,G( 1) }, /* 5.5Mb/s */
1607 + { 4,G(11), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 11Mb/s */
1608 + { 4,G( 6), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 6Mb/s */
1609 + { 4,G( 9), 3,G( 6), 4,G(5.5), 2,G( 1) }, /* 9Mb/s */
1610 + { 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) }, /* 12Mb/s */
1611 + { 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) }, /* 18Mb/s */
1612 + { 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) }, /* 24Mb/s */
1613 + { 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) }, /* 36Mb/s */
1614 + { 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) }, /* 48Mb/s */
1615 + { 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) } /* 54Mb/s */
1616 +};
1617 +
1618 +#define NG1(_r) \
1619 + (((_r) == 6.5) ? 12 : (((_r) == 13) ? 13 : (((_r) == 19.5)? 14 : \
1620 + (((_r) == 26) ? 15 : (((_r) == 39) ? 16 : (((_r) == 52) ? 17 : \
1621 + (((_r) == 58.5)? 18 : (((_r) == 65) ? 19 : 0))))))))
1622 +#define NG2(_r) \
1623 + (((_r) == 13) ? 20 : (((_r) == 26) ? 21 : (((_r) == 39) ? 22 : \
1624 + (((_r) == 52) ? 23 : (((_r) == 78) ? 24 : (((_r) == 104) ? 25 : \
1625 + (((_r) == 117) ? 26 : (((_r) == 130)? 27 : 0))))))))
1626 +#define NG3(_r) \
1627 + (((_r) == 19.5) ? 28 : (((_r) == 39) ? 29 : (((_r) == 58.5) ? 30 : \
1628 + (((_r) == 78) ? 31 : (((_r) == 117) ? 32 : (((_r) == 156) ? 33 : \
1629 + (((_r) == 175.5) ? 34 : (((_r) == 195)? 35 : 0))))))))
1630 +
1631 +static const struct txschedule series_11ng[] = {
1632 + { 3,G( 1), 3,G( 1), 0,G( 1), 0,G( 1) }, /* 1Mb/s */
1633 + { 4,G( 2), 3,G( 1), 4,G( 1), 0,G( 1) }, /* 2Mb/s */
1634 + { 4,G(5.5),3,G( 2), 4,G( 1), 2,G( 1) }, /* 5.5Mb/s */
1635 + { 4,G(11), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 11Mb/s */
1636 + { 4,G( 6), 3,G(5.5), 4,G( 2), 2,G( 1) }, /* 6Mb/s */
1637 + { 4,G( 9), 3,G( 6), 4,G(5.5), 2,G( 1) }, /* 9Mb/s */
1638 + { 4,G(12), 3,G( 11), 4,G(5.5), 2,G( 1) }, /* 12Mb/s */
1639 + { 4,G(18), 3,G( 12), 4,G( 11), 2,G( 1) }, /* 18Mb/s */
1640 + { 4,G(24), 3,G( 18), 4,G( 12), 2,G( 1) }, /* 24Mb/s */
1641 + { 4,G(36), 3,G( 24), 4,G( 18), 2,G( 1) }, /* 36Mb/s */
1642 + { 4,G(48), 3,G( 36), 4,G( 24), 2,G( 1) }, /* 48Mb/s */
1643 + { 4,G(54), 3,G( 48), 4,G( 36), 2,G( 1) }, /* 54Mb/s */
1644 +
1645 + /* 1 stream rates */
1646 +
1647 + { 3,NG1( 6.5), 3,NG1( 6.5), 0,NG1( 6.5), 0,NG1(6.5) }, /* 6.5Mb/s */
1648 + { 4,NG1( 13), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) }, /* 13Mb/s */
1649 + { 4,NG1(19.5), 3,NG1( 6.5), 4,NG1( 6.5), 0,NG1(6.5) }, /*19.5Mb/s */
1650 + { 4,NG1( 26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) }, /* 26Mb/s */
1651 + { 4,NG1( 39), 3,NG1( 26), 4,NG1(19.5), 2,NG1(6.5) }, /* 39Mb/s */
1652 + { 4,NG1( 52), 3,NG1( 39), 4,NG1( 26), 2,NG1(6.5) }, /* 52Mb/s */
1653 + { 4,NG1(58.5), 3,NG1( 52), 4,NG1( 39), 2,NG1( 13) }, /*58.5Mb/s */
1654 + { 4,NG1( 65), 3,NG1(58.5), 4,NG1( 52), 2,NG1( 13) }, /* 65Mb/s */
1655 +
1656 + /* 2 stream rates */
1657 +
1658 + { 3,NG2( 13), 3,NG2( 13), 0,NG2( 13), 0,NG2( 13) }, /* 13Mb/s */
1659 + { 4,NG2( 26), 3,NG2( 13), 4,NG2( 13), 0,NG2( 13) }, /* 26Mb/s */
1660 + { 4,NG2( 39), 3,NG2( 26), 4,NG2( 13), 2,NG2( 13) }, /* 39Mb/s */
1661 + { 4,NG2( 52), 3,NG2( 39), 4,NG2( 26), 2,NG2( 13) }, /* 52Mb/s */
1662 + { 4,NG2( 78), 3,NG2( 52), 4,NG2( 39), 2,NG2( 13) }, /* 78Mb/s */
1663 + { 4,NG2( 104), 3,NG2( 78), 4,NG2( 52), 2,NG2( 13) }, /* 104Mb/s */
1664 + { 4,NG2( 117), 3,NG2( 104), 4,NG2( 78), 2,NG2( 26) }, /* 117Mb/s */
1665 + { 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) }, /* 130Mb/s */
1666 +
1667 + /* 3 stream rates */
1668 +
1669 + { 3,NG3(19.5), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) }, /* 19Mb/s */
1670 + { 3,NG3( 39), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) }, /* 39Mb/s */
1671 + { 3,NG3(58.5), 3,NG3( 39), 0,NG3(19.5), 0,NG3(19.5) }, /* 58Mb/s */
1672 + { 3,NG3( 78), 3,NG3(58.5), 0,NG3( 39), 0,NG3(19.5) }, /* 78Mb/s */
1673 + { 3,NG3( 117), 3,NG3( 78), 0,NG3(58.5), 0,NG3(19.5) }, /* 117Mb/s */
1674 + { 3,NG3( 156), 3,NG3( 117), 0,NG3( 78), 0,NG3(19.5) }, /* 156Mb/s */
1675 + { 3,NG3(175.5), 3,NG3( 156), 0,NG3( 117), 0,NG3( 39) }, /* 175Mb/s */
1676 + { 3,NG3( 195), 3,NG3( 195), 0,NG3( 156), 0,NG3(58.5) }, /* 195Mb/s */
1677 +
1678 +};
1679 +#undef G
1680 +#undef NG3
1681 +#undef NG2
1682 +#undef NG1
1683 +
1684 +#define H(_r) \
1685 + (((_r) == 3) ? 0 : (((_r) == 4.5) ? 1 : (((_r) == 6) ? 2 : \
1686 + (((_r) == 9) ? 3 : (((_r) == 12) ? 4 : (((_r) == 18) ? 5 : \
1687 + (((_r) == 24) ? 6 : (((_r) == 27) ? 7 : 0))))))))
1688 +static const struct txschedule series_half[] = {
1689 + { 3,H( 3), 3,H( 3), 0,H( 3), 0,H( 3) }, /* 3Mb/s */
1690 + { 4,H(4.5),3,H( 3), 4,H( 3), 0,H( 3) }, /* 4.5Mb/s */
1691 + { 4,H( 6), 3,H( 3), 4,H( 3), 0,H( 3) }, /* 6Mb/s */
1692 + { 4,H( 9), 3,H( 6), 4,H( 3), 2,H( 3) }, /* 9Mb/s */
1693 + { 4,H(12), 3,H( 9), 4,H( 6), 2,H( 3) }, /* 12Mb/s */
1694 + { 4,H(18), 3,H( 12), 4,H( 9), 2,H( 3) }, /* 18Mb/s */
1695 + { 4,H(24), 3,H( 18), 4,H( 12), 2,H( 6) }, /* 24Mb/s */
1696 + { 4,H(27), 3,H( 24), 4,H( 18), 2,H(12) } /* 27Mb/s */
1697 +};
1698 +#undef H
1699 +
1700 +#ifdef Q
1701 +#undef Q
1702 +#endif
1703 +#define Q(_r) \
1704 + (((_r) == 1.5) ? 0 : (((_r) ==2.25) ? 1 : (((_r) == 3) ? 2 : \
1705 + (((_r) == 4.5) ? 3 : (((_r) == 6) ? 4 : (((_r) == 9) ? 5 : \
1706 + (((_r) == 12) ? 6 : (((_r) == 13.5)? 7 : 0))))))))
1707 +static const struct txschedule series_quarter[] = {
1708 + { 3,Q( 1.5),3,Q(1.5), 0,Q(1.5), 0,Q(1.5) }, /* 1.5Mb/s */
1709 + { 4,Q(2.25),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /*2.25Mb/s */
1710 + { 4,Q( 3),3,Q(1.5), 4,Q(1.5), 0,Q(1.5) }, /* 3Mb/s */
1711 + { 4,Q( 4.5),3,Q( 3), 4,Q(1.5), 2,Q(1.5) }, /* 4.5Mb/s */
1712 + { 4,Q( 6),3,Q(4.5), 4,Q( 3), 2,Q(1.5) }, /* 6Mb/s */
1713 + { 4,Q( 9),3,Q( 6), 4,Q(4.5), 2,Q(1.5) }, /* 9Mb/s */
1714 + { 4,Q( 12),3,Q( 9), 4,Q( 6), 2,Q( 3) }, /* 12Mb/s */
1715 + { 4,Q(13.5),3,Q( 12), 4,Q( 9), 2,Q( 6) } /*13.5Mb/s */
1716 +};
1717 +#undef Q
1718 +
1719 +#endif /* _NET80211_IEEE80211_RATECTL_SAMPLE_TXSCHEDULES_H_ */
1720 Index: sys/net80211/ieee80211_rssadapt.c
1721 ===================================================================
1722 --- sys/net80211/ieee80211_rssadapt.c (revision 254826)
1723 +++ sys/net80211/ieee80211_rssadapt.c (working copy)
1724 @@ -74,7 +74,7 @@
1725 parm##_denom)
1726
1727 static void rssadapt_setinterval(const struct ieee80211vap *, int);
1728 -static void rssadapt_init(struct ieee80211vap *);
1729 +static void rssadapt_init(struct ieee80211vap *, uint32_t);
1730 static void rssadapt_deinit(struct ieee80211vap *);
1731 static void rssadapt_updatestats(struct ieee80211_rssadapt_node *);
1732 static void rssadapt_node_init(struct ieee80211_node *);
1733 @@ -84,8 +84,7 @@
1734 static void rssadapt_raise_rate(struct ieee80211_rssadapt_node *,
1735 int, int);
1736 static void rssadapt_tx_complete(const struct ieee80211vap *,
1737 - const struct ieee80211_node *, int,
1738 - void *, void *);
1739 + const struct ieee80211_node *, struct ieee80211_rc_info *);
1740 static void rssadapt_sysctlattach(struct ieee80211vap *,
1741 struct sysctl_ctx_list *, struct sysctl_oid *);
1742
1743 @@ -121,7 +120,7 @@
1744 }
1745
1746 static void
1747 -rssadapt_init(struct ieee80211vap *vap)
1748 +rssadapt_init(struct ieee80211vap *vap, uint32_t capabilities)
1749 {
1750 struct ieee80211_rssadapt *rs;
1751
1752 @@ -134,6 +133,10 @@
1753 if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
1754 return;
1755 }
1756 +
1757 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1758 + irs->irs_capabilities = capabilities;
1759 +
1760 rs->vap = vap;
1761 rssadapt_setinterval(vap, 500 /* msecs */);
1762 rssadapt_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid);
1763 @@ -307,10 +310,11 @@
1764
1765 static void
1766 rssadapt_tx_complete(const struct ieee80211vap *vap,
1767 - const struct ieee80211_node *ni, int success, void *arg1, void *arg2)
1768 + const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
1769 {
1770 struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
1771 - int pktlen = *(int *)arg1, rssi = *(int *)arg2;
1772 + /*int pktlen = *(int *)arg1, rssi = *(int *)arg2;*/
1773 + int pktlen = 0, rssi = 0, success = 0; /* just make it compiled. qcc */
1774
1775 if (success) {
1776 ra->ra_nok++;
1777 Index: sys/net80211/ieee80211_amrr.c
1778 ===================================================================
1779 --- sys/net80211/ieee80211_amrr.c (revision 254826)
1780 +++ sys/net80211/ieee80211_amrr.c (working copy)
1781 @@ -47,8 +47,8 @@
1782
1783 #include <net80211/ieee80211_var.h>
1784 #include <net80211/ieee80211_ht.h>
1785 +#include <net80211/ieee80211_ratectl.h>
1786 #include <net80211/ieee80211_amrr.h>
1787 -#include <net80211/ieee80211_ratectl.h>
1788
1789 #define is_success(amn) \
1790 ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
1791 @@ -57,19 +57,18 @@
1792 #define is_enough(amn) \
1793 ((amn)->amn_txcnt > 10)
1794
1795 -static void amrr_setinterval(const struct ieee80211vap *, int);
1796 -static void amrr_init(struct ieee80211vap *);
1797 +static void amrr_init(struct ieee80211vap *, uint32_t);
1798 static void amrr_deinit(struct ieee80211vap *);
1799 static void amrr_node_init(struct ieee80211_node *);
1800 static void amrr_node_deinit(struct ieee80211_node *);
1801 -static int amrr_update(struct ieee80211_amrr *,
1802 - struct ieee80211_amrr_node *, struct ieee80211_node *);
1803 static int amrr_rate(struct ieee80211_node *, void *, uint32_t);
1804 +static void amrr_rates(struct ieee80211_node *, struct ieee80211_rc_info *);
1805 static void amrr_tx_complete(const struct ieee80211vap *,
1806 - const struct ieee80211_node *, int,
1807 - void *, void *);
1808 -static void amrr_tx_update(const struct ieee80211vap *vap,
1809 + const struct ieee80211_node *, struct ieee80211_rc_info *);
1810 +static void amrr_tx_update(const struct ieee80211vap *,
1811 const struct ieee80211_node *, void *, void *, void *);
1812 +static void amrr_stats(const struct ieee80211vap *);
1813 +static void amrr_setinterval(const struct ieee80211vap *, int);
1814 static void amrr_sysctlattach(struct ieee80211vap *,
1815 struct sysctl_ctx_list *, struct sysctl_oid *);
1816
1817 @@ -85,9 +84,11 @@
1818 .ir_node_init = amrr_node_init,
1819 .ir_node_deinit = amrr_node_deinit,
1820 .ir_rate = amrr_rate,
1821 + .ir_rates = amrr_rates,
1822 .ir_tx_complete = amrr_tx_complete,
1823 .ir_tx_update = amrr_tx_update,
1824 .ir_setinterval = amrr_setinterval,
1825 + .ir_stats = amrr_stats,
1826 };
1827 IEEE80211_RATECTL_MODULE(amrr, 1);
1828 IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr);
1829 @@ -105,7 +106,7 @@
1830 }
1831
1832 static void
1833 -amrr_init(struct ieee80211vap *vap)
1834 +amrr_init(struct ieee80211vap *vap, uint32_t capabilities)
1835 {
1836 struct ieee80211_amrr *amrr;
1837
1838 @@ -117,6 +118,10 @@
1839 if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
1840 return;
1841 }
1842 +
1843 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
1844 + irs->irs_capabilities = capabilities;
1845 +
1846 amrr->amrr_min_success_threshold = IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD;
1847 amrr->amrr_max_success_threshold = IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD;
1848 amrr_setinterval(vap, 500 /* ms */);
1849 @@ -129,17 +134,6 @@
1850 free(vap->iv_rs, M_80211_RATECTL);
1851 }
1852
1853 -static int
1854 -amrr_node_is_11n(struct ieee80211_node *ni)
1855 -{
1856 -
1857 - if (ni->ni_chan == NULL)
1858 - return (0);
1859 - if (ni->ni_chan == IEEE80211_CHAN_ANYC)
1860 - return (0);
1861 - return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
1862 -}
1863 -
1864 static void
1865 amrr_node_init(struct ieee80211_node *ni)
1866 {
1867 @@ -159,29 +153,20 @@
1868 }
1869 } else
1870 amn = ni->ni_rctls;
1871 +
1872 amn->amn_amrr = amrr;
1873 amn->amn_success = 0;
1874 amn->amn_recovery = 0;
1875 amn->amn_txcnt = amn->amn_retrycnt = 0;
1876 amn->amn_success_threshold = amrr->amrr_min_success_threshold;
1877
1878 - /* 11n or not? Pick the right rateset */
1879 - if (amrr_node_is_11n(ni)) {
1880 - /* XXX ew */
1881 - IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1882 - "%s: 11n node", __func__);
1883 - rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1884 - } else {
1885 - IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1886 - "%s: non-11n node", __func__);
1887 - rs = &ni->ni_rates;
1888 - }
1889 + rs = ieee80211_ratectl_get_rateset(ni);
1890
1891 /* Initial rate - lowest */
1892 rate = rs->rs_rates[0];
1893
1894 /* XXX clear the basic rate flag if it's not 11n */
1895 - if (! amrr_node_is_11n(ni))
1896 + if (! ieee80211_ratectl_node_is11n(ni))
1897 rate &= IEEE80211_RATE_VAL;
1898
1899 /* pick initial rate from the rateset - HT or otherwise */
1900 @@ -189,7 +174,7 @@
1901 amn->amn_rix--) {
1902 /* legacy - anything < 36mbit, stop searching */
1903 /* 11n - stop at MCS4 / MCS12 / MCS28 */
1904 - if (amrr_node_is_11n(ni) &&
1905 + if (ieee80211_ratectl_node_is11n(ni) &&
1906 (rs->rs_rates[amn->amn_rix] & 0x7) < 4)
1907 break;
1908 else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72)
1909 @@ -198,7 +183,7 @@
1910 }
1911
1912 /* if the rate is an 11n rate, ensure the MCS bit is set */
1913 - if (amrr_node_is_11n(ni))
1914 + if (ieee80211_ratectl_node_is11n(ni))
1915 rate |= IEEE80211_RATE_MCS;
1916
1917 /* Assign initial rate from the rateset */
1918 @@ -206,9 +191,8 @@
1919 amn->amn_ticks = ticks;
1920
1921 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1922 - "AMRR: nrates=%d, initial rate %d",
1923 - rs->rs_nrates,
1924 - rate);
1925 + "%s: AMRR: nrates=%d, initial rate %d",
1926 + __func__, rs->rs_nrates, rate);
1927 }
1928
1929 static void
1930 @@ -226,17 +210,12 @@
1931
1932 KASSERT(is_enough(amn), ("txcnt %d", amn->amn_txcnt));
1933
1934 - /* 11n or not? Pick the right rateset */
1935 - if (amrr_node_is_11n(ni)) {
1936 - /* XXX ew */
1937 - rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1938 - } else {
1939 - rs = &ni->ni_rates;
1940 - }
1941 + rs = ieee80211_ratectl_get_rateset(ni);
1942
1943 +
1944 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1945 - "AMRR: current rate %d, txcnt=%d, retrycnt=%d",
1946 - rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1947 + "%s: AMRR: current rate %d, txcnt=%d, retrycnt=%d",
1948 + __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1949 amn->amn_txcnt,
1950 amn->amn_retrycnt);
1951
1952 @@ -256,8 +235,8 @@
1953 amn->amn_success = 0;
1954 rix++;
1955 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1956 - "AMRR increasing rate %d (txcnt=%d retrycnt=%d)",
1957 - rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1958 + "%s: AMRR increasing rate %d (txcnt=%d retrycnt=%d)",
1959 + __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1960 amn->amn_txcnt, amn->amn_retrycnt);
1961 } else {
1962 amn->amn_recovery = 0;
1963 @@ -277,8 +256,8 @@
1964 }
1965 rix--;
1966 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1967 - "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)",
1968 - rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1969 + "%s: AMRR decreasing rate %d (txcnt=%d retrycnt=%d)",
1970 + __func__, rs->rs_rates[rix] & IEEE80211_RATE_VAL,
1971 amn->amn_txcnt, amn->amn_retrycnt);
1972 }
1973 amn->amn_recovery = 0;
1974 @@ -304,13 +283,7 @@
1975 const struct ieee80211_rateset *rs = NULL;
1976 int rix;
1977
1978 - /* 11n or not? Pick the right rateset */
1979 - if (amrr_node_is_11n(ni)) {
1980 - /* XXX ew */
1981 - rs = (struct ieee80211_rateset *) &ni->ni_htrates;
1982 - } else {
1983 - rs = &ni->ni_rates;
1984 - }
1985 + rs = ieee80211_ratectl_get_rateset(ni);
1986
1987 if (is_enough(amn) && (ticks - amn->amn_ticks) > amrr->amrr_interval) {
1988 rix = amrr_update(amrr, amn, ni);
1989 @@ -318,7 +291,7 @@
1990 /* update public rate */
1991 ni->ni_txrate = rs->rs_rates[rix];
1992 /* XXX strip basic rate flag from txrate, if non-11n */
1993 - if (amrr_node_is_11n(ni))
1994 + if (ieee80211_ratectl_node_is11n(ni))
1995 ni->ni_txrate |= IEEE80211_RATE_MCS;
1996 else
1997 ni->ni_txrate &= IEEE80211_RATE_VAL;
1998 @@ -330,6 +303,76 @@
1999 return rix;
2000 }
2001
2002 +static void
2003 +amrr_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2004 +{
2005 +#define RATE(_ix) (rs->rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2006 +#define MCS(_ix) (rs->rs_rates[(_ix)] | IEEE80211_RATE_MCS)
2007 + struct ieee80211_rc_series *rc = rc_info->iri_rc;
2008 + const struct ieee80211_rateset *rs = NULL;
2009 + const struct ieee80211_rate_table *rt = NULL;
2010 + int rix, code;
2011 +
2012 + rs = ieee80211_ratectl_get_rateset(ni);
2013 + rt = ieee80211_get_ratetable(ni->ni_ic->ic_curchan);
2014 + IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_RATECTL,
2015 + "%s: channel flags: 0x%08x\n", __func__,
2016 + ni->ni_ic->ic_curchan->ic_flags);
2017 +
2018 + rix = amrr_rate(ni, NULL, 0);
2019 +
2020 + rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
2021 +
2022 + if (rs->rs_nrates > 0) {
2023 + code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2024 + rc[0].rix = rt->rateCodeToIndex[code];
2025 +
2026 + if (IEEE80211_RATECTL_HASCAP_MRR(ni->ni_vap)) {
2027 + rc[0].tries = 1;
2028 + rc[1].tries = 1;
2029 + rc[2].tries = 1;
2030 + rc[3].tries = 1;
2031 + if (--rix >= 0) {
2032 + code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2033 + rc[1].rix = rt->rateCodeToIndex[code];
2034 + } else {
2035 + rc[1].rix = rt->rateCodeToIndex[0];
2036 + }
2037 + if (--rix >= 0) {
2038 + code = ieee80211_ratectl_node_is11n(ni)? MCS(rix) : RATE(rix);
2039 + rc[2].rix = rt->rateCodeToIndex[code];
2040 + } else {
2041 + rc[2].rix = rt->rateCodeToIndex[0];
2042 + }
2043 + if (rix >= 0) {
2044 + /* NB: only do this if we didn't already do it above */
2045 + code = ieee80211_ratectl_node_is11n(ni)? MCS(0) : RATE(0);
2046 + rc[3].rix = rt->rateCodeToIndex[code];
2047 + } else {
2048 + rc[3].rix = rt->rateCodeToIndex[0];
2049 + }
2050 + } else {
2051 + rc[0].tries = IEEE80211_RATECTL_TXMAXTRY;
2052 +
2053 + rc[1].tries = 0;
2054 + rc[2].tries = 0;
2055 + rc[3].tries = 0;
2056 + rc[1].rix = rt->rateCodeToIndex[0];
2057 + rc[2].rix = rt->rateCodeToIndex[0];
2058 + rc[3].rix = rt->rateCodeToIndex[0];
2059 + }
2060 + }
2061 + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
2062 + "%s: AMRR rate sets(rix, tries). rc[0]:(%d, %d), rc[1]:(%d, %d), "
2063 + "rc[2]:(%d, %d), rc[3]:(%d, %d)", __func__,
2064 + rc[0].rix, rc[0].tries,
2065 + rc[1].rix, rc[1].tries,
2066 + rc[2].rix, rc[2].tries,
2067 + rc[3].rix, rc[3].tries);
2068 +#undef RATE
2069 +#undef MCS
2070 +}
2071 +
2072 /*
2073 * Update statistics with tx complete status. Ok is non-zero
2074 * if the packet is known to be ACK'd. Retries has the number
2075 @@ -337,16 +380,22 @@
2076 */
2077 static void
2078 amrr_tx_complete(const struct ieee80211vap *vap,
2079 - const struct ieee80211_node *ni, int ok,
2080 - void *arg1, void *arg2 __unused)
2081 + const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2082 {
2083 struct ieee80211_amrr_node *amn = ni->ni_rctls;
2084 - int retries = *(int *)arg1;
2085
2086 - amn->amn_txcnt++;
2087 - if (ok)
2088 - amn->amn_success++;
2089 - amn->amn_retrycnt += retries;
2090 + /* update per vap statistics */
2091 + ieee80211_ratectl_update_stat(vap, rc_info);
2092 +
2093 + amn->amn_txcnt += rc_info->iri_txcnt;
2094 + amn->amn_success += (rc_info->iri_txcnt - rc_info->iri_failcnt);
2095 + amn->amn_retrycnt += rc_info->iri_retrycnt;
2096 +
2097 + IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
2098 + "%s: AMRR tx complete. txcnt=%d(%d) success=%d(%d) retrycnt=%d(%d)\n",
2099 + __func__, amn->amn_txcnt, rc_info->iri_txcnt,
2100 + amn->amn_success, (rc_info->iri_txcnt - rc_info->iri_failcnt),
2101 + amn->amn_retrycnt, rc_info->iri_retrycnt);
2102 }
2103
2104 /*
2105 @@ -364,8 +413,21 @@
2106 amn->amn_txcnt = txcnt;
2107 amn->amn_success = success;
2108 amn->amn_retrycnt = retrycnt;
2109 + IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
2110 + "%s: AMRR tx update. txcnt=%d success=%d retrycnt=%d\n",
2111 + __func__, txcnt, success, retrycnt);
2112 }
2113
2114 +static void
2115 +amrr_stats(const struct ieee80211vap *vap)
2116 +{
2117 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
2118 + printf("tx count: %d (ok count: %d, fail count: %d)\n"
2119 + "retry count: %d (short retry: %d, long retry: %d)\n",
2120 + irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
2121 + irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
2122 +}
2123 +
2124 static int
2125 amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
2126 {
2127 Index: sys/net80211/ieee80211_freebsd.c
2128 ===================================================================
2129 --- sys/net80211/ieee80211_freebsd.c (revision 254826)
2130 +++ sys/net80211/ieee80211_freebsd.c (working copy)
2131 @@ -262,7 +262,9 @@
2132 "driver_caps", CTLFLAG_RW, &vap->iv_caps, 0,
2133 "driver capabilities");
2134 #ifdef IEEE80211_DEBUG
2135 + ieee80211_debug |= (IEEE80211_MSG_RATECTL|IEEE80211_MSG_NODE|IEEE80211_MSG_SCAN);
2136 vap->iv_debug = ieee80211_debug;
2137 + if_printf(ifp, "%s: iv_debug=0x%08x\n", __func__, vap->iv_debug);
2138 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2139 "debug", CTLFLAG_RW, &vap->iv_debug, 0,
2140 "control debugging printfs");
2141 Index: sys/net80211/ieee80211_sample.c
2142 ===================================================================
2143 --- sys/net80211/ieee80211_sample.c (revision 0)
2144 +++ sys/net80211/ieee80211_sample.c (revision 257398)
2145 @@ -0,0 +1,1127 @@
2146 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 248573 2013-02-27 04:33:06Z adrian $*/
2147 +
2148 +/*-
2149 + * Copyright (c) 2005 John Bicket
2150 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
2151 + * All rights reserved.
2152 + *
2153 + * Redistribution and use in source and binary forms, with or without
2154 + * modification, are permitted provided that the following conditions
2155 + * are met:
2156 + * 1. Redistributions of source code must retain the above copyright
2157 + * notice, this list of conditions and the following disclaimer.
2158 + * 2. Redistributions in binary form must reproduce the above copyright
2159 + * notice, this list of conditions and the following disclaimer in the
2160 + * documentation and/or other materials provided with the distribution.
2161 + *
2162 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2163 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2164 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2165 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2166 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2167 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2168 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2169 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2170 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2171 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2172 + */
2173 +
2174 +#include <sys/cdefs.h>
2175 +
2176 +#include "opt_wlan.h"
2177 +
2178 +#include <sys/param.h>
2179 +#include <sys/kernel.h>
2180 +#include <sys/module.h>
2181 +#include <sys/socket.h>
2182 +#include <sys/sysctl.h>
2183 +
2184 +#include <net/if.h>
2185 +#include <net/if_media.h>
2186 +#include <net/ethernet.h>
2187 +
2188 +#ifdef INET
2189 +#include <netinet/in.h>
2190 +#include <netinet/if_ether.h>
2191 +#endif
2192 +
2193 +#include <net80211/ieee80211_var.h>
2194 +#include <net80211/ieee80211_ht.h>
2195 +#include <net80211/ieee80211_ratectl.h>
2196 +#include <net80211/ieee80211_sample.h>
2197 +#include <net80211/ieee80211_sample_txsched.h>
2198 +
2199 +static void sample_init(struct ieee80211vap *, uint32_t);
2200 +static void sample_deinit(struct ieee80211vap *);
2201 +static void sample_node_init(struct ieee80211_node *);
2202 +static void sample_node_deinit(struct ieee80211_node *);
2203 +static int sample_rate(struct ieee80211_node *, void *, uint32_t);
2204 +static void sample_rates(struct ieee80211_node *, struct ieee80211_rc_info *);
2205 +static void sample_tx_complete(const struct ieee80211vap *,
2206 + const struct ieee80211_node *, struct ieee80211_rc_info *);
2207 +static void sample_tx_update(const struct ieee80211vap *vap,
2208 + const struct ieee80211_node *, void *, void *, void *);
2209 +static void sample_stats(const struct ieee80211vap *);
2210 +static void sample_setinterval(const struct ieee80211vap *, int);
2211 +
2212 +static void sample_sysctlattach(struct ieee80211vap *,
2213 + struct sysctl_ctx_list *, struct sysctl_oid *);
2214 +static void sample_update_static_rix(struct ieee80211_node *);
2215 +
2216 +/* number of references from net80211 layer */
2217 +static int nrefs = 0;
2218 +
2219 +static const struct ieee80211_ratectl sample = {
2220 + .ir_name = "sample",
2221 + .ir_attach = NULL,
2222 + .ir_detach = NULL,
2223 + .ir_init = sample_init,
2224 + .ir_deinit = sample_deinit,
2225 + .ir_node_init = sample_node_init,
2226 + .ir_node_deinit = sample_node_deinit,
2227 + .ir_rate = sample_rate,
2228 + .ir_rates = sample_rates,
2229 + .ir_tx_complete = sample_tx_complete,
2230 + .ir_tx_update = sample_tx_update,
2231 + .ir_setinterval = sample_setinterval,
2232 + .ir_stats = sample_stats,
2233 +};
2234 +IEEE80211_RATECTL_MODULE(sample, 1);
2235 +IEEE80211_RATECTL_ALG(sample, IEEE80211_RATECTL_SAMPLE, sample);
2236 +
2237 +static void
2238 +sample_init(struct ieee80211vap *vap, uint32_t capabilities)
2239 +{
2240 + struct ieee80211_sample *sample;
2241 +
2242 + KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__));
2243 +
2244 + sample = vap->iv_rs = malloc(sizeof(struct ieee80211_sample),
2245 + M_80211_RATECTL, M_NOWAIT|M_ZERO);
2246 + if (sample == NULL) {
2247 + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n");
2248 + return;
2249 + }
2250 +
2251 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
2252 + irs->irs_capabilities = capabilities;
2253 +
2254 + sample->sample_smoothing_rate = 75; /* ewma percentage ([0..99]) */
2255 + sample->sample_smoothing_minpackets = 100 / (100 - sample->sample_smoothing_rate);
2256 + sample->sample_rate = 10; /* %time to try diff tx rates */
2257 + sample->sample_max_successive_failures = 3; /* threshold for rate sampling*/
2258 + sample->sample_stale_failure_timeout = 10 * hz; /* 10 seconds */
2259 + sample->sample_min_switch = hz; /* 1 second */
2260 + sample_setinterval(vap, 500 /* ms */); /* actually do nothing */
2261 + sample_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid);
2262 +}
2263 +
2264 +static void
2265 +sample_deinit(struct ieee80211vap *vap)
2266 +{
2267 + free(vap->iv_rs, M_80211_RATECTL);
2268 +}
2269 +
2270 +static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = {
2271 + NULL, /* IEEE80211_MODE_AUTO */
2272 + series_11a, /* IEEE80211_MODE_11A */
2273 + series_11g, /* IEEE80211_MODE_11B */
2274 + series_11g, /* IEEE80211_MODE_11G */
2275 + NULL, /* IEEE80211_MODE_FH */
2276 + series_11a, /* IEEE80211_MODE_TURBO_A */
2277 + series_11g, /* IEEE80211_MODE_TURBO_G */
2278 + series_11a, /* IEEE80211_MODE_STURBO_A */
2279 + series_11na, /* IEEE80211_MODE_11NA */
2280 + series_11ng, /* IEEE80211_MODE_11NG */
2281 + series_half, /* IEEE80211_MODE_HALF */
2282 + series_quarter, /* IEEE80211_MODE_QUARTER */
2283 +};
2284 +
2285 +static void
2286 +sample_node_init(struct ieee80211_node *ni)
2287 +{
2288 +#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2289 +#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
2290 +#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
2291 +
2292 + struct ieee80211vap *vap = ni->ni_vap;
2293 + struct ieee80211_sample *sample = vap->iv_rs;
2294 + struct ieee80211_sample_node *san = NULL;
2295 +
2296 + const struct ieee80211_rate_table *rt = NULL;
2297 + enum ieee80211_phymode curmode = ieee80211_chan2mode(vap->iv_ic->ic_curchan);
2298 + int x, y, rix;
2299 +
2300 + if (ni->ni_rctls == NULL) {
2301 + ni->ni_rctls = san = malloc(sizeof(struct ieee80211_sample_node),
2302 + M_80211_RATECTL, M_NOWAIT|M_ZERO);
2303 + if (san == NULL) {
2304 + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
2305 + "structure\n");
2306 + return;
2307 + }
2308 + } else
2309 + san = ni->ni_rctls;
2310 +
2311 + san->san_sample = sample;
2312 +
2313 + rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2314 + KASSERT(rt != NULL, ("no rate table, mode %u", curmode));
2315 +
2316 + san->sched = mrr_schedules[curmode];
2317 + KASSERT(san->sched != NULL, ("no mrr schedule for mode %u", curmode));
2318 +
2319 + san->static_rix = -1;
2320 + sample_update_static_rix(ni);
2321 +
2322 + /*
2323 + * Construct a bitmask of usable rates. This has all
2324 + * negotiated rates minus those marked by the hal as
2325 + * to be ignored for doing rate control.
2326 + */
2327 + san->ratemask = 0;
2328 +
2329 + /* MCS rates */
2330 + if (ni->ni_flags & IEEE80211_NODE_HT) {
2331 + for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
2332 + rix = rt->rateCodeToIndex[MCS(x)];
2333 + if (rix == 0xff)
2334 + continue;
2335 + KASSERT(rix < SAMPLE_MAXRATES,
2336 + ("mcs %u has rix %d", MCS(x), rix));
2337 + san->ratemask |= (uint64_t) 1<<rix;
2338 + }
2339 + }
2340 +
2341 + /* Legacy rates */
2342 + for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
2343 + rix = rt->rateCodeToIndex[RATE(x)];
2344 + if (rix == 0xff)
2345 + continue;
2346 + KASSERT(rix < SAMPLE_MAXRATES,
2347 + ("rate %u has rix %d", RATE(x), rix));
2348 + san->ratemask |= (uint64_t) 1<<rix;
2349 + }
2350 +
2351 + for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
2352 + int size = bin_to_size(y);
2353 + uint64_t mask;
2354 +
2355 + san->packets_sent[y] = 0;
2356 + san->current_sample_rix[y] = -1;
2357 + san->last_sample_rix[y] = 0;
2358 + /* XXX start with first valid rate */
2359 + san->current_rix[y] = ffs(san->ratemask)-1;
2360 +
2361 + /*
2362 + * Initialize the statistics buckets; these are
2363 + * indexed by the rate code index.
2364 + */
2365 + for (rix = 0, mask = san->ratemask; mask != 0; rix++, mask >>= 1) {
2366 + if ((mask & 1) == 0) /* not a valid rate */
2367 + continue;
2368 + san->stats[y][rix].successive_failures = 0;
2369 + san->stats[y][rix].tries = 0;
2370 + san->stats[y][rix].total_packets = 0;
2371 + san->stats[y][rix].packets_acked = 0;
2372 + san->stats[y][rix].last_tx = 0;
2373 + san->stats[y][rix].ewma_pct = 0;
2374 +
2375 + san->stats[y][rix].perfect_tx_time =
2376 + calc_usecs_unicast_packet(vap, size, rix, 0, 0,
2377 + (ni->ni_chw == 40));
2378 + san->stats[y][rix].average_tx_time =
2379 + san->stats[y][rix].perfect_tx_time;
2380 + }
2381 + }
2382 +
2383 + /* set the visible bit-rate */
2384 + if (san->static_rix != -1)
2385 + ni->ni_txrate = DOT11RATE(san->static_rix);
2386 + else
2387 + ni->ni_txrate = RATE(0);
2388 +#undef RATE
2389 +#undef DOT11RATE
2390 +#undef MCS
2391 +}
2392 +
2393 +static void
2394 +sample_node_deinit(struct ieee80211_node *ni)
2395 +{
2396 + free(ni->ni_rctls, M_80211_RATECTL);
2397 +}
2398 +
2399 +static int
2400 +dot11rate(const struct ieee80211_rate_table *rt, int rix)
2401 +{
2402 + if (rix < 0)
2403 + return -1;
2404 + return rt->info[rix].phy == IEEE80211_T_HT ?
2405 + rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
2406 +}
2407 +
2408 +static const char *
2409 +dot11rate_label(const struct ieee80211_rate_table *rt, int rix)
2410 +{
2411 + if (rix < 0)
2412 + return "";
2413 + return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb ";
2414 +}
2415 +
2416 +/*
2417 + * Return the rix with the lowest average_tx_time,
2418 + * or -1 if all the average_tx_times are 0.
2419 + */
2420 +static __inline int
2421 +pick_best_rate(const struct ieee80211_node *ni, const struct ieee80211_rate_table *rt,
2422 + int size_bin, int require_acked_before)
2423 +{
2424 + struct ieee80211_sample_node *san = ni->ni_rctls;
2425 + int best_rate_rix, best_rate_tt, best_rate_pct;
2426 + uint64_t mask;
2427 + int rix, tt, pct;
2428 +
2429 + best_rate_rix = 0;
2430 + best_rate_tt = 0;
2431 + best_rate_pct = 0;
2432 +
2433 + for (mask = san->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
2434 + if ((mask & 1) == 0) /* not a supported rate */
2435 + continue;
2436 +
2437 + /* Don't pick a non-HT rate for a HT node */
2438 + if ((ni->ni_flags & IEEE80211_NODE_HT) &&
2439 + (rt->info[rix].phy != IEEE80211_T_HT)) {
2440 + continue;
2441 + }
2442 +
2443 + tt = san->stats[size_bin][rix].average_tx_time;
2444 + if (tt <= 0 ||
2445 + (require_acked_before &&
2446 + !san->stats[size_bin][rix].packets_acked))
2447 + continue;
2448 +
2449 + /* Calculate percentage if possible */
2450 + if (san->stats[size_bin][rix].total_packets > 0) {
2451 + pct = san->stats[size_bin][rix].ewma_pct;
2452 + } else {
2453 + /* XXX for now, assume 95% ok */
2454 + pct = 95;
2455 + }
2456 +
2457 + /* don't use a bit-rate that has been failing */
2458 + if (san->stats[size_bin][rix].successive_failures > 3)
2459 + continue;
2460 +
2461 + /*
2462 + * For HT, Don't use a bit rate that is much more
2463 + * lossy than the best.
2464 + *
2465 + * XXX this isn't optimal; it's just designed to
2466 + * eliminate rates that are going to be obviously
2467 + * worse.
2468 + */
2469 + if (ni->ni_flags & IEEE80211_NODE_HT) {
2470 + if (best_rate_pct > (pct + 50))
2471 + continue;
2472 + }
2473 +
2474 + /*
2475 + * For non-MCS rates, use the current average txtime for
2476 + * comparison.
2477 + */
2478 + if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
2479 + if (best_rate_tt == 0 || tt <= best_rate_tt) {
2480 + best_rate_tt = tt;
2481 + best_rate_rix = rix;
2482 + best_rate_pct = pct;
2483 + }
2484 + }
2485 +
2486 + /*
2487 + * Since 2 stream rates have slightly higher TX times,
2488 + * allow a little bit of leeway. This should later
2489 + * be abstracted out and properly handled.
2490 + */
2491 + if (ni->ni_flags & IEEE80211_NODE_HT) {
2492 + if (best_rate_tt == 0 || (tt * 8 <= best_rate_tt * 10)) {
2493 + best_rate_tt = tt;
2494 + best_rate_rix = rix;
2495 + best_rate_pct = pct;
2496 + }
2497 + }
2498 + }
2499 + return (best_rate_tt ? best_rate_rix : -1);
2500 +}
2501 +
2502 +/*
2503 + * Pick a good "random" bit-rate to sample other than the current one.
2504 + */
2505 +static __inline int
2506 +pick_sample_rate(const struct ieee80211_node *ni,
2507 + const struct ieee80211_rate_table *rt, int size_bin)
2508 +{
2509 +#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2510 +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2511 + struct ieee80211_sample_node *san = ni->ni_rctls;
2512 + struct ieee80211_sample *sample = san->san_sample;
2513 + int current_rix, rix;
2514 + unsigned current_tt;
2515 + uint64_t mask;
2516 +
2517 + current_rix = san->current_rix[size_bin];
2518 + if (current_rix < 0) {
2519 + /* no successes yet, send at the lowest bit-rate */
2520 + /* XXX should return MCS0 if HT */
2521 + return 0;
2522 + }
2523 +
2524 + current_tt = san->stats[size_bin][current_rix].average_tx_time;
2525 +
2526 + rix = san->last_sample_rix[size_bin]+1; /* next sample rate */
2527 + mask = san->ratemask &~ ((uint64_t) 1<<current_rix);/* don't sample current rate */
2528 + while (mask != 0) {
2529 + if ((mask & ((uint64_t) 1<<rix)) == 0) { /* not a supported rate */
2530 + nextrate:
2531 + if (++rix >= rt->rateCount)
2532 + rix = 0;
2533 + continue;
2534 + }
2535 +
2536 + /*
2537 + * The following code stops trying to sample
2538 + * non-MCS rates when speaking to an MCS node.
2539 + * However, at least for CCK rates in 2.4GHz mode,
2540 + * the non-MCS rates MAY actually provide better
2541 + * PER at the very far edge of reception.
2542 + *
2543 + * However! Until ath_rate_form_aggr() grows
2544 + * some logic to not form aggregates if the
2545 + * selected rate is non-MCS, this won't work.
2546 + *
2547 + * So don't disable this code until you've taught
2548 + * ath_rate_form_aggr() to drop out if any of
2549 + * the selected rates are non-MCS.
2550 + */
2551 +#if 1
2552 + /* if the node is HT and the rate isn't HT, don't bother sample */
2553 + if ((ni->ni_flags & IEEE80211_NODE_HT) &&
2554 + (rt->info[rix].phy != IEEE80211_T_HT)) {
2555 + mask &= ~((uint64_t) 1<<rix);
2556 + goto nextrate;
2557 + }
2558 +#endif
2559 +
2560 + /* this bit-rate is always worse than the current one */
2561 + if (san->stats[size_bin][rix].perfect_tx_time > current_tt) {
2562 + mask &= ~((uint64_t) 1<<rix);
2563 + goto nextrate;
2564 + }
2565 +
2566 + /* rarely sample bit-rates that fail a lot */
2567 + if (san->stats[size_bin][rix].successive_failures > sample->sample_max_successive_failures &&
2568 + ticks - san->stats[size_bin][rix].last_tx < sample->sample_stale_failure_timeout) {
2569 + mask &= ~((uint64_t) 1<<rix);
2570 + goto nextrate;
2571 + }
2572 +
2573 + /*
2574 + * For HT, only sample a few rates on either side of the
2575 + * current rix; there's quite likely a lot of them.
2576 + */
2577 + if (ni->ni_flags & IEEE80211_NODE_HT) {
2578 + if (rix < (current_rix - 3) ||
2579 + rix > (current_rix + 3)) {
2580 + mask &= ~((uint64_t) 1<<rix);
2581 + goto nextrate;
2582 + }
2583 + }
2584 +
2585 + /* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */
2586 + if (! (ni->ni_flags & IEEE80211_NODE_HT)) {
2587 + if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) {
2588 + mask &= ~((uint64_t) 1<<rix);
2589 + goto nextrate;
2590 + }
2591 + }
2592 +
2593 + san->last_sample_rix[size_bin] = rix;
2594 + return rix;
2595 + }
2596 + return current_rix;
2597 +#undef DOT11RATE
2598 +#undef MCS
2599 +}
2600 +
2601 +static int
2602 +sample_get_static_rix(const struct ieee80211_node *ni)
2603 +{
2604 +#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
2605 +#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
2606 + struct ieee80211vap *vap = ni->ni_vap;
2607 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2608 + const struct ieee80211_txparam *tp = ni->ni_txparms;
2609 + int srate;
2610 +
2611 + /* Check MCS rates */
2612 + for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) {
2613 + if (MCS(srate) == tp->ucastrate)
2614 + return rt->rateCodeToIndex[tp->ucastrate];
2615 + }
2616 +
2617 + /* Check legacy rates */
2618 + for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) {
2619 + if (RATE(srate) == tp->ucastrate)
2620 + return rt->rateCodeToIndex[tp->ucastrate];
2621 + }
2622 + return -1;
2623 +#undef RATE
2624 +#undef MCS
2625 +}
2626 +
2627 +static void
2628 +sample_update_static_rix(struct ieee80211_node *ni)
2629 +{
2630 + struct ieee80211_sample_node *san = ni->ni_rctls;
2631 + const struct ieee80211_txparam *tp = ni->ni_txparms;
2632 +
2633 + if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
2634 + /*
2635 + * A fixed rate is to be used; ucastrate is the IEEE code
2636 + * for this rate (sans basic bit). Check this against the
2637 + * negotiated rate set for the node. Note the fixed rate
2638 + * may not be available for various reasons so we only
2639 + * setup the static rate index if the lookup is successful.
2640 + */
2641 + san->static_rix = sample_get_static_rix(ni);
2642 + } else {
2643 + san->static_rix = -1;
2644 + }
2645 +}
2646 +
2647 +/*
2648 + * Pick a non-HT rate to begin using.
2649 + */
2650 +static int
2651 +sample_pick_seed_rate_legacy(const struct ieee80211_node *ni, int frameLen)
2652 +{
2653 +#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2654 + struct ieee80211vap *vap = ni->ni_vap;
2655 + struct ieee80211_sample_node *san = ni->ni_rctls;
2656 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2657 +
2658 + const int size_bin = size_to_bin(frameLen);
2659 + int rix = -1;
2660 +
2661 + /* no packet has been sent successfully yet */
2662 + for (rix = rt->rateCount-1; rix > 0; rix--) {
2663 + if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
2664 + continue;
2665 +
2666 + /* Skip HT rates */
2667 + if (rt->info[rix].phy == IEEE80211_T_HT)
2668 + continue;
2669 +
2670 + /*
2671 + * Pick the highest rate <= 36 Mbps
2672 + * that hasn't failed.
2673 + */
2674 + if (DOT11RATE(rix) <= 72 &&
2675 + san->stats[size_bin][rix].successive_failures == 0) {
2676 + break;
2677 + }
2678 + }
2679 + return rix;
2680 +#undef DOT11RATE
2681 +}
2682 +
2683 +/*
2684 + * Pick a HT rate to begin using.
2685 + *
2686 + * Don't use any non-HT rates; only consider HT rates.
2687 + */
2688 +static int
2689 +sample_pick_seed_rate_ht(const struct ieee80211_node *ni, int frameLen)
2690 +{
2691 +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2692 + struct ieee80211vap *vap = ni->ni_vap;
2693 + struct ieee80211_sample_node *san = ni->ni_rctls;
2694 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2695 +
2696 + const int size_bin = size_to_bin(frameLen);
2697 + int rix = -1, ht_rix = -1;
2698 +
2699 + /* no packet has been sent successfully yet */
2700 + for (rix = rt->rateCount-1; rix > 0; rix--) {
2701 + /* Skip rates we can't use */
2702 + if ((san->ratemask & ((uint64_t) 1<<rix)) == 0)
2703 + continue;
2704 +
2705 + /* Keep a copy of the last seen HT rate index */
2706 + if (rt->info[rix].phy == IEEE80211_T_HT)
2707 + ht_rix = rix;
2708 +
2709 + /* Skip non-HT rates */
2710 + if (rt->info[rix].phy != IEEE80211_T_HT)
2711 + continue;
2712 +
2713 + /*
2714 + * Pick a medium-speed rate regardless of stream count
2715 + * which has not seen any failures. Higher rates may fail;
2716 + * we'll try them later.
2717 + */
2718 + if (((MCS(rix) & 0x7) <= 4) &&
2719 + san->stats[size_bin][rix].successive_failures == 0) {
2720 + break;
2721 + }
2722 + }
2723 +
2724 + /*
2725 + * If all the MCS rates have successive failures, rix should be
2726 + * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.)
2727 + */
2728 + return MAX(rix, ht_rix);
2729 +#undef MCS
2730 +}
2731 +
2732 +static int
2733 +sample_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
2734 +{
2735 +#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
2736 +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
2737 +#define RATE(ix) (DOT11RATE(ix) / 2)
2738 + struct ieee80211vap *vap = ni->ni_vap;
2739 + struct ieee80211_sample_node *san = ni->ni_rctls;
2740 + struct ieee80211_sample *sample = san->san_sample;
2741 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
2742 +
2743 + int rix, mrr, best_rix, change_rates;
2744 + unsigned average_tx_time;
2745 +
2746 + size_t frameLen = (size_t)iarg;
2747 + const int size_bin = size_to_bin(frameLen);
2748 +
2749 + sample_update_static_rix(ni);
2750 +
2751 + if (san->static_rix != -1) {
2752 + rix = san->static_rix;
2753 + goto done;
2754 + }
2755 +
2756 + if (IEEE80211_RATECTL_HASCAP_MRR(vap))
2757 + mrr = 1;
2758 + if (! IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
2759 + mrr = 0;
2760 +
2761 + best_rix = pick_best_rate(ni, rt, size_bin, !mrr);
2762 + if (best_rix >= 0) {
2763 + average_tx_time = san->stats[size_bin][best_rix].average_tx_time;
2764 + } else {
2765 + average_tx_time = 0;
2766 + }
2767 +
2768 + /*
2769 + * Limit the time measuring the performance of other tx
2770 + * rates to sample_rate% of the total transmission time.
2771 + */
2772 + if (san->sample_tt[size_bin] < average_tx_time * (san->packets_since_sample[size_bin] *
2773 + sample->sample_rate/100)) {
2774 + rix = pick_sample_rate(ni, rt, size_bin);
2775 + IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL,
2776 + ni, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s",
2777 + average_tx_time,
2778 + san->sample_tt[size_bin],
2779 + bin_to_size(size_bin),
2780 + dot11rate(rt, rix),
2781 + dot11rate_label(rt, rix),
2782 + dot11rate(rt, san->current_rix[size_bin]),
2783 + dot11rate_label(rt, san->current_rix[size_bin]));
2784 + if (rix != san->current_rix[size_bin]) {
2785 + san->current_sample_rix[size_bin] = rix;
2786 + } else {
2787 + san->current_sample_rix[size_bin] = -1;
2788 + }
2789 + san->packets_since_sample[size_bin] = 0;
2790 + } else {
2791 + change_rates = 0;
2792 + if (!san->packets_sent[size_bin] || best_rix == -1) {
2793 + /* no packet has been sent successfully yet */
2794 + change_rates = 1;
2795 + if (ni->ni_flags & IEEE80211_NODE_HT)
2796 + best_rix = sample_pick_seed_rate_ht(ni, frameLen);
2797 + else
2798 + best_rix = sample_pick_seed_rate_legacy(ni, frameLen);
2799 + } else if (san->packets_sent[size_bin] < 20) {
2800 + /* let the bit-rate switch quickly during the first few packets */
2801 + IEEE80211_NOTE(vap,
2802 + IEEE80211_MSG_RATECTL, ni,
2803 + "%s: switching quickly..", __func__);
2804 + change_rates = 1;
2805 + } else if (ticks - sample->sample_min_switch > san->ticks_since_switch[size_bin]) {
2806 + /* min_switch seconds have gone by */
2807 + IEEE80211_NOTE(vap,
2808 + IEEE80211_MSG_RATECTL, ni,
2809 + "%s: min_switch %d > ticks_since_switch %d..",
2810 + __func__, ticks - sample->sample_min_switch, san->ticks_since_switch[size_bin]);
2811 + change_rates = 1;
2812 + } else if ((! (ni->ni_flags & IEEE80211_NODE_HT)) &&
2813 + (2*average_tx_time < san->stats[size_bin][san->current_rix[size_bin]].average_tx_time)) {
2814 + /* the current bit-rate is twice as slow as the best one */
2815 + IEEE80211_NOTE(vap,
2816 + IEEE80211_MSG_RATECTL, ni,
2817 + "%s: 2x att (= %d) < cur_rix att %d",
2818 + __func__,
2819 + 2 * average_tx_time, san->stats[size_bin][san->current_rix[size_bin]].average_tx_time);
2820 + change_rates = 1;
2821 + } else if ((ni->ni_flags & IEEE80211_NODE_HT)) {
2822 + int cur_rix = san->current_rix[size_bin];
2823 + int cur_att = san->stats[size_bin][cur_rix].average_tx_time;
2824 + /*
2825 + * If the node is HT, upgrade it if the MCS rate is
2826 + * higher and the average tx time is within 20% of
2827 + * the current rate. It can fail a little.
2828 + *
2829 + * This is likely not optimal!
2830 + */
2831 +#if 0
2832 + printf("cur rix/att %x/%d, best rix/att %x/%d\n",
2833 + MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time);
2834 +#endif
2835 + if ((MCS(best_rix) > MCS(cur_rix)) &&
2836 + (average_tx_time * 8) <= (cur_att * 10)) {
2837 + IEEE80211_NOTE(vap,
2838 + IEEE80211_MSG_RATECTL, ni,
2839 + "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d",
2840 + __func__,
2841 + MCS(best_rix), MCS(cur_rix), average_tx_time, cur_att);
2842 + change_rates = 1;
2843 + }
2844 + }
2845 +
2846 + san->packets_since_sample[size_bin]++;
2847 +
2848 + if (change_rates) {
2849 + if (best_rix != san->current_rix[size_bin]) {
2850 + IEEE80211_NOTE(vap,
2851 + IEEE80211_MSG_RATECTL,
2852 + ni,
2853 +"%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d",
2854 + __func__,
2855 + bin_to_size(size_bin),
2856 + RATE(san->current_rix[size_bin]),
2857 + san->stats[size_bin][san->current_rix[size_bin]].average_tx_time,
2858 + san->stats[size_bin][san->current_rix[size_bin]].perfect_tx_time,
2859 + RATE(best_rix),
2860 + san->stats[size_bin][best_rix].average_tx_time,
2861 + san->stats[size_bin][best_rix].perfect_tx_time,
2862 + san->packets_since_switch[size_bin],
2863 + mrr);
2864 + }
2865 + san->packets_since_switch[size_bin] = 0;
2866 + san->current_rix[size_bin] = best_rix;
2867 + san->ticks_since_switch[size_bin] = ticks;
2868 + /*
2869 + * Set the visible txrate for this node.
2870 + */
2871 + ni->ni_txrate = dot11rate(rt, best_rix);
2872 + }
2873 + rix = san->current_rix[size_bin];
2874 + san->packets_since_switch[size_bin]++;
2875 + }
2876 + // *try0 = mrr ? san->sched[rix].t0 : ATH_TXMAXTRY;
2877 +done:
2878 +
2879 + /*
2880 + * This bug totally sucks and should be fixed.
2881 + *
2882 + * For now though, let's not panic, so we can start to figure
2883 + * out how to better reproduce it.
2884 + */
2885 + if (rix < 0 || rix >= rt->rateCount) {
2886 + printf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
2887 + __func__,
2888 + rix,
2889 + rt->rateCount);
2890 + rix = 0; /* XXX just default for now */
2891 + }
2892 + KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix));
2893 +
2894 + // *rix0 = rix;
2895 + // *txrate = rt->info[rix].rateCode
2896 + // | (shortPreamble ? rt->info[rix].shortPreamble : 0);
2897 + san->packets_sent[size_bin]++;
2898 +
2899 + return rix;
2900 +#undef DOT11RATE
2901 +#undef MCS
2902 +#undef RATE
2903 +}
2904 +
2905 +static void
2906 +sample_rates(struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
2907 +{
2908 + struct ieee80211_sample_node *san = ni->ni_rctls;
2909 + uint8_t rix0 = sample_rate(ni, NULL, 0);
2910 + const struct txschedule *sched = &san->sched[rix0];
2911 + struct ieee80211_rc_series *rc = rc_info->iri_rc;
2912 +
2913 + KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n",
2914 + rix0, sched->r0));
2915 + /* XXX */
2916 + rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
2917 +
2918 + rc[0].rix = sched->r0;
2919 + rc[1].rix = sched->r1;
2920 + rc[2].rix = sched->r2;
2921 + rc[3].rix = sched->r3;
2922 +
2923 + rc[0].tries = sched->t0;
2924 + rc[1].tries = sched->t1;
2925 + rc[2].tries = sched->t2;
2926 + rc[3].tries = sched->t3;
2927 +}
2928 +
2929 +static void
2930 +update_stats(const struct ieee80211vap *vap,
2931 + const struct ieee80211_node *ni,
2932 + int frame_size,
2933 + int rix0, int tries0,
2934 + int rix1, int tries1,
2935 + int rix2, int tries2,
2936 + int rix3, int tries3,
2937 + int short_tries, int tries,
2938 + int nframes, int nbad)
2939 +{
2940 + struct ieee80211_sample_node *san = ni->ni_rctls;
2941 + struct ieee80211_sample *sample = san->san_sample;
2942 +
2943 + const int size_bin = size_to_bin(frame_size);
2944 + const int size = bin_to_size(size_bin);
2945 +
2946 + int is_ht40 = ieee80211_ratectl_hascap_cw40(ni);
2947 + int tt, tries_so_far;
2948 + int pct;
2949 +
2950 + if (!IS_RATE_DEFINED(san, rix0))
2951 + return;
2952 + tt = calc_usecs_unicast_packet(vap, size, rix0, short_tries,
2953 + MIN(tries0, tries) - 1, is_ht40);
2954 + tries_so_far = tries0;
2955 +
2956 + if (tries1 && tries_so_far < tries) {
2957 + if (!IS_RATE_DEFINED(san, rix1))
2958 + return;
2959 + tt += calc_usecs_unicast_packet(vap, size, rix1, short_tries,
2960 + MIN(tries1 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2961 + tries_so_far += tries1;
2962 + }
2963 +
2964 + if (tries2 && tries_so_far < tries) {
2965 + if (!IS_RATE_DEFINED(san, rix2))
2966 + return;
2967 + tt += calc_usecs_unicast_packet(vap, size, rix2, short_tries,
2968 + MIN(tries2 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2969 + tries_so_far += tries2;
2970 + }
2971 +
2972 + if (tries3 && tries_so_far < tries) {
2973 + if (!IS_RATE_DEFINED(san, rix3))
2974 + return;
2975 + tt += calc_usecs_unicast_packet(vap, size, rix3, short_tries,
2976 + MIN(tries3 + tries_so_far, tries) - tries_so_far - 1, is_ht40);
2977 + }
2978 +
2979 + if (san->stats[size_bin][rix0].total_packets < sample->sample_smoothing_minpackets) {
2980 + /* just average the first few packets */
2981 + int avg_tx = san->stats[size_bin][rix0].average_tx_time;
2982 + int packets = san->stats[size_bin][rix0].total_packets;
2983 + san->stats[size_bin][rix0].average_tx_time = (tt+(avg_tx*packets))/(packets+nframes);
2984 + } else {
2985 + /* use a ewma */
2986 + san->stats[size_bin][rix0].average_tx_time =
2987 + ((san->stats[size_bin][rix0].average_tx_time * sample->sample_smoothing_rate) +
2988 + (tt * (100 - sample->sample_smoothing_rate))) / 100;
2989 + }
2990 +
2991 + /*
2992 + * XXX Don't mark the higher bit rates as also having failed; as this
2993 + * unfortunately stops those rates from being tasted when trying to
2994 + * TX. This happens with 11n aggregation.
2995 + */
2996 + if (nframes == nbad) {
2997 + san->stats[size_bin][rix0].successive_failures += nbad;
2998 +
2999 + } else {
3000 + san->stats[size_bin][rix0].packets_acked += (nframes - nbad);
3001 + san->stats[size_bin][rix0].successive_failures = 0;
3002 + }
3003 + san->stats[size_bin][rix0].tries += tries;
3004 + san->stats[size_bin][rix0].last_tx = ticks;
3005 + san->stats[size_bin][rix0].total_packets += nframes;
3006 +
3007 + /* update EWMA for this rix */
3008 +
3009 + /* Calculate percentage based on current rate */
3010 + if (nframes == 0)
3011 + nframes = nbad = 1;
3012 + pct = ((nframes - nbad) * 1000) / nframes;
3013 +
3014 + if (san->stats[size_bin][rix0].total_packets <
3015 + sample->sample_smoothing_minpackets) {
3016 + /* just average the first few packets */
3017 + int a_pct = (san->stats[size_bin][rix0].packets_acked * 1000) /
3018 + (san->stats[size_bin][rix0].total_packets);
3019 + san->stats[size_bin][rix0].ewma_pct = a_pct;
3020 + } else {
3021 + /* use a ewma */
3022 + san->stats[size_bin][rix0].ewma_pct =
3023 + ((san->stats[size_bin][rix0].ewma_pct * sample->sample_smoothing_rate) +
3024 + (pct * (100 - sample->sample_smoothing_rate))) / 100;
3025 + }
3026 +
3027 + if (rix0 == san->current_sample_rix[size_bin]) {
3028 + san->sample_tt[size_bin] = tt;
3029 + san->current_sample_rix[size_bin] = -1;
3030 + }
3031 +}
3032 +
3033 +static void
3034 +sample_tx_complete(const struct ieee80211vap *vap,
3035 + const struct ieee80211_node *ni, struct ieee80211_rc_info *rc_info)
3036 +{
3037 + struct ieee80211_sample_node *san = ni->ni_rctls;
3038 + const struct ieee80211_rate_table *rt = NULL;
3039 + struct ieee80211_rc_series *rc = NULL;
3040 + int final_rix, short_tries, long_tries;
3041 + int nframes, nbad;
3042 + int frame_size, mrr;
3043 +
3044 + rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3045 + rc = rc_info->iri_rc;
3046 + /* update per vap statistics */
3047 + ieee80211_ratectl_update_stat(vap, rc_info);
3048 +
3049 + final_rix = rt->rateCodeToIndex[rc_info->iri_txrate];
3050 + short_tries = rc_info->iri_shortretry;
3051 + long_tries = rc_info->iri_longretry + 1;
3052 +
3053 + nframes = rc_info->iri_txcnt;
3054 + nbad = rc_info->iri_failcnt;
3055 +
3056 + frame_size = rc_info->iri_framelen;
3057 + mrr = 0;
3058 +
3059 + if (nframes == 0) {
3060 + /* XXX need some msg out */
3061 + return;
3062 + }
3063 +
3064 + if (frame_size == 0) /* NB: should not happen */
3065 + frame_size = 1500;
3066 +
3067 + if (san->ratemask == 0) {
3068 + return;
3069 + }
3070 +
3071 + if (IEEE80211_RATECTL_HASCAP_MRR(vap))
3072 + mrr = 1;
3073 + /* XXX check HT protmode too */
3074 + if (mrr && !IEEE80211_RATECTL_HASCAP_MRRPROT(vap))
3075 + mrr = 0;
3076 +
3077 + if (!mrr || rc_info->iri_finaltsi == 0) {
3078 + if (!IS_RATE_DEFINED(san, final_rix)) {
3079 + return;
3080 + }
3081 + /*
3082 + * Only one rate was used; optimize work.
3083 + */
3084 + update_stats(vap, ni, frame_size,
3085 + final_rix, long_tries,
3086 + 0, 0,
3087 + 0, 0,
3088 + 0, 0,
3089 + short_tries, long_tries,
3090 + nframes, nbad);
3091 +
3092 + } else {
3093 + int finalTSIdx = rc_info->iri_finaltsi;
3094 +
3095 + /*
3096 + * NB: series > 0 are not penalized for failure
3097 + * based on the try counts under the assumption
3098 + * that losses are often bursty and since we
3099 + * sample higher rates 1 try at a time doing so
3100 + * may unfairly penalize them.
3101 + */
3102 + if (rc[0].tries) {
3103 + update_stats(vap, ni, frame_size,
3104 + rc[0].rix, rc[0].tries,
3105 + rc[1].rix, rc[1].tries,
3106 + rc[2].rix, rc[2].tries,
3107 + rc[3].rix, rc[3].tries,
3108 + short_tries, long_tries,
3109 + nframes, nbad);
3110 + long_tries -= rc[0].tries;
3111 + }
3112 +
3113 + if (rc[1].tries && finalTSIdx > 0) {
3114 + update_stats(vap, ni, frame_size,
3115 + rc[1].rix, rc[1].tries,
3116 + rc[2].rix, rc[2].tries,
3117 + rc[3].rix, rc[3].tries,
3118 + 0, 0,
3119 + short_tries, long_tries,
3120 + nframes, nbad);
3121 + long_tries -= rc[1].tries;
3122 + }
3123 +
3124 + if (rc[2].tries && finalTSIdx > 1) {
3125 + update_stats(vap, ni, frame_size,
3126 + rc[2].rix, rc[2].tries,
3127 + rc[3].rix, rc[3].tries,
3128 + 0, 0,
3129 + 0, 0,
3130 + short_tries, long_tries,
3131 + nframes, nbad);
3132 + long_tries -= rc[2].tries;
3133 + }
3134 +
3135 + if (rc[3].tries && finalTSIdx > 2) {
3136 + update_stats(vap, ni, frame_size,
3137 + rc[3].rix, rc[3].tries,
3138 + 0, 0,
3139 + 0, 0,
3140 + 0, 0,
3141 + short_tries, long_tries,
3142 + nframes, nbad);
3143 + }
3144 + }
3145 +}
3146 +
3147 +static void
3148 +sample_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni,
3149 + void *arg1, void *arg2, void *arg3)
3150 +{
3151 + /* nothing here. */
3152 +}
3153 +
3154 +static void
3155 +sample_setinterval(const struct ieee80211vap *vap, int msecs)
3156 +{
3157 + /* ieee80211_sample doesn't have the sample_interval field by now */
3158 +}
3159 +
3160 +static void
3161 +sample_stats_node(void *arg, struct ieee80211_node *ni)
3162 +{
3163 + struct ieee80211vap *vap = ni->ni_vap;
3164 + struct ieee80211_sample_node *san = ni->ni_rctls;
3165 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3166 + uint64_t mask;
3167 + int rix, y;
3168 +
3169 + printf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
3170 + ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni),
3171 + dot11rate(rt, san->static_rix),
3172 + dot11rate_label(rt, san->static_rix),
3173 + (uintmax_t)san->ratemask);
3174 + for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
3175 + printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
3176 + bin_to_size(y), san->current_rix[y],
3177 + dot11rate(rt, san->current_rix[y]),
3178 + dot11rate_label(rt, san->current_rix[y]),
3179 + san->packets_since_switch[y], san->ticks_since_switch[y]);
3180 + printf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
3181 + bin_to_size(y),
3182 + dot11rate(rt, san->last_sample_rix[y]),
3183 + dot11rate_label(rt, san->last_sample_rix[y]),
3184 + dot11rate(rt, san->current_sample_rix[y]),
3185 + dot11rate_label(rt, san->current_sample_rix[y]),
3186 + san->packets_sent[y]);
3187 + printf("[%4u] packets since sample %d sample tt %u\n",
3188 + bin_to_size(y), san->packets_since_sample[y],
3189 + san->sample_tt[y]);
3190 + }
3191 + for (mask = san->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
3192 + if ((mask & 1) == 0)
3193 + continue;
3194 + for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
3195 + if (san->stats[y][rix].total_packets == 0)
3196 + continue;
3197 + printf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
3198 + dot11rate(rt, rix), dot11rate_label(rt, rix),
3199 + bin_to_size(y),
3200 + (uintmax_t) san->stats[y][rix].total_packets,
3201 + (uintmax_t) san->stats[y][rix].packets_acked,
3202 + (int) ((san->stats[y][rix].packets_acked * 100ULL) /
3203 + san->stats[y][rix].total_packets),
3204 + san->stats[y][rix].ewma_pct / 10,
3205 + san->stats[y][rix].ewma_pct % 10,
3206 + (uintmax_t) san->stats[y][rix].tries,
3207 + san->stats[y][rix].successive_failures,
3208 + san->stats[y][rix].average_tx_time,
3209 + ticks - san->stats[y][rix].last_tx);
3210 + }
3211 + }
3212 +}
3213 +static void
3214 +sample_stats(const struct ieee80211vap *vap)
3215 +{
3216 + struct ieee80211com *ic = vap->iv_ifp->if_l2com;
3217 + struct ieee80211_rc_stat * irs = IEEE80211_RATECTL_STAT(vap);
3218 + printf("tx count: %d (ok count: %d, fail count: %d)\n"
3219 + "retry count: %d (short retry: %d, long retry: %d)\n",
3220 + irs->irs_txcnt, irs->irs_txcnt - irs->irs_failcnt, irs->irs_failcnt,
3221 + irs->irs_retrycnt, irs->irs_shortretry, irs->irs_longretry);
3222 + ieee80211_iterate_nodes(&ic->ic_sta, sample_stats_node, NULL);
3223 +}
3224 +
3225 +static int
3226 +sample_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS)
3227 +{
3228 + struct ieee80211vap *vap = arg1;
3229 + struct ieee80211_sample *sample = vap->iv_rs;
3230 + int rate, error;
3231 +
3232 + rate = sample->sample_smoothing_rate;
3233 + error = sysctl_handle_int(oidp, &rate, 0, req);
3234 + if (error || !req->newptr)
3235 + return error;
3236 + if (!(0 <= rate && rate < 100))
3237 + return EINVAL;
3238 + sample->sample_smoothing_rate = rate;
3239 + sample->sample_smoothing_minpackets = 100 / (100 - rate);
3240 + return 0;
3241 +}
3242 +
3243 +static int
3244 +sample_sysctl_sample_rate(SYSCTL_HANDLER_ARGS)
3245 +{
3246 + struct ieee80211vap *vap = arg1;
3247 + struct ieee80211_sample *sample = vap->iv_rs;
3248 + int rate, error;
3249 +
3250 + rate = sample->sample_rate;
3251 + error = sysctl_handle_int(oidp, &rate, 0, req);
3252 + if (error || !req->newptr)
3253 + return error;
3254 + if (!(2 <= rate && rate <= 100))
3255 + return EINVAL;
3256 + sample->sample_rate = rate;
3257 + return 0;
3258 +}
3259 +
3260 +static void
3261 +sample_sysctlattach(struct ieee80211vap *vap,
3262 + struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
3263 +{
3264 + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
3265 + "sample_smoothing_rate", CTLTYPE_INT | CTLFLAG_RW, vap, 0,
3266 + sample_sysctl_smoothing_rate, "I",
3267 + "sample: smoothing rate for avg tx time (%%)");
3268 + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
3269 + "sample_rate", CTLTYPE_INT | CTLFLAG_RW, vap, 0,
3270 + sample_sysctl_sample_rate, "I",
3271 + "sample: percent air time devoted to sampling new rates (%%)");
3272 +}
3273 Index: sys/net80211/ieee80211_sample.h
3274 ===================================================================
3275 --- sys/net80211/ieee80211_sample.h (revision 0)
3276 +++ sys/net80211/ieee80211_sample.h (revision 257398)
3277 @@ -0,0 +1,288 @@
3278 +/* $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.h 240382 2012-08-15 07:10:10Z adrian $*/
3279 +
3280 +/*-
3281 + * Copyright (c) 2005 John Bicket
3282 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
3283 + * All rights reserved.
3284 + *
3285 + * Redistribution and use in source and binary forms, with or without
3286 + * modification, are permitted provided that the following conditions
3287 + * are met:
3288 + * 1. Redistributions of source code must retain the above copyright
3289 + * notice, this list of conditions and the following disclaimer,
3290 + * without modification.
3291 + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
3292 + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
3293 + * redistribution must be conditioned upon including a substantially
3294 + * similar Disclaimer requirement for further binary redistribution.
3295 + * 3. Neither the names of the above-listed copyright holders nor the names
3296 + * of any contributors may be used to endorse or promote products derived
3297 + * from this software without specific prior written permission.
3298 + *
3299 + * Alternatively, this software may be distributed under the terms of the
3300 + * GNU General Public License ("GPL") version 2 as published by the Free
3301 + * Software Foundation.
3302 + *
3303 + * NO WARRANTY
3304 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3305 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3306 + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
3307 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
3308 + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
3309 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3310 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3311 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3312 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3313 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3314 + * THE POSSIBILITY OF SUCH DAMAGES.
3315 + */
3316 +
3317 +#ifndef _NET80211_IEEE80211_RATECTL_SAMPLE_H_
3318 +#define _NET80211_IEEE80211_RATECTL_SAMPLE_H_
3319 +
3320 +#include <net80211/ieee80211_ratectl.h>
3321 +
3322 +/*
3323 + * for now, we track performance for three different packet
3324 + * size buckets
3325 + */
3326 +#define NUM_PACKET_SIZE_BINS 2
3327 +#define SAMPLE_MAXRATES 64 /* NB: corresponds to hal info[32] */
3328 +
3329 +/*
3330 + * Rate control settings.
3331 + */
3332 +struct ieee80211_sample {
3333 + struct ieee80211_rc_stat sample_stat;
3334 + int sample_smoothing_rate; /* ewma percentage [0..99] */
3335 + int sample_smoothing_minpackets;
3336 + int sample_rate; /* %time to try different tx rates */
3337 + int sample_max_successive_failures;
3338 + int sample_stale_failure_timeout; /* how long to honor max_successive_failures */
3339 + int sample_min_switch; /* min time between rate changes */
3340 + int sample_min_good_pct; /* min good percentage for a rate to be considered */
3341 +};
3342 +
3343 +struct rate_stats {
3344 + unsigned average_tx_time;
3345 + int successive_failures;
3346 + uint64_t tries;
3347 + uint64_t total_packets; /* pkts total since assoc */
3348 + uint64_t packets_acked; /* pkts acked since assoc */
3349 + int ewma_pct; /* EWMA percentage */
3350 + unsigned perfect_tx_time; /* transmit time for 0 retries */
3351 + int last_tx;
3352 +};
3353 +
3354 +struct txschedule {
3355 + uint8_t t0, r0; /* series 0: tries, rate code */
3356 + uint8_t t1, r1; /* series 1: tries, rate code */
3357 + uint8_t t2, r2; /* series 2: tries, rate code */
3358 + uint8_t t3, r3; /* series 3: tries, rate code */
3359 +};
3360 +
3361 +/*
3362 + * Rate control state for a given node.
3363 + */
3364 +/* XXX change naming conversion? */
3365 +struct ieee80211_sample_node {
3366 + struct ieee80211_sample *san_sample;/* backpointer */
3367 + int static_rix; /* rate index of fixed tx rate */
3368 + uint64_t ratemask; /* bit mask of valid rate indices */
3369 + const struct txschedule *sched; /* tx schedule table */
3370 +
3371 + struct rate_stats stats[NUM_PACKET_SIZE_BINS][SAMPLE_MAXRATES];
3372 + int last_sample_rix[NUM_PACKET_SIZE_BINS];
3373 +
3374 + int current_sample_rix[NUM_PACKET_SIZE_BINS];
3375 + int packets_sent[NUM_PACKET_SIZE_BINS];
3376 +
3377 + int current_rix[NUM_PACKET_SIZE_BINS];
3378 + int packets_since_switch[NUM_PACKET_SIZE_BINS];
3379 + unsigned ticks_since_switch[NUM_PACKET_SIZE_BINS];
3380 +
3381 + int packets_since_sample[NUM_PACKET_SIZE_BINS];
3382 + unsigned sample_tt[NUM_PACKET_SIZE_BINS];
3383 +};
3384 +
3385 +#define IS_RATE_DEFINED(san, rix) (((san)->ratemask & (1<<(rix))) != 0)
3386 +
3387 +#ifndef MIN
3388 +#define MIN(a,b) ((a) < (b) ? (a) : (b))
3389 +#endif
3390 +#ifndef MAX
3391 +#define MAX(a,b) ((a) > (b) ? (a) : (b))
3392 +#endif
3393 +
3394 +static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600 };
3395 +
3396 +static inline int
3397 +bin_to_size(int index)
3398 +{
3399 + return packet_size_bins[index];
3400 +}
3401 +
3402 +static inline int
3403 +size_to_bin(int size)
3404 +{
3405 +#if NUM_PACKET_SIZE_BINS > 1
3406 + if (size <= packet_size_bins[0])
3407 + return 0;
3408 +#endif
3409 +#if NUM_PACKET_SIZE_BINS > 2
3410 + if (size <= packet_size_bins[1])
3411 + return 1;
3412 +#endif
3413 +#if NUM_PACKET_SIZE_BINS > 3
3414 + if (size <= packet_size_bins[2])
3415 + return 2;
3416 +#endif
3417 +#if NUM_PACKET_SIZE_BINS > 4
3418 +#error "add support for more packet sizes"
3419 +#endif
3420 + return NUM_PACKET_SIZE_BINS-1;
3421 +}
3422 +
3423 +static uint32_t sample_pkt_tx_time(const struct ieee80211_rate_table *rt,
3424 + uint32_t frameLen, uint16_t rateix, int isht40, int isShortPreamble)
3425 +{
3426 + uint8_t rate = rt->info[rateix].dot11Rate;
3427 + uint32_t tx_time = 0;
3428 +
3429 + if (rt->info[rateix].phy == IEEE80211_T_HT) {
3430 + int numStreams;
3431 + /* 11n frame - extract out the number of spatial streams */
3432 + rate |= IEEE80211_RATE_MCS;
3433 + numStreams = HT_RC_2_STREAMS(rate);
3434 + KASSERT(numStreams > 0 && numStreams <= 4,
3435 + ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
3436 + rateix));
3437 + tx_time = ieee80211_compute_duration_ht(frameLen, rate, numStreams, isht40, isShortPreamble);
3438 + } else {
3439 + /* Legacy rate? Return the old way */
3440 + rate &= IEEE80211_RATE_VAL;
3441 + tx_time = ieee80211_compute_duration(rt, frameLen, rate, isShortPreamble);
3442 + }
3443 +
3444 + return tx_time;
3445 +}
3446 +
3447 +#define WIFI_CW_MIN 31
3448 +#define WIFI_CW_MAX 1023
3449 +
3450 +/*
3451 + * Calculate the transmit duration of a frame.
3452 + */
3453 +static unsigned calc_usecs_unicast_packet(const struct ieee80211vap *vap,
3454 + int length,
3455 + int rix, int short_retries,
3456 + int long_retries, int is_ht40)
3457 +{
3458 + const struct ieee80211_rate_table *rt = ieee80211_get_ratetable(vap->iv_ic->ic_curchan);
3459 + struct ieee80211com *ic = vap->iv_ic;
3460 + int curmode = ieee80211_chan2mode(vap->iv_ic->ic_curchan);
3461 +
3462 + unsigned t_slot, t_difs, t_sifs;
3463 + int rts, cts;
3464 + int tt, x, cw, cix;
3465 +
3466 + tt = 0;
3467 + x = 0;
3468 + cw = WIFI_CW_MIN;
3469 +
3470 + KASSERT(rt != NULL, ("no rate table, mode %u", curmode));
3471 +
3472 + if (rix >= rt->rateCount) {
3473 + printf("bogus rix %d, max %u, mode %u\n",
3474 + rix, rt->rateCount, curmode);
3475 + return 0;
3476 + }
3477 + cix = rt->info[rix].ctlRateIndex;
3478 + /*
3479 + * XXX getting mac/phy level timings should be fixed for turbo
3480 + * rates, and there is probably a way to get this from the
3481 + * hal...
3482 + */
3483 + switch (rt->info[rix].phy) {
3484 + case IEEE80211_T_OFDM:
3485 + t_slot = 9;
3486 + t_sifs = 16;
3487 + t_difs = 28;
3488 + /* fall through */
3489 + case IEEE80211_T_TURBO:
3490 + t_slot = 9;
3491 + t_sifs = 8;
3492 + t_difs = 28;
3493 + break;
3494 + case IEEE80211_T_HT:
3495 + t_slot = 9;
3496 + t_sifs = 8;
3497 + t_difs = 28;
3498 + break;
3499 + case IEEE80211_T_DS:
3500 + /* fall through to default */
3501 + default:
3502 + /* pg 205 ieee.802.11.pdf */
3503 + t_slot = 20;
3504 + t_difs = 50;
3505 + t_sifs = 10;
3506 + }
3507 +
3508 + rts = cts = 0;
3509 +
3510 + if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
3511 + rt->info[rix].phy == IEEE80211_T_OFDM) {
3512 + if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
3513 + rts = 1;
3514 + else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
3515 + cts = 1;
3516 +
3517 + int protrix;
3518 + if (curmode == IEEE80211_MODE_11G)
3519 + protrix = rt->rateCodeToIndex[2*2];
3520 + else
3521 + protrix = rt->rateCodeToIndex[2*1];
3522 + if (0xff == protrix)
3523 + protrix = 0;
3524 +
3525 + cix = rt->info[protrix].ctlRateIndex;
3526 + }
3527 +
3528 + if (0 /*length > ic->ic_rtsthreshold */) {
3529 + rts = 1;
3530 + }
3531 +
3532 + if (rts || cts) {
3533 + int ctsduration = 0;
3534 +
3535 + /* NB: this is intentionally not a runtime check */
3536 + KASSERT(cix < rt->rateCount,
3537 + ("bogus cix %d, max %u, mode %u\n", cix, rt->rateCount,
3538 + curmode));
3539 +
3540 + if (rts) /* SIFS + CTS */
3541 + ctsduration += rt->info[cix].spAckDuration;
3542 +
3543 + /* XXX assumes short preamble */
3544 + ctsduration += sample_pkt_tx_time(rt, length, rix, is_ht40, 0);
3545 +
3546 + if (cts) /* SIFS + ACK */
3547 + ctsduration += rt->info[cix].spAckDuration;
3548 +
3549 + tt += (short_retries + 1) * ctsduration;
3550 + }
3551 + tt += t_difs;
3552 +
3553 + /* XXX assumes short preamble */
3554 + tt += (long_retries+1)*sample_pkt_tx_time(rt, length, rix, is_ht40, 0);
3555 +
3556 + tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration);
3557 +
3558 + for (x = 0; x <= short_retries + long_retries; x++) {
3559 + cw = MIN(WIFI_CW_MAX, (cw + 1) * 2);
3560 + tt += (t_slot * cw/2);
3561 + }
3562 + return tt;
3563 +}
3564 +
3565 +#endif /* _NET80211_IEEE80211_RATECTL_SAMPLE_H_ */
3566 Index: sys/net80211/ieee80211_ratectl_none.h
3567 ===================================================================
3568 --- sys/net80211/ieee80211_ratectl_none.h (revision 0)
3569 +++ sys/net80211/ieee80211_ratectl_none.h (revision 256825)
3570 @@ -0,0 +1,38 @@
3571 +/*-
3572 + * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
3573 + *
3574 + * Permission to use, copy, modify, and distribute this software for any
3575 + * purpose with or without fee is hereby granted, provided that the above
3576 + * copyright notice and this permission notice appear in all copies.
3577 + *
3578 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3579 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3580 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3581 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3582 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3583 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3584 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3585 + */
3586 +
3587 +#ifndef _NET80211_IEEE80211_RATECTL_NONE_H_
3588 +#define _NET80211_IEEE80211_RATECTL_NONE_H_
3589 +
3590 +#include <net80211/ieee80211_ratectl.h>
3591 +
3592 +/*
3593 + * Rate control settings.
3594 + */
3595 +
3596 +struct ieee80211_none {
3597 + struct ieee80211_rc_stat none_stat;
3598 + /* other stuffs */
3599 +};
3600 +
3601 +/*
3602 + * Rate control state for a given node.
3603 + */
3604 +struct ieee80211_none_node {
3605 + struct ieee80211_none *non_none;
3606 +};
3607 +
3608 +#endif /* _NET80211_IEEE80211_RATECTL_NONE_H_ */
3609 Index: sys/net80211/ieee80211_rssadapt.h
3610 ===================================================================
3611 --- sys/net80211/ieee80211_rssadapt.h (revision 254826)
3612 +++ sys/net80211/ieee80211_rssadapt.h (working copy)
3613 @@ -32,6 +32,8 @@
3614 #ifndef _NET80211_IEEE80211_RSSADAPT_H_
3615 #define _NET80211_IEEE80211_RSSADAPT_H_
3616
3617 +#include <net80211/ieee80211_ratectl.h>
3618 +
3619 /* Data-rate adaptation loosely based on "Link Adaptation Strategy
3620 * for IEEE 802.11 WLAN via Received Signal Strength Measurement"
3621 * by Javier del Prado Pavon and Sunghyun Choi.
3622 @@ -43,6 +45,7 @@
3623 #define IEEE80211_RSSADAPT_BKTPOWER 3 /* 2**_BKTPOWER */
3624
3625 struct ieee80211_rssadapt {
3626 + struct ieee80211_rc_stat rssadapt_stat;
3627 const struct ieee80211vap *vap;
3628 int interval; /* update interval (ticks) */
3629 };
3630 Index: sys/net80211/ieee80211_amrr.h
3631 ===================================================================
3632 --- sys/net80211/ieee80211_amrr.h (revision 254826)
3633 +++ sys/net80211/ieee80211_amrr.h (working copy)
3634 @@ -20,6 +20,7 @@
3635 #ifndef _NET80211_IEEE80211_AMRR_H_
3636 #define _NET80211_IEEE80211_AMRR_H_
3637
3638 +#include <net80211/ieee80211_ratectl.h>
3639 /*-
3640 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
3641 *
3642 @@ -35,6 +36,7 @@
3643 struct ieee80211vap;
3644
3645 struct ieee80211_amrr {
3646 + struct ieee80211_rc_stat amrr_stat;
3647 u_int amrr_min_success_threshold;
3648 u_int amrr_max_success_threshold;
3649 int amrr_interval; /* update interval (ticks) */
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.