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/ath/ath_rate/amrr/amrr.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 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 2004 INRIA
    5  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer,
   13  *    without modification.
   14  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   15  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   16  *    redistribution must be conditioned upon including a substantially
   17  *    similar Disclaimer requirement for further binary redistribution.
   18  * 3. Neither the names of the above-listed copyright holders nor the names
   19  *    of any contributors may be used to endorse or promote products derived
   20  *    from this software without specific prior written permission.
   21  *
   22  * Alternatively, this software may be distributed under the terms of the
   23  * GNU General Public License ("GPL") version 2 as published by the Free
   24  * Software Foundation.
   25  *
   26  * NO WARRANTY
   27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   29  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   30  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   31  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   32  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   35  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   37  * THE POSSIBILITY OF SUCH DAMAGES.
   38  *
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD$");
   43 
   44 /*
   45  * AMRR rate control. See:
   46  * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
   47  * "IEEE 802.11 Rate Adaptation: A Practical Approach" by
   48  *    Mathieu Lacage, Hossein Manshaei, Thierry Turletti
   49  */
   50 #include "opt_ath.h"
   51 #include "opt_inet.h"
   52 #include "opt_wlan.h"
   53 
   54 #include <sys/param.h>
   55 #include <sys/systm.h> 
   56 #include <sys/sysctl.h>
   57 #include <sys/kernel.h>
   58 #include <sys/lock.h>
   59 #include <sys/mutex.h>
   60 #include <sys/errno.h>
   61 
   62 #include <machine/bus.h>
   63 #include <machine/resource.h>
   64 #include <sys/bus.h>
   65 
   66 #include <sys/socket.h>
   67 
   68 #include <net/if.h>
   69 #include <net/if_media.h>
   70 #include <net/if_arp.h>
   71 
   72 #include <net80211/ieee80211_var.h>
   73 
   74 #include <net/bpf.h>
   75 
   76 #ifdef INET
   77 #include <netinet/in.h> 
   78 #include <netinet/if_ether.h>
   79 #endif
   80 
   81 #include <dev/ath/if_athvar.h>
   82 #include <dev/ath/ath_rate/amrr/amrr.h>
   83 #include <dev/ath/ath_hal/ah_desc.h>
   84 
   85 static  int ath_rateinterval = 1000;            /* rate ctl interval (ms)  */
   86 static  int ath_rate_max_success_threshold = 10;
   87 static  int ath_rate_min_success_threshold = 1;
   88 
   89 static void     ath_rate_update(struct ath_softc *, struct ieee80211_node *,
   90                         int rate);
   91 static void     ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *);
   92 static void     ath_rate_ctl(void *, struct ieee80211_node *);
   93 
   94 void
   95 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
   96 {
   97         /* NB: assumed to be zero'd by caller */
   98 }
   99 
  100 void
  101 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
  102 {
  103 }
  104 
  105 void
  106 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
  107         int shortPreamble, size_t frameLen, int tid, int is_aggr,
  108         u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur,
  109         int *maxpktlen)
  110 {
  111         struct amrr_node *amn = ATH_NODE_AMRR(an);
  112 
  113         *rix = amn->amn_tx_rix0;
  114         *try0 = amn->amn_tx_try0;
  115         if (shortPreamble)
  116                 *txrate = amn->amn_tx_rate0sp;
  117         else
  118                 *txrate = amn->amn_tx_rate0;
  119         maxdur = -1;
  120         maxpktlen = -1;
  121 }
  122 
  123 /*
  124  * Get the TX rates.
  125  *
  126  * The short preamble bits aren't set here; the caller should augment
  127  * the returned rate with the relevant preamble rate flag.
  128  */
  129 void
  130 ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
  131     uint8_t rix0, int is_aggr, struct ath_rc_series *rc)
  132 {
  133         struct amrr_node *amn = ATH_NODE_AMRR(an);
  134 
  135         rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
  136 
  137         rc[0].rix = amn->amn_tx_rate0;
  138         rc[1].rix = amn->amn_tx_rate1;
  139         rc[2].rix = amn->amn_tx_rate2;
  140         rc[3].rix = amn->amn_tx_rate3;
  141 
  142         rc[0].tries = amn->amn_tx_try0;
  143         rc[1].tries = amn->amn_tx_try1;
  144         rc[2].tries = amn->amn_tx_try2;
  145         rc[3].tries = amn->amn_tx_try3;
  146 }
  147 
  148 void
  149 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
  150         struct ath_desc *ds, int shortPreamble, u_int8_t rix)
  151 {
  152         struct amrr_node *amn = ATH_NODE_AMRR(an);
  153 
  154         ath_hal_setupxtxdesc(sc->sc_ah, ds
  155                 , amn->amn_tx_rate1sp, amn->amn_tx_try1 /* series 1 */
  156                 , amn->amn_tx_rate2sp, amn->amn_tx_try2 /* series 2 */
  157                 , amn->amn_tx_rate3sp, amn->amn_tx_try3 /* series 3 */
  158         );
  159 }
  160 
  161 void
  162 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
  163         const struct ath_rc_series *rc, const struct ath_tx_status *ts,
  164         int frame_size, int rc_framesize, int nframes, int nbad)
  165 {
  166         struct amrr_node *amn = ATH_NODE_AMRR(an);
  167         int sr = ts->ts_shortretry;
  168         int lr = ts->ts_longretry;
  169         int retry_count = sr + lr;
  170 
  171         amn->amn_tx_try0_cnt++;
  172         if (retry_count == 1) {
  173                 amn->amn_tx_try1_cnt++;
  174         } else if (retry_count == 2) {
  175                 amn->amn_tx_try1_cnt++;
  176                 amn->amn_tx_try2_cnt++;
  177         } else if (retry_count == 3) {
  178                 amn->amn_tx_try1_cnt++;
  179                 amn->amn_tx_try2_cnt++;
  180                 amn->amn_tx_try3_cnt++;
  181         } else if (retry_count > 3) {
  182                 amn->amn_tx_try1_cnt++;
  183                 amn->amn_tx_try2_cnt++;
  184                 amn->amn_tx_try3_cnt++;
  185                 amn->amn_tx_failure_cnt++;
  186         }
  187         if (amn->amn_interval != 0 &&
  188             ticks - amn->amn_ticks > amn->amn_interval) {
  189                 ath_rate_ctl(sc, &an->an_node);
  190                 amn->amn_ticks = ticks;
  191         }
  192 }
  193 
  194 void
  195 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
  196 {
  197         if (isnew)
  198                 ath_rate_ctl_start(sc, &an->an_node);
  199 }
  200 
  201 void
  202 ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
  203 {
  204 }
  205 
  206 static void 
  207 node_reset(struct amrr_node *amn)
  208 {
  209         amn->amn_tx_try0_cnt = 0;
  210         amn->amn_tx_try1_cnt = 0;
  211         amn->amn_tx_try2_cnt = 0;
  212         amn->amn_tx_try3_cnt = 0;
  213         amn->amn_tx_failure_cnt = 0;
  214         amn->amn_success = 0;
  215         amn->amn_recovery = 0;
  216         amn->amn_success_threshold = ath_rate_min_success_threshold;
  217 }
  218 
  219 /**
  220  * The code below assumes that we are dealing with hardware multi rate retry
  221  * I have no idea what will happen if you try to use this module with another
  222  * type of hardware. Your machine might catch fire or it might work with
  223  * horrible performance...
  224  */
  225 static void
  226 ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
  227 {
  228         struct ath_node *an = ATH_NODE(ni);
  229         struct amrr_node *amn = ATH_NODE_AMRR(an);
  230         struct ieee80211vap *vap = ni->ni_vap;
  231         const HAL_RATE_TABLE *rt = sc->sc_currates;
  232         u_int8_t rix;
  233 
  234         KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
  235 
  236         IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
  237             "%s: set xmit rate to %dM", __func__, 
  238             ni->ni_rates.rs_nrates > 0 ?
  239                 (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
  240 
  241         amn->amn_rix = rate;
  242         /*
  243          * Before associating a node has no rate set setup
  244          * so we can't calculate any transmit codes to use.
  245          * This is ok since we should never be sending anything
  246          * but management frames and those always go at the
  247          * lowest hardware rate.
  248          */
  249         if (ni->ni_rates.rs_nrates > 0) {
  250                 ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL;
  251                 amn->amn_tx_rix0 = sc->sc_rixmap[ni->ni_txrate];
  252                 amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode;
  253                 amn->amn_tx_rate0sp = amn->amn_tx_rate0 |
  254                         rt->info[amn->amn_tx_rix0].shortPreamble;
  255                 if (sc->sc_mrretry) {
  256                         amn->amn_tx_try0 = 1;
  257                         amn->amn_tx_try1 = 1;
  258                         amn->amn_tx_try2 = 1;
  259                         amn->amn_tx_try3 = 1;
  260                         if (--rate >= 0) {
  261                                 rix = sc->sc_rixmap[
  262                                                     ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
  263                                 amn->amn_tx_rate1 = rt->info[rix].rateCode;
  264                                 amn->amn_tx_rate1sp = amn->amn_tx_rate1 |
  265                                         rt->info[rix].shortPreamble;
  266                         } else {
  267                                 amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
  268                         }
  269                         if (--rate >= 0) {
  270                                 rix = sc->sc_rixmap[
  271                                                     ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
  272                                 amn->amn_tx_rate2 = rt->info[rix].rateCode;
  273                                 amn->amn_tx_rate2sp = amn->amn_tx_rate2 |
  274                                         rt->info[rix].shortPreamble;
  275                         } else {
  276                                 amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
  277                         }
  278                         if (rate > 0) {
  279                                 /* NB: only do this if we didn't already do it above */
  280                                 amn->amn_tx_rate3 = rt->info[0].rateCode;
  281                                 amn->amn_tx_rate3sp =
  282                                         amn->amn_tx_rate3 | rt->info[0].shortPreamble;
  283                         } else {
  284                                 amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
  285                         }
  286                 } else {
  287                         amn->amn_tx_try0 = ATH_TXMAXTRY;
  288                         /* theorically, these statements are useless because
  289                          *  the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY
  290                          */
  291                         amn->amn_tx_try1 = 0;
  292                         amn->amn_tx_try2 = 0;
  293                         amn->amn_tx_try3 = 0;
  294                         amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
  295                         amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
  296                         amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
  297                 }
  298         }
  299         node_reset(amn);
  300 
  301         amn->amn_interval = ath_rateinterval;
  302         if (vap->iv_opmode == IEEE80211_M_STA)
  303                 amn->amn_interval /= 2;
  304         amn->amn_interval = (amn->amn_interval * hz) / 1000;
  305 }
  306 
  307 /*
  308  * Set the starting transmit rate for a node.
  309  */
  310 static void
  311 ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni)
  312 {
  313 #define RATE(_ix)       (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
  314         const struct ieee80211_txparam *tp = ni->ni_txparms;
  315         int srate;
  316 
  317         KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
  318         if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
  319                 /*
  320                  * No fixed rate is requested. For 11b start with
  321                  * the highest negotiated rate; otherwise, for 11g
  322                  * and 11a, we start "in the middle" at 24Mb or 36Mb.
  323                  */
  324                 srate = ni->ni_rates.rs_nrates - 1;
  325                 if (sc->sc_curmode != IEEE80211_MODE_11B) {
  326                         /*
  327                          * Scan the negotiated rate set to find the
  328                          * closest rate.
  329                          */
  330                         /* NB: the rate set is assumed sorted */
  331                         for (; srate >= 0 && RATE(srate) > 72; srate--)
  332                                 ;
  333                 }
  334         } else {
  335                 /*
  336                  * A fixed rate is to be used; ic_fixed_rate is the
  337                  * IEEE code for this rate (sans basic bit).  Convert this
  338                  * to the index into the negotiated rate set for
  339                  * the node.  We know the rate is there because the
  340                  * rate set is checked when the station associates.
  341                  */
  342                 /* NB: the rate set is assumed sorted */
  343                 srate = ni->ni_rates.rs_nrates - 1;
  344                 for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--)
  345                         ;
  346         }
  347         /*
  348          * The selected rate may not be available due to races
  349          * and mode settings.  Also orphaned nodes created in
  350          * adhoc mode may not have any rate set so this lookup
  351          * can fail.  This is not fatal.
  352          */
  353         ath_rate_update(sc, ni, srate < 0 ? 0 : srate);
  354 #undef RATE
  355 }
  356 
  357 /* 
  358  * Examine and potentially adjust the transmit rate.
  359  */
  360 static void
  361 ath_rate_ctl(void *arg, struct ieee80211_node *ni)
  362 {
  363         struct ath_softc *sc = arg;
  364         struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni));
  365         int rix;
  366 
  367 #define is_success(amn) \
  368 (amn->amn_tx_try1_cnt  < (amn->amn_tx_try0_cnt/10))
  369 #define is_enough(amn) \
  370 (amn->amn_tx_try0_cnt > 10)
  371 #define is_failure(amn) \
  372 (amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3))
  373 
  374         rix = amn->amn_rix;
  375   
  376         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
  377             "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d",
  378             amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt,
  379             amn->amn_tx_try3_cnt, amn->amn_success_threshold);
  380         if (is_success (amn) && is_enough (amn)) {
  381                 amn->amn_success++;
  382                 if (amn->amn_success == amn->amn_success_threshold &&
  383                     rix + 1 < ni->ni_rates.rs_nrates) {
  384                         amn->amn_recovery = 1;
  385                         amn->amn_success = 0;
  386                         rix++;
  387                         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
  388                             "increase rate to %d", rix);
  389                 } else {
  390                         amn->amn_recovery = 0;
  391                 }
  392         } else if (is_failure (amn)) {
  393                 amn->amn_success = 0;
  394                 if (rix > 0) {
  395                         if (amn->amn_recovery) {
  396                                 /* recovery failure. */
  397                                 amn->amn_success_threshold *= 2;
  398                                 amn->amn_success_threshold = min (amn->amn_success_threshold,
  399                                                                   (u_int)ath_rate_max_success_threshold);
  400                                 IEEE80211_NOTE(ni->ni_vap,
  401                                     IEEE80211_MSG_RATECTL, ni,
  402                                     "decrease rate recovery thr: %d",
  403                                     amn->amn_success_threshold);
  404                         } else {
  405                                 /* simple failure. */
  406                                 amn->amn_success_threshold = ath_rate_min_success_threshold;
  407                                 IEEE80211_NOTE(ni->ni_vap,
  408                                     IEEE80211_MSG_RATECTL, ni,
  409                                     "decrease rate normal thr: %d",
  410                                     amn->amn_success_threshold);
  411                         }
  412                         amn->amn_recovery = 0;
  413                         rix--;
  414                 } else {
  415                         amn->amn_recovery = 0;
  416                 }
  417         }
  418         if (is_enough (amn) || rix != amn->amn_rix) {
  419                 /* reset counters. */
  420                 amn->amn_tx_try0_cnt = 0;
  421                 amn->amn_tx_try1_cnt = 0;
  422                 amn->amn_tx_try2_cnt = 0;
  423                 amn->amn_tx_try3_cnt = 0;
  424                 amn->amn_tx_failure_cnt = 0;
  425         }
  426         if (rix != amn->amn_rix) {
  427                 ath_rate_update(sc, ni, rix);
  428         }
  429 }
  430 
  431 static int
  432 ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an,
  433     struct ath_rateioctl *re)
  434 {
  435 
  436         return (EINVAL);
  437 }
  438 
  439 static void
  440 ath_rate_sysctlattach(struct ath_softc *sc)
  441 {
  442         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
  443         struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
  444 
  445         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  446                 "rate_interval", CTLFLAG_RW, &ath_rateinterval, 0,
  447                 "rate control: operation interval (ms)");
  448         /* XXX bounds check values */
  449         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  450                 "max_sucess_threshold", CTLFLAG_RW,
  451                 &ath_rate_max_success_threshold, 0, "");
  452         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  453                 "min_sucess_threshold", CTLFLAG_RW,
  454                 &ath_rate_min_success_threshold, 0, "");
  455 }
  456 
  457 struct ath_ratectrl *
  458 ath_rate_attach(struct ath_softc *sc)
  459 {
  460         struct amrr_softc *asc;
  461 
  462         asc = malloc(sizeof(struct amrr_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
  463         if (asc == NULL)
  464                 return NULL;
  465         asc->arc.arc_space = sizeof(struct amrr_node);
  466         ath_rate_sysctlattach(sc);
  467 
  468         return &asc->arc;
  469 }
  470 
  471 void
  472 ath_rate_detach(struct ath_ratectrl *arc)
  473 {
  474         struct amrr_softc *asc = (struct amrr_softc *) arc;
  475 
  476         free(asc, M_DEVBUF);
  477 }

Cache object: 0d685763663b27dbe68750adbc899782


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