Lines Matching +full:poll +full:- +full:rate +full:- +full:ms
3 /*-
22 /*-
23 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
25 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
27 * INRIA Sophia - Projet Planete
28 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
57 ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
59 ((amn)->amn_retrycnt > (amn)->amn_txcnt / 3)
61 ((amn)->amn_txcnt > 10)
103 struct ieee80211_amrr *amrr = vap->iv_rs; in amrr_setinterval()
110 amrr->amrr_interval = msecs_to_ticks(msecs); in amrr_setinterval()
118 KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__)); in amrr_init()
121 amrr = vap->iv_rs = IEEE80211_MALLOC(sizeof(struct ieee80211_amrr), in amrr_init()
127 amrr->amrr_min_success_threshold = IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD; in amrr_init()
128 amrr->amrr_max_success_threshold = IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD; in amrr_init()
129 amrr_setinterval(vap, 500 /* ms */); in amrr_init()
130 amrr_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid); in amrr_init()
137 IEEE80211_FREE(vap->iv_rs, M_80211_RATECTL); in amrr_deinit()
138 vap->iv_rs = NULL; /* guard */ in amrr_deinit()
139 nrefs--; /* XXX locking */ in amrr_deinit()
145 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_node_init_vht()
148 amn->amn_vht_mcs = 2; in amrr_node_init_vht()
149 amn->amn_vht_nss = 1; in amrr_node_init_vht()
150 ieee80211_node_set_txrate_vht_rate(ni, amn->amn_vht_nss, in amrr_node_init_vht()
151 amn->amn_vht_mcs); in amrr_node_init_vht()
153 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_node_init_vht()
154 "AMRR: VHT: initial rate NSS %d MCS %d", in amrr_node_init_vht()
155 amn->amn_vht_nss, in amrr_node_init_vht()
156 amn->amn_vht_mcs); in amrr_node_init_vht()
163 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_node_init_ht()
164 uint8_t rate; /* dot11rate */ in amrr_node_init_ht() local
166 rs = (struct ieee80211_rateset *) &ni->ni_htrates; in amrr_node_init_ht()
167 /* Initial rate - lowest */ in amrr_node_init_ht()
168 rate = rs->rs_rates[0]; in amrr_node_init_ht()
171 for (amn->amn_rix = rs->rs_nrates - 1; amn->amn_rix > 0; in amrr_node_init_ht()
172 amn->amn_rix--) { in amrr_node_init_ht()
173 /* 11n - stop at MCS4 */ in amrr_node_init_ht()
174 if ((rs->rs_rates[amn->amn_rix] & 0x1f) < 4) in amrr_node_init_ht()
177 rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; in amrr_node_init_ht()
180 rate |= IEEE80211_RATE_MCS; in amrr_node_init_ht()
182 /* Assign initial rate from the rateset */ in amrr_node_init_ht()
183 ieee80211_node_set_txrate_dot11rate(ni, rate); in amrr_node_init_ht()
185 /* XXX TODO: we really need a rate-to-string method */ in amrr_node_init_ht()
186 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_node_init_ht()
187 "AMRR: nrates=%d, initial rate MCS %d", in amrr_node_init_ht()
188 rs->rs_nrates, in amrr_node_init_ht()
189 (rate & IEEE80211_RATE_VAL)); in amrr_node_init_ht()
196 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_node_init_legacy()
197 uint8_t rate; /* dot11rate */ in amrr_node_init_legacy() local
199 rs = &ni->ni_rates; in amrr_node_init_legacy()
200 /* Initial rate - lowest */ in amrr_node_init_legacy()
201 rate = rs->rs_rates[0]; in amrr_node_init_legacy()
203 /* Clear the basic rate flag if it's not 11n */ in amrr_node_init_legacy()
204 rate &= IEEE80211_RATE_VAL; in amrr_node_init_legacy()
207 for (amn->amn_rix = rs->rs_nrates - 1; amn->amn_rix > 0; in amrr_node_init_legacy()
208 amn->amn_rix--) { in amrr_node_init_legacy()
209 /* legacy - anything < 36mbit, stop searching */ in amrr_node_init_legacy()
210 if ((rs->rs_rates[amn->amn_rix] & in amrr_node_init_legacy()
214 rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; in amrr_node_init_legacy()
216 /* Assign initial rate from the rateset */ in amrr_node_init_legacy()
217 ieee80211_node_set_txrate_dot11rate(ni, rate); in amrr_node_init_legacy()
219 /* XXX TODO: we really need a rate-to-string method */ in amrr_node_init_legacy()
220 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_node_init_legacy()
221 "AMRR: nrates=%d, initial rate %d Mb", in amrr_node_init_legacy()
222 rs->rs_nrates, in amrr_node_init_legacy()
223 (rate & IEEE80211_RATE_VAL) / 2); in amrr_node_init_legacy()
229 struct ieee80211vap *vap = ni->ni_vap; in amrr_node_init()
230 struct ieee80211_amrr *amrr = vap->iv_rs; in amrr_node_init()
236 "per-node structure allocation skipped\n"); in amrr_node_init()
240 if (ni->ni_rctls == NULL) { in amrr_node_init()
241 ni->ni_rctls = amn = IEEE80211_MALLOC(sizeof(struct ieee80211_amrr_node), in amrr_node_init()
245 "couldn't alloc per-node ratectl structure\n"); in amrr_node_init()
249 amn = ni->ni_rctls; in amrr_node_init()
252 amn->amn_amrr = amrr; in amrr_node_init()
253 amn->amn_success = 0; in amrr_node_init()
254 amn->amn_recovery = 0; in amrr_node_init()
255 amn->amn_txcnt = amn->amn_retrycnt = 0; in amrr_node_init()
256 amn->amn_success_threshold = amrr->amrr_min_success_threshold; in amrr_node_init()
257 amn->amn_ticks = ticks; in amrr_node_init()
271 IEEE80211_FREE(ni->ni_rctls, M_80211_RATECTL); in amrr_node_deinit()
277 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_update_vht_inc()
287 nss = amn->amn_vht_nss; in amrr_update_vht_inc()
288 mcs = amn->amn_vht_mcs; in amrr_update_vht_inc()
300 if (ieee80211_vht_node_check_tx_valid_mcs(ni, ni->ni_chw, nss, in amrr_update_vht_inc()
302 amn->amn_vht_nss = nss; in amrr_update_vht_inc()
303 amn->amn_vht_mcs = mcs; in amrr_update_vht_inc()
312 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_update_vht_dec()
322 nss = amn->amn_vht_nss; in amrr_update_vht_dec()
323 mcs = amn->amn_vht_mcs; in amrr_update_vht_dec()
329 nss--; in amrr_update_vht_dec()
331 mcs--; in amrr_update_vht_dec()
335 if (ieee80211_vht_node_check_tx_valid_mcs(ni, ni->ni_chw, nss, in amrr_update_vht_dec()
337 amn->amn_vht_nss = nss; in amrr_update_vht_dec()
338 amn->amn_vht_mcs = mcs; in amrr_update_vht_dec()
345 * A placeholder / temporary hack VHT rate control.
353 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_update_vht()
354 struct ieee80211_amrr *amrr = ni->ni_vap->iv_rs; in amrr_update_vht()
356 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_vht()
357 "AMRR: VHT: current rate NSS %d MCS %d, txcnt=%d, retrycnt=%d", in amrr_update_vht()
358 amn->amn_vht_nss, amn->amn_vht_mcs, amn->amn_txcnt, in amrr_update_vht()
359 amn->amn_retrycnt); in amrr_update_vht()
362 amn->amn_success++; in amrr_update_vht()
363 if (amn->amn_success >= amn->amn_success_threshold) { in amrr_update_vht()
364 amn->amn_recovery = 1; in amrr_update_vht()
365 amn->amn_success = 0; in amrr_update_vht()
367 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_vht()
368 "AMRR: VHT: increase rate (txcnt=%d retrycnt=%d)", in amrr_update_vht()
369 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_vht()
373 amn->amn_recovery = 0; in amrr_update_vht()
376 amn->amn_success = 0; in amrr_update_vht()
378 if (amn->amn_recovery) { in amrr_update_vht()
379 amn->amn_success_threshold *= 2; in amrr_update_vht()
380 if (amn->amn_success_threshold > in amrr_update_vht()
381 amrr->amrr_max_success_threshold) in amrr_update_vht()
382 amn->amn_success_threshold = in amrr_update_vht()
383 amrr->amrr_max_success_threshold; in amrr_update_vht()
385 amn->amn_success_threshold = in amrr_update_vht()
386 amrr->amrr_min_success_threshold; in amrr_update_vht()
388 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_vht()
389 "AMRR: VHT: decreasing rate (txcnt=%d retrycnt=%d)", in amrr_update_vht()
390 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_vht()
394 amn->amn_recovery = 0; in amrr_update_vht()
398 amn->amn_txcnt = 0; in amrr_update_vht()
399 amn->amn_retrycnt = 0; in amrr_update_vht()
409 int rix = amn->amn_rix; in amrr_update_ht()
412 rs = (struct ieee80211_rateset *)&ni->ni_htrates; in amrr_update_ht()
414 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_ht()
415 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_ht()
416 "AMRR: current rate MCS %d, txcnt=%d, retrycnt=%d", in amrr_update_ht()
417 rs->rs_rates[rix] & IEEE80211_RATE_VAL, in amrr_update_ht()
418 amn->amn_txcnt, in amrr_update_ht()
419 amn->amn_retrycnt); in amrr_update_ht()
430 amn->amn_success++; in amrr_update_ht()
431 if (amn->amn_success >= amn->amn_success_threshold && in amrr_update_ht()
432 rix + 1 < rs->rs_nrates) { in amrr_update_ht()
433 amn->amn_recovery = 1; in amrr_update_ht()
434 amn->amn_success = 0; in amrr_update_ht()
436 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_ht()
437 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_ht()
438 "AMRR increasing rate MCS %d " in amrr_update_ht()
440 rs->rs_rates[rix] & IEEE80211_RATE_VAL, in amrr_update_ht()
441 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_ht()
443 amn->amn_recovery = 0; in amrr_update_ht()
446 amn->amn_success = 0; in amrr_update_ht()
448 if (amn->amn_recovery) { in amrr_update_ht()
449 amn->amn_success_threshold *= 2; in amrr_update_ht()
450 if (amn->amn_success_threshold > in amrr_update_ht()
451 amrr->amrr_max_success_threshold) in amrr_update_ht()
452 amn->amn_success_threshold = in amrr_update_ht()
453 amrr->amrr_max_success_threshold; in amrr_update_ht()
455 amn->amn_success_threshold = in amrr_update_ht()
456 amrr->amrr_min_success_threshold; in amrr_update_ht()
458 rix--; in amrr_update_ht()
459 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_ht()
460 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_ht()
461 "AMRR decreasing rate MCS %d " in amrr_update_ht()
463 rs->rs_rates[rix] & IEEE80211_RATE_VAL, in amrr_update_ht()
464 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_ht()
466 amn->amn_recovery = 0; in amrr_update_ht()
476 int rix = amn->amn_rix; in amrr_update_legacy()
479 rs = &ni->ni_rates; in amrr_update_legacy()
481 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_legacy()
482 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_legacy()
483 "AMRR: current rate %d Mb, txcnt=%d, retrycnt=%d", in amrr_update_legacy()
484 (rs->rs_rates[rix] & IEEE80211_RATE_VAL) / 2, in amrr_update_legacy()
485 amn->amn_txcnt, in amrr_update_legacy()
486 amn->amn_retrycnt); in amrr_update_legacy()
489 amn->amn_success++; in amrr_update_legacy()
490 if (amn->amn_success >= amn->amn_success_threshold && in amrr_update_legacy()
491 rix + 1 < rs->rs_nrates) { in amrr_update_legacy()
492 amn->amn_recovery = 1; in amrr_update_legacy()
493 amn->amn_success = 0; in amrr_update_legacy()
495 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_legacy()
496 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_legacy()
497 "AMRR increasing rate %d Mb (txcnt=%d retrycnt=%d)", in amrr_update_legacy()
498 (rs->rs_rates[rix] & IEEE80211_RATE_VAL) / 2, in amrr_update_legacy()
499 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_legacy()
501 amn->amn_recovery = 0; in amrr_update_legacy()
504 amn->amn_success = 0; in amrr_update_legacy()
506 if (amn->amn_recovery) { in amrr_update_legacy()
507 amn->amn_success_threshold *= 2; in amrr_update_legacy()
508 if (amn->amn_success_threshold > in amrr_update_legacy()
509 amrr->amrr_max_success_threshold) in amrr_update_legacy()
510 amn->amn_success_threshold = in amrr_update_legacy()
511 amrr->amrr_max_success_threshold; in amrr_update_legacy()
513 amn->amn_success_threshold = in amrr_update_legacy()
514 amrr->amrr_min_success_threshold; in amrr_update_legacy()
516 rix--; in amrr_update_legacy()
517 /* XXX TODO: we really need a rate-to-string method */ in amrr_update_legacy()
518 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, in amrr_update_legacy()
519 "AMRR decreasing rate %d Mb (txcnt=%d retrycnt=%d)", in amrr_update_legacy()
520 (rs->rs_rates[rix] & IEEE80211_RATE_VAL) / 2, in amrr_update_legacy()
521 amn->amn_txcnt, amn->amn_retrycnt); in amrr_update_legacy()
523 amn->amn_recovery = 0; in amrr_update_legacy()
535 KASSERT(is_enough(amn), ("txcnt %d", amn->amn_txcnt)); in amrr_update()
546 amn->amn_txcnt = 0; in amrr_update()
547 amn->amn_retrycnt = 0; in amrr_update()
555 struct ieee80211_amrr *amrr = ni->ni_vap->iv_rs; in amrr_rate_vht()
556 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_rate_vht()
558 if (is_enough(amn) && (ticks - amn->amn_ticks) > amrr->amrr_interval) in amrr_rate_vht()
561 ieee80211_node_set_txrate_vht_rate(ni, amn->amn_vht_nss, in amrr_rate_vht()
562 amn->amn_vht_mcs); in amrr_rate_vht()
569 * Return the rate index to use in sending a data frame.
571 * If the rate changes we also update ni_txrate to match.
576 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_rate()
581 /* XXX should return -1 here, but drivers may not expect this... */ in amrr_rate()
585 ni->ni_rates.rs_rates[0]); in amrr_rate()
595 rs = (struct ieee80211_rateset *) &ni->ni_htrates; in amrr_rate()
597 rs = &ni->ni_rates; in amrr_rate()
600 amrr = amn->amn_amrr; in amrr_rate()
601 if (is_enough(amn) && (ticks - amn->amn_ticks) > amrr->amrr_interval) { in amrr_rate()
603 if (rix != amn->amn_rix) { in amrr_rate()
605 /* update public rate */ in amrr_rate()
606 dot11Rate = rs->rs_rates[rix]; in amrr_rate()
607 /* XXX strip basic rate flag from txrate, if non-11n */ in amrr_rate()
614 amn->amn_rix = rix; in amrr_rate()
616 amn->amn_ticks = ticks; in amrr_rate()
618 rix = amn->amn_rix; in amrr_rate()
623 * Update statistics with tx complete status. Ok is non-zero
625 * retransmissions (i.e. xmit attempts - 1).
631 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_tx_complete()
638 if (status->flags & IEEE80211_RATECTL_STATUS_LONG_RETRY) in amrr_tx_complete()
639 retries = status->long_retries; in amrr_tx_complete()
641 amn->amn_txcnt++; in amrr_tx_complete()
642 if (status->status == IEEE80211_RATECTL_TX_SUCCESS) in amrr_tx_complete()
643 amn->amn_success++; in amrr_tx_complete()
644 amn->amn_retrycnt += retries; in amrr_tx_complete()
651 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_tx_update_cb()
657 txcnt = stats->nframes; in amrr_tx_update_cb()
658 success = stats->nsuccess; in amrr_tx_update_cb()
660 if (stats->flags & IEEE80211_RATECTL_TX_STATS_RETRIES) in amrr_tx_update_cb()
661 retrycnt = stats->nretries; in amrr_tx_update_cb()
663 amn->amn_txcnt += txcnt; in amrr_tx_update_cb()
664 amn->amn_success += success; in amrr_tx_update_cb()
665 amn->amn_retrycnt += retrycnt; in amrr_tx_update_cb()
670 * drivers that poll the device for statistics maintained
678 if (stats->flags & IEEE80211_RATECTL_TX_STATS_NODE) in amrr_tx_update()
679 amrr_tx_update_cb(stats, stats->ni); in amrr_tx_update()
681 ieee80211_iterate_nodes_vap(&vap->iv_ic->ic_sta, vap, in amrr_tx_update()
690 struct ieee80211_amrr *amrr = vap->iv_rs; in amrr_sysctl_interval()
696 msecs = ticks_to_msecs(amrr->amrr_interval); in amrr_sysctl_interval()
698 if (error || !req->newptr) in amrr_sysctl_interval()
708 struct ieee80211_amrr *amrr = vap->iv_rs; in amrr_sysctlattach()
715 vap, 0, amrr_sysctl_interval, "I", "amrr operation interval (ms)"); in amrr_sysctlattach()
719 &amrr->amrr_max_success_threshold, 0, ""); in amrr_sysctlattach()
722 &amrr->amrr_min_success_threshold, 0, ""); in amrr_sysctlattach()
729 int rate; in amrr_print_node_rate() local
733 rs = (struct ieee80211_rateset *) &ni->ni_htrates; in amrr_print_node_rate()
734 rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; in amrr_print_node_rate()
735 sbuf_printf(s, "rate: MCS %d\n", rate); in amrr_print_node_rate()
737 rs = &ni->ni_rates; in amrr_print_node_rate()
738 rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; in amrr_print_node_rate()
739 sbuf_printf(s, "rate: %d Mbit\n", rate / 2); in amrr_print_node_rate()
746 struct ieee80211_amrr_node *amn = ni->ni_rctls; in amrr_node_stats()
754 sbuf_printf(s, "ticks: %d\n", amn->amn_ticks); in amrr_node_stats()
755 sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt); in amrr_node_stats()
756 sbuf_printf(s, "success: %u\n", amn->amn_success); in amrr_node_stats()
757 sbuf_printf(s, "success_threshold: %u\n", amn->amn_success_threshold); in amrr_node_stats()
758 sbuf_printf(s, "recovery: %u\n", amn->amn_recovery); in amrr_node_stats()
759 sbuf_printf(s, "retry_cnt: %u\n", amn->amn_retrycnt); in amrr_node_stats()