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

Cache object: af19a18848d997642ecf6cdf92e393bf


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