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


[ 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.