From owner-p4-projects@FreeBSD.ORG Wed Mar 30 22:35:41 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 578F216A4D0; Wed, 30 Mar 2005 22:35:41 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3216F16A4CE for ; Wed, 30 Mar 2005 22:35:41 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id B719D43D2D for ; Wed, 30 Mar 2005 22:35:40 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j2UMZeO9071679 for ; Wed, 30 Mar 2005 22:35:40 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j2UMZer5071676 for perforce@freebsd.org; Wed, 30 Mar 2005 22:35:40 GMT (envelope-from sam@freebsd.org) Date: Wed, 30 Mar 2005 22:35:40 GMT Message-Id: <200503302235.j2UMZer5071676@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 74132 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Mar 2005 22:35:42 -0000 http://perforce.freebsd.org/chv.cgi?CH=74132 Change 74132 by sam@sam_ebb on 2005/03/30 22:35:12 IFC Affected files ... .. //depot/projects/wifi/sys/dev/ath/ath_rate/sample/sample.c#3 integrate .. //depot/projects/wifi/sys/dev/ath/ath_rate/sample/sample.h#3 integrate Differences ... ==== //depot/projects/wifi/sys/dev/ath/ath_rate/sample/sample.c#3 (text+ko) ==== @@ -36,7 +36,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.4 2005/01/24 19:32:10 sam Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.6 2005/03/30 20:20:49 sam Exp $"); /* * John Bicket's SampleRate control algorithm. @@ -111,7 +111,9 @@ * */ -static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *); +#define STALE_FAILURE_TIMEOUT_MS 10000 + +static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *); static __inline int size_to_bin(int size) { @@ -127,6 +129,16 @@ return packet_size_bins[index]; } +static __inline int rate_to_ndx(struct sample_node *sn, int rate) { + int x = 0; + for (x = 0; x < sn->num_rates; x++) { + if (sn->rates[x].rate == rate) { + return x; + } + } + return -1; +} + /* * Setup rate codes for management/control frames. We force * all such frames to the lowest rate. @@ -162,18 +174,21 @@ * returns the ndx with the lowest average_tx_time, * or -1 if all the average_tx_times are 0. */ -static __inline int best_rate_ndx(struct sample_node *sn, int size_bin) +static __inline int best_rate_ndx(struct sample_node *sn, int size_bin, + int require_acked_before) { int x = 0; int best_rate_ndx = 0; int best_rate_tt = 0; for (x = 0; x < sn->num_rates; x++) { int tt = sn->stats[size_bin][x].average_tx_time; - if (tt > 0) { - if (!best_rate_tt || best_rate_tt > tt) { - best_rate_tt = tt; - best_rate_ndx = x; - } + if (tt <= 0 || (require_acked_before && + !sn->stats[size_bin][x].packets_acked)) { + continue; + } + if (!best_rate_tt || best_rate_tt > tt) { + best_rate_tt = tt; + best_rate_ndx = x; } } return (best_rate_tt) ? best_rate_ndx : -1; @@ -187,45 +202,38 @@ static __inline int pick_sample_ndx(struct sample_node *sn, int size_bin) { int x = 0; - int best_ndx = best_rate_ndx(sn, size_bin); - int best_tt = 0; - int num_eligible = 0; + int current_ndx = 0; + unsigned current_tt = 0; - if (best_ndx < 0) { + current_ndx = sn->current_rate[size_bin]; + if (current_ndx < 0) { /* no successes yet, send at the lowest bit-rate */ return 0; } - best_tt = sn->stats[size_bin][best_ndx].average_tx_time; - sn->sample_num[size_bin]++; + current_tt = sn->stats[size_bin][current_ndx].average_tx_time; - /* - * first, find the number of bit-rates we could potentially - * sample. we assume this list doesn't change a lot, so - * we will just cycle through them. - */ for (x = 0; x < sn->num_rates; x++) { - if (x != best_ndx && - sn->stats[size_bin][x].perfect_tx_time < best_tt && - sn->stats[size_bin][x].successive_failures < 4) { - num_eligible++; + int ndx = (sn->last_sample_ndx[size_bin] + 1 + x) % sn->num_rates; + /* + * clear any stale stuff out. + */ + if (ticks - sn->stats[size_bin][ndx].last_tx > ((hz * STALE_FAILURE_TIMEOUT_MS)/1000)) { + sn->stats[size_bin][ndx].average_tx_time = sn->stats[size_bin][ndx].perfect_tx_time; + sn->stats[size_bin][ndx].successive_failures = 0; + sn->stats[size_bin][ndx].tries = 0; + sn->stats[size_bin][ndx].total_packets = 0; + sn->stats[size_bin][ndx].packets_acked = 0; } - } - - if (num_eligible > 0) { - int pick = sn->sample_num[size_bin] % num_eligible; - for (x = 0; x < sn->num_rates; x++) { - if (x != best_ndx && - sn->stats[size_bin][x].perfect_tx_time < best_tt && - sn->stats[size_bin][x].successive_failures < 4) { - if (pick == 0) { - return x; - } - pick--; - } + + if (ndx != current_ndx && + sn->stats[size_bin][ndx].perfect_tx_time < current_tt && + sn->stats[size_bin][ndx].successive_failures < 4) { + sn->last_sample_ndx[size_bin] = ndx; + return ndx; } } - return best_ndx; + return current_ndx; } void @@ -235,73 +243,138 @@ { struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); - int x; - int ndx = 0; - int size_bin = size_to_bin(frameLen); - int best_ndx = best_rate_ndx(sn, size_bin); + struct ieee80211com *ic = &sc->sc_ic; + int ndx, size_bin, mrr, best_ndx; + unsigned average_tx_time; + + mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && + !(frameLen > ic->ic_rtsthreshold); + size_bin = size_to_bin(frameLen); + best_ndx = best_rate_ndx(sn, size_bin, !mrr); + if (best_ndx >= 0) { + average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time; + } else { + average_tx_time = 0; + } if (sn->static_rate_ndx != -1) { - *try0 = 4; - *rix = sn->rates[sn->static_rate_ndx].rix; - *txrate = sn->rates[sn->static_rate_ndx].rateCode; - return; - } - - *try0 = 2; - - best_ndx = best_rate_ndx(sn, size_bin); - if (!sn->packets_sent[size_bin] || - sn->packets_sent[size_bin] % ssc->ath_sample_rate > 0) { - /* - * for most packets, send the packet at the bit-rate with - * the lowest estimated transmission time. - */ - if (best_ndx != -1) { - ndx = best_ndx; + ndx = sn->static_rate_ndx; + *try0 = ATH_TXMAXTRY; + } else { + ndx = 0; + *try0 = mrr ? 2 : ATH_TXMAXTRY; + + DPRINTF(sc, "%s: %s size %d mrr %d packets_sent %d best_ndx %d " + "sample tt %d packets since %d\n" + , __func__, ether_sprintf(an->an_node.ni_macaddr) + , packet_size_bins[size_bin] + , mrr + , sn->packets_sent[size_bin] + , best_ndx + , sn->sample_tt[size_bin] + , sn->packets_since_sample[size_bin] + ); + if (!sn->packets_sent[size_bin]) { + /* no packets sent */ + if (best_ndx == -1) { + ndx = sn->num_rates - 1; + if (sc->sc_curmode != IEEE80211_MODE_11B) { + for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--) + ; + + } + } else { + ndx = best_ndx; + } + } else if (best_ndx == -1) { + /* no packet has succeeded yet */ + if (mrr) { + /* + * no packet has succeeded, try the + * highest bitrate that hasn't failed + */ + for (ndx = sn->num_rates-1; ndx >= 0; ndx--) { + if (sn->stats[size_bin][ndx].successive_failures == 0) { + break; + } + } + } else { + ndx = sn->num_rates - 1; + if (sc->sc_curmode != IEEE80211_MODE_11B) { + for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--) + ; + + } + } + } else if (sn->sample_tt[size_bin] < (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100) * average_tx_time && + sn->packets_since_sample[size_bin] > 15) { + /* + * we want to limit the time measuring the performance + * of other bit-rates to ath_sample_rate% of the + * total transmission time. + */ + ndx = pick_sample_ndx(sn, size_bin); + if (ndx != sn->current_rate[size_bin]) { + DPRINTF(sc, "%s: %s size %d last sample tt %d sampling %d packets since %d\n", + __func__, + ether_sprintf(an->an_node.ni_macaddr), + packet_size_bins[size_bin], + sn->sample_tt[size_bin], + sn->rates[ndx].rate, + sn->packets_since_sample[size_bin]); + sn->current_sample_ndx[size_bin] = ndx; + } else { + sn->current_sample_ndx[size_bin] = -1; + } + sn->packets_since_sample[size_bin] = 0; + } else { - /* - * no packet has succeeded, try the highest bitrate - * that hasn't failed. - */ - for (ndx = sn->num_rates-1; ndx >= 0; ndx--) { - if (sn->stats[size_bin][ndx].successive_failures == 0) { - break; + sn->packets_since_sample[size_bin]++; + /* + * don't switch bit-rates every packet. only + * switch during the first few packets we send + * or after 100 packets, or if the current + * bit-rate begins to perform twice as bad as + * another one. + */ + if (sn->packets_sent[size_bin] < 20 || + ticks - ((hz*2000)/1000) > sn->jiffies_since_switch[size_bin] || + average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time ) { + if (sn->packets_sent[size_bin] > 20) { + DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mmr %d\n", + __func__, + ether_sprintf(an->an_node.ni_macaddr), + packet_size_bins[size_bin], + sn->rates[sn->current_rate[size_bin]].rate, + sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time, + sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time, + sn->rates[best_ndx].rate, + sn->stats[size_bin][best_ndx].average_tx_time, + sn->stats[size_bin][best_ndx].perfect_tx_time, + sn->packets_since_switch[size_bin], + mrr); } + sn->packets_since_switch[size_bin] = 0; + sn->current_rate[size_bin] = best_ndx; + sn->jiffies_since_switch[size_bin] = ticks; } + ndx = sn->current_rate[size_bin]; + sn->packets_since_switch[size_bin]++; } - if (size_bin == 0) { - /* update the visible txrate for this node */ - an->an_node.ni_txrate = ndx; - } - } else { - /* - * before we pick a bit-rate to "sample", clear any - * stale stuff out. - */ - for (x = 0; x < sn->num_rates; x++) { - if (ticks - sn->stats[size_bin][x].last_tx > ((hz * 10000)/1000)) { - sn->stats[size_bin][x].average_tx_time = sn->stats[size_bin][x].perfect_tx_time; - sn->stats[size_bin][x].successive_failures = 0; - sn->stats[size_bin][x].tries = 0; - sn->stats[size_bin][x].total_packets = 0; - sn->stats[size_bin][x].packets_acked = 0; - } - } + + } - /* send the packet at a different bit-rate */ - ndx = pick_sample_ndx(sn, size_bin); + if (ndx < 0) { + ndx = 0; } - - *rix = sn->rates[ndx].rix; if (shortPreamble) { *txrate = sn->rates[ndx].shortPreambleRateCode; } else { - *txrate = sn->rates[ndx].rateCode; } - sn->packets_sent[size_bin]++; + an->an_node.ni_txrate = ndx; } void @@ -310,107 +383,109 @@ { struct sample_node *sn = ATH_NODE_SAMPLE(an); int rateCode = -1; - int frame_size; - int size_bin; - int best_ndx; + int frame_size, size_bin, best_ndx, ndx; frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ - if (frame_size == 0) - frame_size = 1500; + KASSERT(frame_size != 0, ("no frame size")); size_bin = size_to_bin(frame_size); - best_ndx = best_rate_ndx(sn, size_bin); + best_ndx = best_rate_ndx(sn, size_bin, 0); if (best_ndx == -1 || !sn->stats[size_bin][best_ndx].packets_acked) { /* - * no packet has succeeded, so also try twice at the lowest bitate. + * no packet has succeeded, so also try at the + * lowest bitate. */ - if (shortPreamble) { - rateCode = sn->rates[0].shortPreambleRateCode; - } else { - rateCode = sn->rates[0].rateCode; - } - } else if (sn->rates[best_ndx].rix != rix) { + ndx = 0; + } else { /* * we're trying a different bit-rate, and it could be lossy, * so if it fails try at the best bit-rate. */ - if (shortPreamble) { - rateCode = sn->rates[MAX(0,best_ndx-1)].shortPreambleRateCode; - } else { - rateCode = sn->rates[MAX(0,best_ndx-1)].rateCode; - } + ndx = best_ndx; } - if (rateCode != -1) { - ath_hal_setupxtxdesc(sc->sc_ah, ds - , rateCode, 1 /* series 1 */ - , rateCode, 1 /* series 2 */ - , rateCode, 1 /* series 3 */ - ); + KASSERT(0 <= ndx && ndx < IEEE80211_RATE_MAXSIZE, + ("invalid ndx %d", ndx)); + if (shortPreamble) { + rateCode = sn->rates[ndx].shortPreambleRateCode; + } else { + rateCode = sn->rates[ndx].rateCode; } - + ath_hal_setupxtxdesc(sc->sc_ah, ds + , rateCode, 3 /* series 1 */ + , sn->rates[0].rateCode, 3 /* series 2 */ + , 0, 0 /* series 3 */ + ); } -void -ath_rate_tx_complete(struct ath_softc *sc, - struct ath_node *an, const struct ath_desc *ds) +static void +update_stats(struct ath_softc *sc, struct ath_node *an, + int frame_size, + int ndx0, int tries0, + int ndx1, int tries1, + int ndx2, int tries2, + int ndx3, int tries3, + int short_tries, int tries, int status) { struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); - int rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate; - int retries = ds->ds_txstat.ts_longretry; - int initial_rate_failed = ((ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE) - || ds->ds_txstat.ts_status != 0 || - retries > 3); int tt = 0; - int rix = -1; - int x = 0; - int frame_size; /* low-order 12 bits of ds_ctl0 */ - int size_bin; - int size; + int tries_so_far = 0; + int size_bin = 0; + int size = 0; + int rate = 0; + + size_bin = size_to_bin(frame_size); + size = bin_to_size(size_bin); + rate = sn->rates[ndx0].rate; - if (!sn->num_rates) { - DPRINTF(sc, "%s: no rates yet\n", __func__); - return; + tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix, + short_tries-1, + MIN(tries0, tries) - 1); + tries_so_far += tries0; + if (tries1 && tries0 < tries) { + tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix, + short_tries-1, + MIN(tries1 + tries_so_far, tries) - tries_so_far - 1); } - for (x = 0; x < sn->num_rates; x++) { - if (sn->rates[x].rate == rate) { - rix = x; - break; - } + tries_so_far += tries1; + + if (tries2 && tries0 + tries1 < tries) { + tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix, + short_tries-1, + MIN(tries2 + tries_so_far, tries) - tries_so_far - 1); } - - if (rix < 0 || rix > sn->num_rates) { - /* maybe a management packet */ - return; - } - frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ - if (frame_size == 0) - frame_size = 1500; - size_bin = size_to_bin(frame_size); - size = bin_to_size(size_bin); - tt = calc_usecs_unicast_packet(sc, size, sn->rates[rix].rix, - retries); + tries_so_far += tries2; - DPRINTF(sc, "%s: rate %d rix %d frame_size %d (%d) retries %d status %d tt %d avg_tt %d perfect_tt %d ts-rate %d\n", - __func__, rate, rix, frame_size, size, retries, initial_rate_failed, tt, - sn->stats[size_bin][rix].average_tx_time, - sn->stats[size_bin][rix].perfect_tx_time, - ds->ds_txstat.ts_rate); - - if (sn->stats[size_bin][rix].total_packets < 7) { + if (tries3 && tries0 + tries1 + tries2 < tries) { + tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix, + short_tries-1, + MIN(tries3 + tries_so_far, tries) - tries_so_far - 1); + } +#ifdef SAMPLE_DEBUG + if (short_tries + tries > 3 || status) { + DPRINTF(sc, "%s: %s size %d rate %d ndx %d tries (%d/%d) tries0 %d tt %d avg_tt %d perfect_tt %d status %d\n", + __func__, ether_sprintf(an->an_node.ni_macaddr), + size, + rate, ndx0, short_tries, tries, tries0, tt, + sn->stats[size_bin][ndx0].average_tx_time, + sn->stats[size_bin][ndx0].perfect_tx_time, + status); + } +#endif /* SAMPLE_DEBUG */ + if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) { /* just average the first few packets */ - int avg_tx = sn->stats[size_bin][rix].average_tx_time; - int packets = sn->stats[size_bin][rix].total_packets; - sn->stats[size_bin][rix].average_tx_time = (tt+(avg_tx*packets))/(packets+1); + int avg_tx = sn->stats[size_bin][ndx0].average_tx_time; + int packets = sn->stats[size_bin][ndx0].total_packets; + sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1); } else { /* use a ewma */ - sn->stats[size_bin][rix].average_tx_time = - ((sn->stats[size_bin][rix].average_tx_time * ssc->ath_smoothing_rate) + + sn->stats[size_bin][ndx0].average_tx_time = + ((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) + (tt * (100 - ssc->ath_smoothing_rate))) / 100; } - if (initial_rate_failed) { + if (status) { /* * this packet failed - count this as a failure * for larger packets also, since we assume @@ -419,82 +494,196 @@ */ int y; for (y = size_bin; y < NUM_PACKET_SIZE_BINS; y++) { - sn->stats[y][rix].successive_failures++; - sn->stats[y][rix].last_tx = ticks; + sn->stats[y][ndx0].successive_failures++; + sn->stats[y][ndx0].last_tx = ticks; } } else { - sn->stats[size_bin][rix].packets_acked++; - sn->stats[size_bin][rix].successive_failures = 0; + sn->stats[size_bin][ndx0].packets_acked++; + sn->stats[size_bin][ndx0].successive_failures = 0; + } + sn->stats[size_bin][ndx0].tries += tries; + sn->stats[size_bin][ndx0].last_tx = ticks; + sn->stats[size_bin][ndx0].total_packets++; + + + if (ndx0 == sn->current_sample_ndx[size_bin]) { + DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n", + __func__, ether_sprintf(an->an_node.ni_macaddr), + size, rate, short_tries, tries, tt, + sn->stats[size_bin][ndx0].average_tx_time, + sn->stats[size_bin][ndx0].perfect_tx_time, + status); + sn->sample_tt[size_bin] = tt; + sn->current_sample_ndx[size_bin] = -1; } - sn->stats[size_bin][rix].tries += (1+retries); - sn->stats[size_bin][rix].last_tx = ticks; - sn->stats[size_bin][rix].total_packets++; } void -ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) +ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, + const struct ath_desc *ds, const struct ath_desc *ds0) { - DPRINTF(sc, "%s:\n", __func__); - if (isnew) - ath_rate_ctl_start(sc, &an->an_node); -} + struct sample_node *sn = ATH_NODE_SAMPLE(an); + const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0; + int final_rate, short_tries, long_tries, frame_size; + int ndx = -1; + + final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate; + short_tries = ds->ds_txstat.ts_shortretry + 1; + long_tries = ds->ds_txstat.ts_longretry + 1; + frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ + if (frame_size == 0) /* NB: should not happen */ + frame_size = 1500; + + if (sn->num_rates <= 0) { + DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d " + "no rates yet\n", + __func__, ether_sprintf(an->an_node.ni_macaddr), + bin_to_size(size_to_bin(frame_size)), + ds->ds_txstat.ts_status, + short_tries, long_tries); + return; + } + + if (sc->sc_mrretry && ds->ds_txstat.ts_status) { + /* this packet failed */ + DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", + __func__, + ether_sprintf(an->an_node.ni_macaddr), + bin_to_size(size_to_bin(frame_size)), + sc->sc_hwmap[ads->xmit_rate0].ieeerate, + ads->xmit_tries0, + sc->sc_hwmap[ads->xmit_rate1].ieeerate, + ads->xmit_tries1, + sc->sc_hwmap[ads->xmit_rate2].ieeerate, + ads->xmit_tries2, + sc->sc_hwmap[ads->xmit_rate3].ieeerate, + ads->xmit_tries3, + ds->ds_txstat.ts_status ? "FAIL" : "OK", + short_tries, + long_tries); + } + + if (!(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) { + /* only one rate was used */ + ndx = rate_to_ndx(sn, final_rate); + DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n", + __func__, ether_sprintf(an->an_node.ni_macaddr), + bin_to_size(size_to_bin(frame_size)), + ds->ds_txstat.ts_status, + ndx, short_tries, long_tries); + if (ndx >= 0 && ndx < sn->num_rates) { + update_stats(sc, an, frame_size, + ndx, long_tries, + 0, 0, + 0, 0, + 0, 0, + short_tries, long_tries, ds->ds_txstat.ts_status); + } + } else { + int rate0, tries0, ndx0; + int rate1, tries1, ndx1; + int rate2, tries2, ndx2; + int rate3, tries3, ndx3; + int finalTSIdx = ads->final_ts_index; -static void -ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) -{ - struct ath_node *an = ATH_NODE(ni); - struct sample_node *sn = ATH_NODE_SAMPLE(an); - int x = 0; - int y = 0; + /* + * Process intermediate rates that failed. + */ - for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { - int size = bin_to_size(y); - sn->packets_sent[y] = 0; - sn->sample_num[y] = 0; + rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate; + tries0 = ads->xmit_tries0; + ndx0 = rate_to_ndx(sn, rate0); + + rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate; + tries1 = ads->xmit_tries1; + ndx1 = rate_to_ndx(sn, rate1); + + rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate; + tries2 = ads->xmit_tries2; + ndx2 = rate_to_ndx(sn, rate2); + + rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate; + tries3 = ads->xmit_tries3; + ndx3 = rate_to_ndx(sn, rate3); + +#if 1 + DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", + __func__, ether_sprintf(an->an_node.ni_macaddr), + bin_to_size(size_to_bin(frame_size)), + finalTSIdx, + long_tries, + ds->ds_txstat.ts_status, + rate0, tries0, + rate1, tries1, + rate2, tries2, + rate3, tries3); +#endif - for (x = 0; x < ni->ni_rates.rs_nrates; x++) { - sn->stats[y][x].successive_failures = 0; - sn->stats[y][x].tries = 0; - sn->stats[y][x].total_packets = 0; - sn->stats[y][x].packets_acked = 0; - sn->stats[y][x].last_tx = 0; - sn->stats[y][x].perfect_tx_time = calc_usecs_unicast_packet(sc, size, - sn->rates[x].rix, - 0); - sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time; + if (tries0) { + update_stats(sc, an, frame_size, + ndx0, tries0, + ndx1, tries1, + ndx2, tries2, + ndx3, tries3, + short_tries, ds->ds_txstat.ts_longretry + 1, + ds->ds_txstat.ts_status); + } + + if (tries1 && finalTSIdx > 0) { + update_stats(sc, an, frame_size, + ndx1, tries1, + ndx2, tries2, + ndx3, tries3, + 0, 0, + short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, + ds->ds_txstat.ts_status); + } - - DPRINTF(sc, "%s: %d rate %d rix %d rateCode %d perfect_tx_time %d \n", __func__, - x, sn->rates[x].rate, - sn->rates[x].rix, sn->rates[x].rateCode, - sn->stats[0][x].perfect_tx_time); + if (tries2 && finalTSIdx > 1) { + update_stats(sc, an, frame_size, + ndx2, tries2, + ndx3, tries3, + 0, 0, + 0, 0, + short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, + ds->ds_txstat.ts_status); } + if (tries3 && finalTSIdx > 2) { + update_stats(sc, an, frame_size, + ndx3, tries3, + 0, 0, + 0, 0, + 0, 0, + short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, + ds->ds_txstat.ts_status); + } } - - /* set the visible bit-rate to the lowest one available */ - ni->ni_txrate = 0; +} +void +ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) +{ + DPRINTF(sc, "%s: %s isnew %d\n", __func__, + ether_sprintf(an->an_node.ni_macaddr), isnew); + if (isnew) + ath_rate_ctl_reset(sc, &an->an_node); } /* * Initialize the tables for a node. */ static void -ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) +ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) { #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) struct ieee80211com *ic = &sc->sc_ic; struct ath_node *an = ATH_NODE(ni); struct sample_node *sn = ATH_NODE_SAMPLE(an); const HAL_RATE_TABLE *rt = sc->sc_currates; + int x, y, srate; - int x; - int srate; - - DPRINTF(sc, "%s:\n", __func__); KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); - KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); sn->static_rate_ndx = -1; if (ic->ic_fixed_rate != -1) { /* @@ -514,20 +703,58 @@ KASSERT(srate >= 0, ("fixed rate %d not in rate set", ic->ic_fixed_rate)); sn->static_rate_ndx = srate; - } + + DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr)); + sn->num_rates = ni->ni_rates.rs_nrates; for (x = 0; x < ni->ni_rates.rs_nrates; x++) { - sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; - sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; - sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; - sn->rates[x].shortPreambleRateCode = - rt->info[sn->rates[x].rix].rateCode | - rt->info[sn->rates[x].rix].shortPreamble; + sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; + sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; + sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; + sn->rates[x].shortPreambleRateCode = + rt->info[sn->rates[x].rix].rateCode | + rt->info[sn->rates[x].rix].shortPreamble; + + DPRINTF(sc, " %d/%d", sn->rates[x].rate, + calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, + 0,0)); + } + DPRINTF(sc, "%s\n", ""); + + /* set the visible bit-rate to the lowest one available */ + ni->ni_txrate = 0; + sn->num_rates = ni->ni_rates.rs_nrates; + + for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { + int size = bin_to_size(y); + sn->packets_sent[y] = 0; + sn->current_sample_ndx[y] = -1; + sn->last_sample_ndx[y] = 0; + + for (x = 0; x < ni->ni_rates.rs_nrates; x++) { + sn->stats[y][x].successive_failures = 0; + sn->stats[y][x].tries = 0; + sn->stats[y][x].total_packets = 0; + sn->stats[y][x].packets_acked = 0; + sn->stats[y][x].last_tx = 0; + + sn->stats[y][x].perfect_tx_time = + calc_usecs_unicast_packet(sc, size, + sn->rates[x].rix, + 0, 0); + sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time; + } } - ath_rate_ctl_reset(sc, ni); +#undef RATE +} + +static void +rate_cb(void *arg, struct ieee80211_node *ni) +{ + struct ath_softc *sc = arg; -#undef RATE + ath_rate_newassoc(sc, ATH_NODE(ni), 1); } /* @@ -538,8 +765,15 @@ { struct ieee80211com *ic = &sc->sc_ic; - if (state == IEEE80211_S_RUN) + if (state == IEEE80211_S_RUN) { + if (ic->ic_opmode != IEEE80211_M_STA) { + /* + * Sync rates for associated stations and neighbors. + */ + ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc); + } ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1); + } } static void @@ -591,7 +825,7 @@ switch (type) { case MOD_LOAD: if (bootverbose) - printf("ath_rate: \n"); + printf("ath_rate: version 1.2 \n"); return 0; case MOD_UNLOAD: return 0; @@ -606,4 +840,5 @@ }; DECLARE_MODULE(ath_rate, sample_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); MODULE_VERSION(ath_rate, 1); +MODULE_DEPEND(ath_rate, ath_hal, 1, 1, 1); /* Atheros HAL */ MODULE_DEPEND(ath_rate, wlan, 1, 1, 1); ==== //depot/projects/wifi/sys/dev/ath/ath_rate/sample/sample.h#3 (text+ko) ==== @@ -33,6 +33,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * + * $FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.h,v 1.3 2005/03/20 01:27:33 sam Exp $ */ /* @@ -58,12 +59,12 @@ struct rate_stats { - int average_tx_time; + unsigned average_tx_time; int successive_failures; int tries; int total_packets; int packets_acked; - int perfect_tx_time; /* transmit time for 0 retries */ + unsigned perfect_tx_time; /* transmit time for 0 retries */ int last_tx; }; @@ -82,9 +83,17 @@ struct rate_info rates[IEEE80211_RATE_MAXSIZE]; struct rate_stats stats[NUM_PACKET_SIZE_BINS][IEEE80211_RATE_MAXSIZE]; - int sample_num[NUM_PACKET_SIZE_BINS]; + int last_sample_ndx[NUM_PACKET_SIZE_BINS]; + + int current_sample_ndx[NUM_PACKET_SIZE_BINS]; int packets_sent[NUM_PACKET_SIZE_BINS]; + int current_rate[NUM_PACKET_SIZE_BINS]; + int packets_since_switch[NUM_PACKET_SIZE_BINS]; + unsigned jiffies_since_switch[NUM_PACKET_SIZE_BINS]; + + int packets_since_sample[NUM_PACKET_SIZE_BINS]; + unsigned sample_tt[NUM_PACKET_SIZE_BINS]; }; #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&an[1]) @@ -98,35 +107,141 @@ #define WIFI_CW_MIN 31 #define WIFI_CW_MAX 1023 +struct ar5212_desc { + /* + * tx_control_0 + */ + u_int32_t frame_len:12; + u_int32_t reserved_12_15:4; + u_int32_t xmit_power:6; + u_int32_t rts_cts_enable:1; + u_int32_t veol:1; + u_int32_t clear_dest_mask:1; + u_int32_t ant_mode_xmit:4; + u_int32_t inter_req:1; + u_int32_t encrypt_key_valid:1; + u_int32_t cts_enable:1; + + /* + * tx_control_1 + */ + u_int32_t buf_len:12; + u_int32_t more:1; + u_int32_t encrypt_key_index:7; + u_int32_t frame_type:4; + u_int32_t no_ack:1; + u_int32_t comp_proc:2; + u_int32_t comp_iv_len:2; + u_int32_t comp_icv_len:2; + u_int32_t reserved_31:1; + + /* + * tx_control_2 + */ + u_int32_t rts_duration:15; + u_int32_t duration_update_enable:1; + u_int32_t xmit_tries0:4; + u_int32_t xmit_tries1:4; + u_int32_t xmit_tries2:4; + u_int32_t xmit_tries3:4; + + /* + * tx_control_3 + */ + u_int32_t xmit_rate0:5; + u_int32_t xmit_rate1:5; + u_int32_t xmit_rate2:5; + u_int32_t xmit_rate3:5; + u_int32_t rts_cts_rate:5; + u_int32_t reserved_25_31:7; + + /* + * tx_status_0 + */ + u_int32_t frame_xmit_ok:1; + u_int32_t excessive_retries:1; + u_int32_t fifo_underrun:1; + u_int32_t filtered:1; + u_int32_t rts_fail_count:4; + u_int32_t data_fail_count:4; + u_int32_t virt_coll_count:4; + u_int32_t send_timestamp:16; + + /* + * tx_status_1 + */ + u_int32_t done:1; + u_int32_t seq_num:12; + u_int32_t ack_sig_strength:8; + u_int32_t final_ts_index:2; + u_int32_t comp_success:1; + u_int32_t xmit_antenna:1; + u_int32_t reserved_25_31_x:7; +} __packed; + /* * Calculate the transmit duration of a frame. */ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, int length, - int rix, int retries) { + int rix, int short_retries, int long_retries) { const HAL_RATE_TABLE *rt = sc->sc_currates; - /* pg 205 ieee.802.11.pdf */ unsigned t_slot = 20; unsigned t_difs = 50; unsigned t_sifs = 10; + struct ieee80211com *ic = &sc->sc_ic; int tt = 0; int x = 0; >>> TRUNCATED FOR MAIL (1000 lines) <<<