void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, u_int8_t *rix0, int *try0, u_int8_t *txrate) { #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) #define RATE(ix) (DOT11RATE(ix) / 2) struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; const HAL_RATE_TABLE *rt = sc->sc_currates; const int size_bin = size_to_bin(frameLen); int rix, mrr, best_rix, change_rates; unsigned average_tx_time; ath_rate_update_static_rix(sc, &an->an_node); if (sn->static_rix != -1) { rix = sn->static_rix; *try0 = ATH_TXMAXTRY; goto done; } /* XXX TODO: this doesn't know about 11gn vs 11g protection; teach it */ mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); best_rix = pick_best_rate(an, rt, size_bin, !mrr); if (best_rix >= 0) { average_tx_time = sn->stats[size_bin][best_rix].average_tx_time; } else { average_tx_time = 0; } /* * Limit the time measuring the performance of other tx * rates to sample_rate% of the total transmission time. */ if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { rix = pick_sample_rate(ssc, an, rt, size_bin); IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s", average_tx_time, sn->sample_tt[size_bin], bin_to_size(size_bin), dot11rate(rt, rix), dot11rate_label(rt, rix), dot11rate(rt, sn->current_rix[size_bin]), dot11rate_label(rt, sn->current_rix[size_bin])); if (rix != sn->current_rix[size_bin]) { sn->current_sample_rix[size_bin] = rix; } else { sn->current_sample_rix[size_bin] = -1; } sn->packets_since_sample[size_bin] = 0; } else { change_rates = 0; if (!sn->packets_sent[size_bin] || best_rix == -1) { /* no packet has been sent successfully yet */ change_rates = 1; if (an->an_node.ni_flags & IEEE80211_NODE_HT) best_rix = ath_rate_pick_seed_rate_ht(sc, an, frameLen); else best_rix = ath_rate_pick_seed_rate_legacy(sc, an, frameLen); } else if (sn->packets_sent[size_bin] < 20) { /* let the bit-rate switch quickly during the first few packets */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: switching quickly..", __func__); change_rates = 1; } else if (ticks - ssc->min_switch > sn->ticks_since_switch[size_bin]) { /* min_switch seconds have gone by */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: min_switch %d > ticks_since_switch %d..", __func__, ticks - ssc->min_switch, sn->ticks_since_switch[size_bin]); change_rates = 1; } else if ((! (an->an_node.ni_flags & IEEE80211_NODE_HT)) && (2*average_tx_time < sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time)) { /* the current bit-rate is twice as slow as the best one */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: 2x att (= %d) < cur_rix att %d", __func__, 2 * average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time); change_rates = 1; } else if ((an->an_node.ni_flags & IEEE80211_NODE_HT)) { int cur_rix = sn->current_rix[size_bin]; int cur_att = sn->stats[size_bin][cur_rix].average_tx_time; /* * If the node is HT, upgrade it if the MCS rate is * higher and the average tx time is within 20% of * the current rate. It can fail a little. * * This is likely not optimal! */ #if 0 printf("cur rix/att %x/%d, best rix/att %x/%d\n", MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time); #endif if ((MCS(best_rix) > MCS(cur_rix)) && (average_tx_time * 8) <= (cur_att * 10)) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d", __func__, MCS(best_rix), MCS(cur_rix), average_tx_time, cur_att); change_rates = 1; } } sn->packets_since_sample[size_bin]++; if (change_rates) { if (best_rix != sn->current_rix[size_bin]) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d", __func__, bin_to_size(size_bin), RATE(sn->current_rix[size_bin]), sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].perfect_tx_time, RATE(best_rix), sn->stats[size_bin][best_rix].average_tx_time, sn->stats[size_bin][best_rix].perfect_tx_time, sn->packets_since_switch[size_bin], mrr); } sn->packets_since_switch[size_bin] = 0; sn->current_rix[size_bin] = best_rix; sn->ticks_since_switch[size_bin] = ticks; /* * Set the visible txrate for this node. */ an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ? MCS(best_rix) : DOT11RATE(best_rix); } rix = sn->current_rix[size_bin]; sn->packets_since_switch[size_bin]++; } *try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY; done: KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix)); *rix0 = rix; *txrate = rt->info[rix].rateCode | (shortPreamble ? rt->info[rix].shortPreamble : 0); sn->packets_sent[size_bin]++; #undef DOT11RATE #undef MCS #undef RATE }
void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, u_int8_t *rix0, int *try0, u_int8_t *txrate) { #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) #define RATE(ix) (DOT11RATE(ix) / 2) struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; const HAL_RATE_TABLE *rt = sc->sc_currates; const int size_bin = size_to_bin(frameLen); int rix, mrr, best_rix, change_rates; unsigned average_tx_time; if (sn->static_rix != -1) { rix = sn->static_rix; *try0 = ATH_TXMAXTRY; goto done; } mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); best_rix = pick_best_rate(sn, rt, size_bin, !mrr); if (best_rix >= 0) { average_tx_time = sn->stats[size_bin][best_rix].average_tx_time; } else { average_tx_time = 0; } /* * Limit the time measuring the performance of other tx * rates to sample_rate% of the total transmission time. */ if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { rix = pick_sample_rate(ssc, sn, rt, size_bin); IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "size %u sample rate %d current rate %d", bin_to_size(size_bin), RATE(rix), RATE(sn->current_rix[size_bin])); if (rix != sn->current_rix[size_bin]) { sn->current_sample_rix[size_bin] = rix; } else { sn->current_sample_rix[size_bin] = -1; } sn->packets_since_sample[size_bin] = 0; } else { change_rates = 0; if (!sn->packets_sent[size_bin] || best_rix == -1) { /* no packet has been sent successfully yet */ for (rix = rt->rateCount-1; rix > 0; rix--) { if ((sn->ratemask & (1<<rix)) == 0) continue; /* * Pick the highest rate <= 36 Mbps * that hasn't failed. */ if (DOT11RATE(rix) <= 72 && sn->stats[size_bin][rix].successive_failures == 0) { break; } } change_rates = 1; best_rix = rix; } else if (sn->packets_sent[size_bin] < 20) { /* let the bit-rate switch quickly during the first few packets */ change_rates = 1; } else if (ticks - ssc->min_switch > sn->ticks_since_switch[size_bin]) { /* min_switch seconds have gone by */ change_rates = 1; } else if (2*average_tx_time < sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time) { /* the current bit-rate is twice as slow as the best one */ change_rates = 1; } sn->packets_since_sample[size_bin]++; if (change_rates) { if (best_rix != sn->current_rix[size_bin]) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d", __func__, bin_to_size(size_bin), RATE(sn->current_rix[size_bin]), sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].perfect_tx_time, RATE(best_rix), sn->stats[size_bin][best_rix].average_tx_time, sn->stats[size_bin][best_rix].perfect_tx_time, sn->packets_since_switch[size_bin], mrr); } sn->packets_since_switch[size_bin] = 0; sn->current_rix[size_bin] = best_rix; sn->ticks_since_switch[size_bin] = ticks; /* * Set the visible txrate for this node. */ an->an_node.ni_txrate = DOT11RATE(best_rix); } rix = sn->current_rix[size_bin]; sn->packets_since_switch[size_bin]++; } *try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY; done: KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix)); *rix0 = rix; *txrate = rt->info[rix].rateCode | (shortPreamble ? rt->info[rix].shortPreamble : 0); sn->packets_sent[size_bin]++; #undef DOT11RATE #undef RATE }