The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/athrate-sample.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: athrate-sample.c,v 1.21 2021/08/09 21:20:50 andvar Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2005 John Bicket
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer,
   12  *    without modification.
   13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   14  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   15  *    redistribution must be conditioned upon including a substantially
   16  *    similar Disclaimer requirement for further binary redistribution.
   17  * 3. Neither the names of the above-listed copyright holders nor the names
   18  *    of any contributors may be used to endorse or promote products derived
   19  *    from this software without specific prior written permission.
   20  *
   21  * Alternatively, this software may be distributed under the terms of the
   22  * GNU General Public License ("GPL") version 2 as published by the Free
   23  * Software Foundation.
   24  *
   25  * NO WARRANTY
   26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   28  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   29  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   30  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   31  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   34  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   36  * THE POSSIBILITY OF SUCH DAMAGES.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 #ifdef __FreeBSD__
   41 __FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.9 2005/07/22 16:50:17 sam Exp $");
   42 #endif
   43 #ifdef __NetBSD__
   44 __KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.21 2021/08/09 21:20:50 andvar Exp $");
   45 #endif
   46 
   47 
   48 /*
   49  * John Bicket's SampleRate control algorithm.
   50  */
   51 #ifdef _KERNEL_OPT
   52 #include "opt_inet.h"
   53 #endif
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h> 
   57 #include <sys/sysctl.h>
   58 #include <sys/kernel.h>
   59 #include <sys/errno.h>
   60 #include <sys/device.h>
   61 
   62 #include <sys/bus.h>
   63 
   64 #include <sys/socket.h>
   65  
   66 #include <net/if.h>
   67 #include <net/if_media.h>
   68 #include <net/if_arp.h>
   69 #include <net/if_ether.h>               /* XXX for ether_sprintf */
   70 
   71 #include <net80211/ieee80211_var.h>
   72 
   73 #include <net/bpf.h>
   74 
   75 #ifdef INET
   76 #include <netinet/in.h> 
   77 #endif
   78 
   79 #include "ah_desc.h"
   80 #include <dev/ic/athvar.h>
   81 #include <dev/ic/athrate-sample.h>
   82 
   83 #define SAMPLE_DEBUG
   84 #ifdef SAMPLE_DEBUG
   85 enum {
   86         ATH_DEBUG_RATE          = 0x00000010    /* rate control */
   87 };
   88 #define DPRINTF(sc, _fmt, ...) do {                             \
   89         if (sc->sc_debug & ATH_DEBUG_RATE)                      \
   90                 printf(_fmt, __VA_ARGS__);                      \
   91 } while (0)
   92 #else
   93 #define DPRINTF(sc, _fmt, ...)
   94 #endif
   95 
   96 /*
   97  * This file is an implementation of the SampleRate algorithm
   98  * in "Bit-rate Selection in Wireless Networks"
   99  * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps)
  100  *
  101  * SampleRate chooses the bit-rate it predicts will provide the most
  102  * throughput based on estimates of the expected per-packet
  103  * transmission time for each bit-rate.  SampleRate periodically sends
  104  * packets at bit-rates other than the current one to estimate when
  105  * another bit-rate will provide better performance. SampleRate
  106  * switches to another bit-rate when its estimated per-packet
  107  * transmission time becomes smaller than the current bit-rate's.
  108  * SampleRate reduces the number of bit-rates it must sample by
  109  * eliminating those that could not perform better than the one
  110  * currently being used.  SampleRate also stops probing at a bit-rate
  111  * if it experiences several successive losses.
  112  *
  113  * The difference between the algorithm in the thesis and the one in this
  114  * file is that the one in this file uses a ewma instead of a window.
  115  *
  116  * Also, this implementation tracks the average transmission time for
  117  * a few different packet sizes independently for each link.
  118  */
  119 
  120 #define STALE_FAILURE_TIMEOUT_MS 10000
  121 #define MIN_SWITCH_MS 1000
  122 
  123 static void     ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
  124 
  125 static inline int
  126 size_to_bin(int size) 
  127 {
  128         int x = 0;
  129         for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) {
  130                 if (size <= packet_size_bins[x]) {
  131                         return x;
  132                 }
  133         }
  134         return NUM_PACKET_SIZE_BINS-1;
  135 }
  136 static inline int bin_to_size(int index) {
  137         return packet_size_bins[index];
  138 }
  139 
  140 static inline int
  141 rate_to_ndx(struct sample_node *sn, int rate) {
  142         int x = 0;
  143         for (x = 0; x < sn->num_rates; x++) {
  144                 if (sn->rates[x].rate == rate) {
  145                         return x;
  146                 }      
  147         }
  148         return -1;
  149 }
  150 
  151 void
  152 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
  153 {
  154         DPRINTF(sc, "%s:\n", __func__);
  155         /* NB: assumed to be zero'd by caller */
  156 }
  157 
  158 void
  159 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
  160 {
  161         DPRINTF(sc, "%s:\n", __func__);
  162 }
  163 
  164 
  165 /*
  166  * returns the ndx with the lowest average_tx_time,
  167  * or -1 if all the average_tx_times are 0.
  168  */
  169 static inline int best_rate_ndx(struct sample_node *sn, int size_bin, 
  170                                   int require_acked_before)
  171 {
  172         int x = 0;
  173         int best_ndx = 0;
  174         int best_rate_tt = 0;
  175         for (x = 0; x < sn->num_rates; x++) {
  176                 int tt = sn->stats[size_bin][x].average_tx_time;
  177                 if (tt <= 0 || (require_acked_before && 
  178                                 !sn->stats[size_bin][x].packets_acked)) {
  179                         continue;
  180                 }
  181 
  182                 /* 9 megabits never works better than 12 */
  183                 if (sn->rates[x].rate == 18) 
  184                         continue;
  185 
  186                 /* don't use a bit-rate that has been failing */
  187                 if (sn->stats[size_bin][x].successive_failures > 3)
  188                         continue;
  189 
  190                 if (!best_rate_tt || best_rate_tt > tt) {
  191                         best_rate_tt = tt;
  192                         best_ndx = x;
  193                 }
  194         }
  195         return (best_rate_tt) ? best_ndx : -1;
  196 }
  197 
  198 /*
  199  * pick a good "random" bit-rate to sample other than the current one
  200  */
  201 static inline int
  202 pick_sample_ndx(struct sample_node *sn, int size_bin) 
  203 {
  204         int x = 0;
  205         int current_ndx = 0;
  206         unsigned current_tt = 0;
  207         
  208         current_ndx = sn->current_rate[size_bin];
  209         if (current_ndx < 0) {
  210                 /* no successes yet, send at the lowest bit-rate */
  211                 return 0;
  212         }
  213         
  214         current_tt = sn->stats[size_bin][current_ndx].average_tx_time;
  215         
  216         for (x = 0; x < sn->num_rates; x++) {
  217                 int ndx = (sn->last_sample_ndx[size_bin]+1+x) % sn->num_rates;
  218 
  219                 /* don't sample the current bit-rate */
  220                 if (ndx == current_ndx) 
  221                         continue;
  222 
  223                 /* this bit-rate is always worse than the current one */
  224                 if (sn->stats[size_bin][ndx].perfect_tx_time > current_tt) 
  225                         continue;
  226 
  227                 /* rarely sample bit-rates that fail a lot */
  228                 if (ticks - sn->stats[size_bin][ndx].last_tx < ((hz * STALE_FAILURE_TIMEOUT_MS)/1000) &&
  229                     sn->stats[size_bin][ndx].successive_failures > 3)
  230                         continue;
  231 
  232                 /* don't sample more than 2 indexes higher 
  233                  * for rates higher than 11 megabits
  234                  */
  235                 if (sn->rates[ndx].rate > 22 && ndx > current_ndx + 2)
  236                         continue;
  237 
  238                 /* 9 megabits never works better than 12 */
  239                 if (sn->rates[ndx].rate == 18) 
  240                         continue;
  241 
  242                 /* if we're using 11 megabits, only sample up to 12 megabits
  243                  */
  244                 if (sn->rates[current_ndx].rate == 22 && ndx > current_ndx + 1) 
  245                         continue;
  246 
  247                 sn->last_sample_ndx[size_bin] = ndx;
  248                 return ndx;
  249         }
  250         return current_ndx;
  251 }
  252 
  253 void
  254 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
  255                   int shortPreamble, size_t frameLen,
  256                   u_int8_t *rix, int *try0, u_int8_t *txrate)
  257 {
  258         struct sample_node *sn = ATH_NODE_SAMPLE(an);
  259         struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
  260         struct ieee80211com *ic = &sc->sc_ic;
  261         int ndx, size_bin, mrr, best_ndx, change_rates;
  262         unsigned average_tx_time;
  263 
  264         mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
  265         size_bin = size_to_bin(frameLen);
  266         best_ndx = best_rate_ndx(sn, size_bin, !mrr);
  267 
  268         if (best_ndx >= 0) {
  269                 average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time;
  270         } else {
  271                 average_tx_time = 0;
  272         }
  273         
  274         if (sn->static_rate_ndx != -1) {
  275                 ndx = sn->static_rate_ndx;
  276                 *try0 = ATH_TXMAXTRY;
  277         } else {
  278                 *try0 = mrr ? 2 : ATH_TXMAXTRY;
  279                 
  280                 if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100)) {
  281                         /*
  282                          * we want to limit the time measuring the performance
  283                          * of other bit-rates to ath_sample_rate% of the
  284                          * total transmission time.
  285                          */
  286                         ndx = pick_sample_ndx(sn, size_bin);
  287                         if (ndx != sn->current_rate[size_bin]) {
  288                                 sn->current_sample_ndx[size_bin] = ndx;
  289                         } else {
  290                                 sn->current_sample_ndx[size_bin] = -1;
  291                         }
  292                         sn->packets_since_sample[size_bin] = 0;
  293 
  294                 } else {
  295                         change_rates = 0;
  296                         if (!sn->packets_sent[size_bin] || best_ndx == -1) {
  297                                 /* no packet has been sent successfully yet */
  298                                 for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
  299                                         /* 
  300                                          * pick the highest rate <= 36 Mbps
  301                                          * that hasn't failed.
  302                                          */
  303                                         if (sn->rates[ndx].rate <= 72 && 
  304                                             sn->stats[size_bin][ndx].successive_failures == 0) {
  305                                                 break;
  306                                         }
  307                                 }
  308                                 change_rates = 1;
  309                                 best_ndx = ndx;
  310                         } else if (sn->packets_sent[size_bin] < 20) {
  311                                 /* let the bit-rate switch quickly during the first few packets */
  312                                 change_rates = 1;
  313                         } else if (ticks - ((hz*MIN_SWITCH_MS)/1000) > sn->ticks_since_switch[size_bin]) {
  314                                 /* 2 seconds have gone by */
  315                                 change_rates = 1;
  316                         } else if (average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time) {
  317                                 /* the current bit-rate is twice as slow as the best one */
  318                                 change_rates = 1;
  319                         }
  320 
  321                         sn->packets_since_sample[size_bin]++;
  322                         
  323                         if (change_rates) {
  324                                 if (best_ndx != sn->current_rate[size_bin]) {
  325                                         DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
  326                                                 __func__,
  327                                                 ether_sprintf(an->an_node.ni_macaddr),
  328                                                 packet_size_bins[size_bin],
  329                                                 sn->rates[sn->current_rate[size_bin]].rate,
  330                                                 sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
  331                                                 sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
  332                                                 sn->rates[best_ndx].rate,
  333                                                 sn->stats[size_bin][best_ndx].average_tx_time,
  334                                                 sn->stats[size_bin][best_ndx].perfect_tx_time,
  335                                                 sn->packets_since_switch[size_bin],
  336                                                 mrr);
  337                                 }
  338                                 sn->packets_since_switch[size_bin] = 0;
  339                                 sn->current_rate[size_bin] = best_ndx;
  340                                 sn->ticks_since_switch[size_bin] = ticks;
  341                         }
  342                         ndx = sn->current_rate[size_bin];
  343                         sn->packets_since_switch[size_bin]++;
  344                         if (size_bin == 0) {
  345                                 /* 
  346                                  * set the visible txrate for this node
  347                                  * to the rate of small packets
  348                                  */
  349                                 an->an_node.ni_txrate = ndx;
  350                         }
  351                 }
  352         }
  353 
  354         KASSERTMSG(ndx >= 0 && ndx < sn->num_rates, "ndx is %d", ndx);
  355 
  356         *rix = sn->rates[ndx].rix;
  357         if (shortPreamble) {
  358                 *txrate = sn->rates[ndx].shortPreambleRateCode;
  359         } else {
  360                 *txrate = sn->rates[ndx].rateCode;
  361         }
  362         sn->packets_sent[size_bin]++;
  363 }
  364 
  365 void
  366 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
  367     struct ath_desc *ds, int shortPreamble, u_int8_t rix)
  368 {
  369         struct sample_node *sn = ATH_NODE_SAMPLE(an);
  370         int rateCode = -1;
  371         int frame_size = 0;
  372         int size_bin = 0;
  373         int ndx = 0;
  374 
  375         size_bin = size_to_bin(frame_size);     // TODO: it's correct that frame_size always 0 ?
  376         ndx = sn->current_rate[size_bin]; /* retry at the current bit-rate */
  377         
  378         if (!sn->stats[size_bin][ndx].packets_acked) {
  379                 ndx = 0;  /* use the lowest bit-rate */
  380         }
  381 
  382         if (shortPreamble) {
  383                 rateCode = sn->rates[ndx].shortPreambleRateCode;
  384         } else {
  385                 rateCode = sn->rates[ndx].rateCode;
  386         }
  387         ath_hal_setupxtxdesc(sc->sc_ah, ds
  388                              , rateCode, 3              /* series 1 */
  389                              , sn->rates[0].rateCode, 3 /* series 2 */
  390                              , 0, 0                     /* series 3 */
  391                              );
  392 }
  393 
  394 static void
  395 update_stats(struct ath_softc *sc, struct ath_node *an, 
  396                   int frame_size,
  397                   int ndx0, int tries0,
  398                   int ndx1, int tries1,
  399                   int ndx2, int tries2,
  400                   int ndx3, int tries3,
  401                   int short_tries, int tries, int status)
  402 {
  403         struct sample_node *sn = ATH_NODE_SAMPLE(an);
  404         struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
  405         int tt = 0;
  406         int tries_so_far = 0;
  407         int size_bin;
  408         int size;
  409         int rate;
  410 
  411         if (ndx0 == -1)
  412                 return;
  413 
  414         size_bin = size_to_bin(frame_size);
  415         size = bin_to_size(size_bin);
  416         rate = sn->rates[ndx0].rate;
  417 
  418         tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix,
  419             short_tries - 1, MIN(tries0, tries) - 1);
  420         tries_so_far += tries0;
  421         if (tries1 && tries0 < tries) {
  422                 tt += calc_usecs_unicast_packet(sc, size,
  423                     ndx1 == -1 ? 0 : sn->rates[ndx1].rix, short_tries - 1, 
  424                     MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
  425         }
  426         tries_so_far += tries1;
  427 
  428         if (tries2 && tries0 + tries1 < tries) {
  429                 tt += calc_usecs_unicast_packet(sc, size,
  430                     ndx2 == -1 ? 0 : sn->rates[ndx2].rix, short_tries - 1, 
  431                     MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
  432         }
  433 
  434         tries_so_far += tries2;
  435 
  436         if (tries3 && tries0 + tries1 + tries2 < tries) {
  437                 tt += calc_usecs_unicast_packet(sc, size,
  438                     ndx3 == -1 ? 0 : sn->rates[ndx3].rix, short_tries - 1, 
  439                     MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
  440         }
  441 
  442         if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
  443                 /* just average the first few packets */
  444                 int avg_tx = sn->stats[size_bin][ndx0].average_tx_time;
  445                 int packets = sn->stats[size_bin][ndx0].total_packets;
  446                 sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1);
  447         } else {
  448                 /* use a ewma */
  449                 sn->stats[size_bin][ndx0].average_tx_time = 
  450                         ((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) + 
  451                          (tt * (100 - ssc->ath_smoothing_rate))) / 100;
  452         }
  453         
  454         if (status) {
  455                 int y;
  456                 sn->stats[size_bin][ndx0].successive_failures++;
  457                 for (y = size_bin+1; y < NUM_PACKET_SIZE_BINS; y++) {
  458                         /* also say larger packets failed since we
  459                          * assume if a small packet fails at a lower
  460                          * bit-rate then a larger one will also.
  461                          */
  462                         sn->stats[y][ndx0].successive_failures++;
  463                         sn->stats[y][ndx0].last_tx = ticks;
  464                         sn->stats[y][ndx0].tries += tries;
  465                         sn->stats[y][ndx0].total_packets++;
  466                 }
  467         } else {
  468                 sn->stats[size_bin][ndx0].packets_acked++;
  469                 sn->stats[size_bin][ndx0].successive_failures = 0;
  470         }
  471         sn->stats[size_bin][ndx0].tries += tries;
  472         sn->stats[size_bin][ndx0].last_tx = ticks;
  473         sn->stats[size_bin][ndx0].total_packets++;
  474 
  475 
  476         if (ndx0 == sn->current_sample_ndx[size_bin]) {
  477                 DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n", 
  478                         __func__, ether_sprintf(an->an_node.ni_macaddr), 
  479                         size, rate, short_tries, tries, tt, 
  480                         sn->stats[size_bin][ndx0].average_tx_time,
  481                         sn->stats[size_bin][ndx0].perfect_tx_time,
  482                         status);
  483                 sn->sample_tt[size_bin] = tt;
  484                 sn->current_sample_ndx[size_bin] = -1;
  485         }
  486 }
  487 
  488 void
  489 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
  490         const struct ath_desc *ds, const struct ath_desc *ds0)
  491 {
  492         struct ieee80211com *ic = &sc->sc_ic;
  493         struct sample_node *sn = ATH_NODE_SAMPLE(an);
  494         const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
  495         int final_rate, short_tries, long_tries, frame_size;
  496         int ndx = -1;
  497         int mrr;
  498 
  499         final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
  500         short_tries = ds->ds_txstat.ts_shortretry + 1;
  501         long_tries = ds->ds_txstat.ts_longretry + 1;
  502         frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
  503         if (frame_size == 0)                /* NB: should not happen */
  504                 frame_size = 1500;
  505 
  506         if (sn->num_rates <= 0) {
  507                 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
  508                         "no rates yet\n", 
  509                         __func__, ether_sprintf(an->an_node.ni_macaddr),
  510                         bin_to_size(size_to_bin(frame_size)),
  511                         ds->ds_txstat.ts_status,
  512                         short_tries, long_tries);
  513                 return;
  514         }
  515 
  516         mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
  517 
  518         if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
  519                 /* this packet failed */
  520                 DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", 
  521                         __func__,
  522                         ether_sprintf(an->an_node.ni_macaddr),
  523                         bin_to_size(size_to_bin(frame_size)),
  524                         sc->sc_hwmap[ads->xmit_rate0].ieeerate,
  525                                 ads->xmit_tries0,
  526                         sc->sc_hwmap[ads->xmit_rate1].ieeerate,
  527                                 ads->xmit_tries1,
  528                         sc->sc_hwmap[ads->xmit_rate2].ieeerate,
  529                                 ads->xmit_tries2,
  530                         sc->sc_hwmap[ads->xmit_rate3].ieeerate,
  531                                 ads->xmit_tries3,
  532                         ds->ds_txstat.ts_status ? "FAIL" : "OK",
  533                         short_tries, 
  534                         long_tries);
  535         }
  536 
  537         if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
  538                 /* only one rate was used */
  539                 ndx = rate_to_ndx(sn, final_rate);
  540                 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n", 
  541                         __func__, ether_sprintf(an->an_node.ni_macaddr),
  542                         bin_to_size(size_to_bin(frame_size)),
  543                         ds->ds_txstat.ts_status,
  544                         ndx, short_tries, long_tries);
  545                 if (ndx >= 0 && ndx < sn->num_rates) {
  546                         update_stats(sc, an, frame_size, 
  547                                      ndx, long_tries,
  548                                      0, 0,
  549                                      0, 0,
  550                                      0, 0,
  551                                      short_tries, long_tries, ds->ds_txstat.ts_status);
  552                 }
  553         } else {
  554                 int rate0, tries0, ndx0;
  555                 int rate1, tries1, ndx1;
  556                 int rate2, tries2, ndx2;
  557                 int rate3, tries3, ndx3;
  558                 int finalTSIdx = ads->final_ts_index;
  559 
  560                 /*
  561                  * Process intermediate rates that failed.
  562                  */
  563 
  564                 rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
  565                 tries0 = ads->xmit_tries0;
  566                 ndx0 = rate_to_ndx(sn, rate0);
  567                 
  568                 rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
  569                 tries1 = ads->xmit_tries1;
  570                 ndx1 = rate_to_ndx(sn, rate1);
  571                 
  572                 rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
  573                 tries2 = ads->xmit_tries2;
  574                 ndx2 = rate_to_ndx(sn, rate2);
  575                 
  576                 rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
  577                 tries3 = ads->xmit_tries3;
  578                 ndx3 = rate_to_ndx(sn, rate3);
  579                 
  580 #if 1
  581                 DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", 
  582                         __func__, ether_sprintf(an->an_node.ni_macaddr),
  583                         bin_to_size(size_to_bin(frame_size)),
  584                         finalTSIdx,
  585                         long_tries, 
  586                         ds->ds_txstat.ts_status,
  587                         rate0, tries0,
  588                         rate1, tries1,
  589                         rate2, tries2,
  590                         rate3, tries3);
  591 #endif
  592 
  593                 if (tries0) {
  594                         update_stats(sc, an, frame_size, 
  595                                      ndx0, tries0, 
  596                                      ndx1, tries1, 
  597                                      ndx2, tries2, 
  598                                      ndx3, tries3, 
  599                                      short_tries, ds->ds_txstat.ts_longretry + 1, 
  600                                      long_tries > tries0);
  601                 }
  602                 
  603                 if (tries1 && finalTSIdx > 0) {
  604                         update_stats(sc, an, frame_size, 
  605                                      ndx1, tries1, 
  606                                      ndx2, tries2, 
  607                                      ndx3, tries3, 
  608                                      0, 0, 
  609                                      short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, 
  610                                      ds->ds_txstat.ts_status);
  611                 }
  612 
  613                 if (tries2 && finalTSIdx > 1) {
  614                         update_stats(sc, an, frame_size, 
  615                                      ndx2, tries2, 
  616                                      ndx3, tries3, 
  617                                      0, 0,
  618                                      0, 0,
  619                                      short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, 
  620                                      ds->ds_txstat.ts_status);
  621                 }
  622 
  623                 if (tries3 && finalTSIdx > 2) {
  624                         update_stats(sc, an, frame_size, 
  625                                      ndx3, tries3, 
  626                                      0, 0,
  627                                      0, 0,
  628                                      0, 0,
  629                                      short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, 
  630                                      ds->ds_txstat.ts_status);
  631                 }
  632         }
  633 }
  634 
  635 void
  636 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
  637 {
  638         DPRINTF(sc, "%s: %s isnew %d\n", __func__,
  639                 ether_sprintf(an->an_node.ni_macaddr), isnew);
  640         if (isnew)
  641                 ath_rate_ctl_reset(sc, &an->an_node);
  642 }
  643 
  644 /*
  645  * Initialize the tables for a node.
  646  */
  647 static void
  648 ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
  649 {
  650 #define RATE(_ix)       (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
  651         struct ieee80211com *ic = &sc->sc_ic;
  652         struct ath_node *an = ATH_NODE(ni);
  653         struct sample_node *sn = ATH_NODE_SAMPLE(an);
  654         const HAL_RATE_TABLE *rt = sc->sc_currates;
  655         int x, y, srate;
  656 
  657         KASSERTMSG(rt != NULL, "no rate table, mode %u", sc->sc_curmode);
  658         sn->static_rate_ndx = -1;
  659         if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
  660                 /*
  661                  * A fixed rate is to be used; ic_fixed_rate is an
  662                  * index into the supported rate set.  Convert this
  663                  * to the index into the negotiated rate set for
  664                  * the node.  We know the rate is there because the
  665                  * rate set is checked when the station associates.
  666                  */
  667                 const struct ieee80211_rateset *rs =
  668                         &ic->ic_sup_rates[ic->ic_curmode];
  669                 int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
  670                 /* NB: the rate set is assumed sorted */
  671                 srate = ni->ni_rates.rs_nrates - 1;
  672                 for (; srate >= 0 && RATE(srate) != r; srate--)
  673                         ;
  674                 KASSERTMSG(srate >= 0,
  675                         "fixed rate %d not in rate set", ic->ic_fixed_rate);
  676                 sn->static_rate_ndx = srate;
  677         }
  678 
  679         DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
  680 
  681         sn->num_rates = ni->ni_rates.rs_nrates;
  682         for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
  683                 sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
  684                 sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
  685                 sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
  686                 sn->rates[x].shortPreambleRateCode = 
  687                         rt->info[sn->rates[x].rix].rateCode | 
  688                         rt->info[sn->rates[x].rix].shortPreamble;
  689 
  690                 DPRINTF(sc, " %d/%d", sn->rates[x].rate,
  691                         calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 
  692                                                   0,0));
  693         }
  694         DPRINTF(sc, "%s\n", "");
  695         
  696         /* set the visible bit-rate to the lowest one available */
  697         ni->ni_txrate = 0;
  698         sn->num_rates = ni->ni_rates.rs_nrates;
  699         
  700         for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
  701                 int size = bin_to_size(y);
  702                 int ndx = 0;
  703                 sn->packets_sent[y] = 0;
  704                 sn->current_sample_ndx[y] = -1;
  705                 sn->last_sample_ndx[y] = 0;
  706                 
  707                 for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
  708                         sn->stats[y][x].successive_failures = 0;
  709                         sn->stats[y][x].tries = 0;
  710                         sn->stats[y][x].total_packets = 0;
  711                         sn->stats[y][x].packets_acked = 0;
  712                         sn->stats[y][x].last_tx = 0;
  713                         
  714                         sn->stats[y][x].perfect_tx_time = 
  715                                 calc_usecs_unicast_packet(sc, size, 
  716                                                           sn->rates[x].rix,
  717                                                           0, 0);
  718                         sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
  719                 }
  720 
  721                 /* set the initial rate */
  722                 for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
  723                         if (sn->rates[ndx].rate <= 72) {
  724                                 break;
  725                         }
  726                 }
  727                 sn->current_rate[y] = ndx;
  728         }
  729 
  730         DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
  731                 __func__, ether_sprintf(ni->ni_macaddr), 
  732                 sn->num_rates,
  733                 sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
  734                 sn->stats[1][0].perfect_tx_time,
  735                 sn->rates[sn->num_rates-1].rate/2,
  736                         sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
  737                 sn->stats[1][sn->num_rates-1].perfect_tx_time
  738         );
  739 
  740         ni->ni_txrate = sn->current_rate[0];
  741 #undef RATE
  742 }
  743 
  744 static void
  745 rate_cb(void *arg, struct ieee80211_node *ni)
  746 {
  747         struct ath_softc *sc = arg;
  748 
  749         ath_rate_newassoc(sc, ATH_NODE(ni), 1);
  750 }
  751 
  752 /*
  753  * Reset the rate control state for each 802.11 state transition.
  754  */
  755 void
  756 ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
  757 {
  758         struct ieee80211com *ic = &sc->sc_ic;
  759 
  760         if (state == IEEE80211_S_RUN) {
  761                 if (ic->ic_opmode != IEEE80211_M_STA) {
  762                         /*
  763                          * Sync rates for associated stations and neighbors.
  764                          */
  765                         ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc);
  766                 }
  767                 ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
  768         }
  769 }
  770 
  771 static void
  772 ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc)
  773 {
  774         int rc;
  775         struct sysctllog **log = &sc->sc_sysctllog;
  776         const struct sysctlnode *cnode, *rnode;
  777 
  778         if ((rnode = ath_sysctl_instance(device_xname(sc->sc_dev), log)) == NULL)
  779                 return;
  780 
  781         /* XXX bounds check [0..100] */
  782         if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, smoothing_rate,
  783             "rate control: retry threshold to credit rate raise (%%)")) != 0)
  784                 goto err;
  785 
  786         /* XXX bounds check [2..100] */
  787         if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, sample_rate,
  788             "rate control: # good periods before raising rate")) != 0)
  789                 goto err;
  790 
  791         return;
  792 err:
  793         printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
  794 }
  795 
  796 struct ath_ratectrl *
  797 ath_rate_attach(struct ath_softc *sc)
  798 {
  799         struct sample_softc *osc;
  800         
  801         DPRINTF(sc, "%s:\n", __func__);
  802         osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_WAITOK|M_ZERO);
  803         osc->arc.arc_space = sizeof(struct sample_node);
  804         osc->ath_smoothing_rate = 95;   /* ewma percentage (out of 100) */
  805         osc->ath_sample_rate = 10;      /* send a different bit-rate 1/X packets */
  806         ath_rate_sysctlattach(sc, osc);
  807         return &osc->arc;
  808 }
  809 
  810 void
  811 ath_rate_detach(struct ath_ratectrl *arc)
  812 {
  813         struct sample_softc *osc = (struct sample_softc *) arc;
  814         
  815         free(osc, M_DEVBUF);
  816 }

Cache object: 4af9094d0f4c25ae0acbdd43ff7292c6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.