Ticket #1222: minstrel.patch

File minstrel.patch, 71.1 kB (added by mrenzmann, 5 years ago)

Patch for minstrel, originally added to #989

  • net80211/ieee80211_rate.c

    old new  
    4646#include <net80211/ieee80211_rate.h> 
    4747 
    4848static const char *module_names[] = { 
    49         [IEEE80211_RATE_AMRR] = "ath_rate_amrr", 
    50         [IEEE80211_RATE_ONOE] = "ath_rate_onoe", 
    51         [IEEE80211_RATE_SAMPLE] = "ath_rate_sample" 
     49        [IEEE80211_RATE_AMRR]     = "ath_rate_amrr", 
     50        [IEEE80211_RATE_MINSTREL] = "ath_rate_minstrel", 
     51        [IEEE80211_RATE_ONOE]     = "ath_rate_onoe", 
     52        [IEEE80211_RATE_SAMPLE]   = "ath_rate_sample" 
    5253}; 
    5354 
    5455/* 
  • net80211/ieee80211_rate.h

    old new  
    6969 
    7070enum { 
    7171        IEEE80211_RATE_AMRR, 
     72        IEEE80211_RATE_MINSTREL, 
    7273        IEEE80211_RATE_ONOE, 
    7374        IEEE80211_RATE_SAMPLE, 
    7475        IEEE80211_RATE_MAX 
  • ath_rate/Makefile

    old new  
    44 
    55TOP = $(obj)/.. 
    66 
    7 obj-y := amrr/ onoe/ sample/ 
     7obj-y := amrr/ minstrel/ onoe/ sample/ 
    88 
    99include $(TOP)/Makefile.inc 
    1010 
  • ath_rate/minstrel/minstrel.h

    old new  
     1/*- 
     2 *  And then Indranet Technologies Ltd sponsored Derek Smithies to work 
     3 * on this code. Derek Smithies (derek@indranet.co.nz) took parts of the  
     4 * adm module and pasted it into this code base.  
     5 * 
     6 * This version of John Bicket's code takes the experimental approach one 
     7 * step further. 
     8 * When in auto rate mode, packets are sent at the selected rate. 
     9 * The Hal asks for what alternative rate to use if the selected rate fails. 
     10 * We provide the alternative rate from a random selection of 1.. max rate. 
     11 * Given the probability of success, multiplied with the transmission time, 
     12 * we can determine the rate which maximises packet throughput. 
     13 * 
     14 * Different rates are used for every remote node - some nodes will work  
     15 * better on different rates. 
     16 * Every second, a timer fires, to assess the throughput at each rate with  
     17 *  each remote node. 
     18 * This timer will then determine the optimum rate for each remote node, based 
     19 * on the performance figures. 
     20 * 
     21 * This code is called minstrel, because we have taken a wandering minstrel 
     22 * apporoch. Wander aimlessly around the different rates, singing wherever  
     23 * you can. And then, look at the performacnce, and make a choice. 
     24 * 
     25 *  Enjoy.  Derek Smithies. 
     26 * 
     27 *********************************************************************** 
     28 * Copyright (c) 2005 John Bicket 
     29 * All rights reserved. 
     30 * 
     31 * Redistribution and use in source and binary forms, with or without 
     32 * modification, are permitted provided that the following conditions 
     33 * are met: 
     34 * 1. Redistributions of source code must retain the above copyright 
     35 *    notice, this list of conditions and the following disclaimer, 
     36 *    without modification. 
     37 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 
     38 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 
     39 *    redistribution must be conditioned upon including a substantially 
     40 *    similar Disclaimer requirement for further binary redistribution. 
     41 * 3. Neither the names of the above-listed copyright holders nor the names 
     42 *    of any contributors may be used to endorse or promote products derived 
     43 *    from this software without specific prior written permission. 
     44 * 
     45 * Alternatively, this software may be distributed under the terms of the 
     46 * GNU General Public License ("GPL") version 2 as published by the Free 
     47 * Software Foundation. 
     48 * 
     49 * NO WARRANTY 
     50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     52 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 
     53 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
     54 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 
     55 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
     56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
     57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
     58 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
     59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
     60 * THE POSSIBILITY OF SUCH DAMAGES. 
     61 * 
     62 * $Id: minstrel.h 1441 2006-02-06 16:03:21Z mrenzmann $ 
     63 */ 
     64 
     65/* 
     66 * Defintions for the Atheros Wireless LAN controller driver. 
     67 */ 
     68#ifndef _DEV_ATH_RATE_MINSTREL_H 
     69#define _DEV_ATH_RATE_MINSTREL_H 
     70#define MINSTREL_COLUMNS 10 
     71 
     72/* per-device state */ 
     73struct minstrel_softc { 
     74        struct ath_ratectrl arc;        /* base state */ 
     75 
     76#ifdef CONFIG_SYSCTL 
     77        struct ctl_table_header *sysctl_header; 
     78        struct ctl_table *sysctls; 
     79#endif 
     80        struct ath_softc  *sc; 
     81        struct net_device *sc_dev;  
     82 
     83 
     84        struct timer_list timer;        /* periodic timer */ 
     85        int close_timer_now; 
     86}; 
     87 
     88 
     89#define ATH_SOFTC_MINSTREL(sc)    ((struct minstrel_softc *)sc->sc_rc) 
     90 
     91struct rate_info { 
     92        int rate; 
     93        int rix; 
     94        int rateCode; 
     95        int shortPreambleRateCode; 
     96}; 
     97 
     98 
     99 
     100/* per-node state */ 
     101struct minstrel_node { 
     102        int static_rate_ndx; /*User has bypassed dynamic selection. Fix on one rate */ 
     103        int num_rates; 
     104        struct rate_info rates[IEEE80211_RATE_MAXSIZE]; 
     105         
     106        unsigned perfect_tx_time[IEEE80211_RATE_MAXSIZE];  /* transmit time for 0 retries */ 
     107        unsigned retry_count[IEEE80211_RATE_MAXSIZE];      /*The number of retrys permitted for this particular rate */ 
     108        unsigned retry_adjusted_count[IEEE80211_RATE_MAXSIZE]; /*retry_count, but altered, depending on if this is a very poor (or very good) link */ 
     109        int current_rate; 
     110 
     111        u_int32_t               rs_rateattempts[IEEE80211_RATE_MAXSIZE]; 
     112        u_int32_t               rs_thisprob    [IEEE80211_RATE_MAXSIZE]; 
     113        u_int32_t               rs_ratesuccess [IEEE80211_RATE_MAXSIZE]; 
     114        u_int32_t               rs_lastrateattempts[IEEE80211_RATE_MAXSIZE]; 
     115        u_int32_t               rs_lastratesuccess [IEEE80211_RATE_MAXSIZE]; 
     116        u_int32_t               rs_probability [IEEE80211_RATE_MAXSIZE]; /* units of parts per thousand */ 
     117        u_int64_t               rs_succ_hist   [IEEE80211_RATE_MAXSIZE];  
     118        u_int64_t               rs_att_hist    [IEEE80211_RATE_MAXSIZE];  
     119        
     120        u_int32_t               rs_this_tp     [IEEE80211_RATE_MAXSIZE]; /*Throughput, each rate */ 
     121 
     122        int                     is_sampling;  
     123 
     124        /** These four parameters are indexes into the current rate 
     125            table, and are calculated in ath_rate_statistics(), which 
     126            happens every time the timer for rate adjustment fires */ 
     127        int max_tp_rate;       /*  Has the current highest recorded throughput */ 
     128        int max_tp_rate2;      /*  Has the second highest recorded throughput */ 
     129        int max_prob_rate;     /*  This rate has the highest chance of success. */ 
     130 
     131        /**These two variables are used to keep track of what 
     132           percentage of packets have been used to do sample on.  
     133           Thus,if ath_lookaround_rate is set to 10%, we can expect that 
     134           sample_count 
     135           ------------                    = 0.1 
     136           sample_count + packet_count                           */ 
     137        int packet_count;     /*  The number of times we have   
     138                                  sent a packet to this node. */ 
     139        int sample_count;     /* The number of times we have  
     140                                 sent a sample packet to this node */ 
     141 
     142        /**The table that holds the sequence of rates that we use. In 
     143           each column in the table, the rates we sample are provided 
     144           in some "random" order. Each rate we sample occurs once in 
     145           each column. There are several columns, so we sample the 
     146           different rates in a different order each time. */ 
     147        u_int8_t              rs_sampleTable[IEEE80211_RATE_MAXSIZE][MINSTREL_COLUMNS]; 
     148        int                   rs_sampleColumn; 
     149        int                   rs_sampleIndex; 
     150 
     151       /**Random number generator is 
     152           Rn+1 = (A*Rn) + B.  
     153 
     154           This Random number generator determines when we send a minstrel 
     155           packet, or a packet at an optimal rate.*/ 
     156        int random_n; 
     157        int a, b;          /**Coefficients of the random thing */ 
     158}; 
     159 
     160 
     161#define ATH_NODE_MINSTREL(an)   ((struct minstrel_node *)&an[1]) 
     162 
     163 
     164#ifndef MIN 
     165#define MIN(a,b)        ((a) < (b) ? (a) : (b)) 
     166#endif 
     167#ifndef MAX 
     168#define MAX(a,b)        ((a) > (b) ? (a) : (b)) 
     169#endif 
     170 
     171#if 0 
     172#define WIFI_CW_MIN 31 
     173#define WIFI_CW_MAX 1023 
     174#else 
     175#define WIFI_CW_MIN 3 
     176#define WIFI_CW_MAX 10 
     177#endif 
     178 
     179struct ar5212_desc { 
     180        /* 
     181         * tx_control_0 
     182         */ 
     183        u_int32_t frame_len:12; 
     184        u_int32_t reserved_12_15:4; 
     185        u_int32_t xmit_power:6; 
     186        u_int32_t rts_cts_enable:1; 
     187        u_int32_t veol:1; 
     188        u_int32_t clear_dest_mask:1; 
     189        u_int32_t ant_mode_xmit:4; 
     190        u_int32_t inter_req:1; 
     191        u_int32_t encrypt_key_valid:1; 
     192        u_int32_t cts_enable:1; 
     193 
     194        /* 
     195         * tx_control_1 
     196         */ 
     197        u_int32_t buf_len:12; 
     198        u_int32_t more:1; 
     199        u_int32_t encrypt_key_index:7; 
     200        u_int32_t frame_type:4; 
     201        u_int32_t no_ack:1; 
     202        u_int32_t comp_proc:2; 
     203        u_int32_t comp_iv_len:2; 
     204        u_int32_t comp_icv_len:2; 
     205        u_int32_t reserved_31:1; 
     206 
     207        /* 
     208         * tx_control_2 
     209         */ 
     210        u_int32_t rts_duration:15; 
     211        u_int32_t duration_update_enable:1; 
     212        u_int32_t xmit_tries0:4; 
     213        u_int32_t xmit_tries1:4; 
     214        u_int32_t xmit_tries2:4; 
     215        u_int32_t xmit_tries3:4; 
     216 
     217        /* 
     218         * tx_control_3 
     219         */ 
     220        u_int32_t xmit_rate0:5; 
     221        u_int32_t xmit_rate1:5; 
     222        u_int32_t xmit_rate2:5; 
     223        u_int32_t xmit_rate3:5; 
     224        u_int32_t rts_cts_rate:5; 
     225        u_int32_t reserved_25_31:7; 
     226 
     227        /* 
     228         * tx_status_0 
     229         */ 
     230        u_int32_t frame_xmit_ok:1; 
     231        u_int32_t excessive_retries:1; 
     232        u_int32_t fifo_underrun:1; 
     233        u_int32_t filtered:1; 
     234        u_int32_t rts_fail_count:4; 
     235        u_int32_t data_fail_count:4; 
     236        u_int32_t virt_coll_count:4; 
     237        u_int32_t send_timestamp:16; 
     238 
     239        /* 
     240         * tx_status_1 
     241         */ 
     242        u_int32_t done:1; 
     243        u_int32_t seq_num:12; 
     244        u_int32_t ack_sig_strength:8; 
     245        u_int32_t final_ts_index:2; 
     246        u_int32_t comp_success:1; 
     247        u_int32_t xmit_antenna:1; 
     248        u_int32_t reserved_25_31_x:7; 
     249} __packed; 
     250 
     251#endif /* _DEV_ATH_RATE_MINSTEL_H */ 
     252 
     253/* The comment below is magic for those who use emacs to edit this file. */ 
     254/* With the comment below, the tab key does auto indent to 8 spaces.     */ 
     255 
     256/* 
     257 * Local Variables: 
     258 * mode:c 
     259 * c-file-style:"linux" 
     260 * c-basic-offset:8 
     261 * End: 
     262 */ 
  • ath_rate/minstrel/minstrel.txt

    old new  
     1 
     2Minstrel 
     3 
     4Introduction 
     5================================================================== 
     6This code is called minstrel, because we have taken a wandering minstrel 
     7apporoch. Wander around the different rates, singing wherever you 
     8can. And then, look at the performacnce, and make a choice. Note that the 
     9wandering minstrel will always wander in directions where he/she feels he/she 
     10will get paid the best for his/her work. 
     11 
     12The Minstrel autorate selection algorithm is an EWMA based algorithm and is 
     13derived from  
     14 1)An initial rate module we released in 2005, 
     15  http://sourceforge.net/mailarchive/forum.php?forum_id=33966&max_rows=25&style=flat&viewmonth=200501&viewday=5 
     16 
     17 2)the "sample" module in the madwifi-ng source tree.  
     18 
     19The code released in 2005 had some algorithmic and implementation 
     20flaws (one of which was that it was based on the old madwifi codebase) 
     21and was shown to be unstable. Performance of the sample module is poor 
     22(http://www.madwifi.org/ticket/989), and we have observed similar 
     23issues. 
     24 
     25We noted: 
     26 1)The rate chosen by sample did not alter to match changes in the radio 
     27    environment. 
     28 2)Higher throughput (between two nodes) could often be achieved by fixing the 
     29    bitrate of both nodes to some value. 
     30 3)After a long period of operation, "sample" appeared to be stuck in a low 
     31    data rate, and would not move to a higher data rate. 
     32 
     33We examined the code in sample, and decided the best approach was a 
     34rewrite based on sample and the module we released in January 2005. 
     35 
     36Theory of operation 
     37================================================================== 
     38 
     39We defined the measure of successfulnes (of packet transmission)  as 
     40 
     41                                  mega-bits-transmitted 
     42    Prob_success_transmission *  ---------------------- 
     43                                     elapsed time 
     44 
     45This measure of successfulness will therefore adjust the transmission speed to  
     46get the maximum number of data bits through the radio interface. Further, it 
     47means that the 1mb/sec rate (which has a very high probability of successful 
     48transmission) will not be used in preference to the 11mb/sec rate. 
     49 
     50We decided that the module should record the successfulness of all packets 
     51that are transmitted. From this data, the module has sufficient information to 
     52decide which packets are more successful than others. However, a variability 
     53element was required. We had to force the module to examine bit rates other 
     54than optimal. Consquently, some percent of the packets have to be sent at 
     55rates regarded as non optimal. 
     56 
     5710 times a second (this frequency is alterable by changing the driver code) 
     58a timer fires, which evaluates the statistics table. EWMA calculations 
     59(described below) are used to process the success history of each rate. On 
     60completion of the calculation, a decision is made as to the rate which has the 
     61best throughput, second best throughput, and  highest probability of success. 
     62This data is used for populating the retry chain during the next 100 ms. 
     63 
     64As stated above, the minstrel algorithm collects statistics from all packet 
     65attempts.  Minstrel spends a particular percentage of frames, doing "look 
     66arounds" i.e. randomly trying other rates, to gather statistics. The 
     67percentage of "look around" frames, is set at boot time via the module 
     68parameter "ath_lookaround_rate" and defaults to 10%. The distribution of 
     69lookaround frames is also randomised somewhat to avoid any potential 
     70"strobing" of lookarounds between similar nodes.  
     71 
     72TCP theory tells us that each packet sent must be delivered in under 26ms. Any 
     73longer duration, and the TCP network layers will start to back off. A delay of 
     7426ms implies that there is congestion in the network, and that fewer packets 
     75should be injected to the device. Our conclusion was to adjust the retry chain 
     76of each packet so the retry chain was guaranteed to be finished in under 26ms. 
     77 
     78 
     79Retry Chain 
     80================================================================== 
     81The HAL provides a multirate retry chain - which consists of four 
     82segments. Each segment is an advisement to the HAL to try to send the current 
     83packet at some rate, with a fixed number of retry attempts. Once the packet is 
     84successfully transmitted, the remainder of the retry chain is 
     85ignored. Selection of the number of retry attempts was based on the desire to 
     86get the packet out in under 26ms, or fail. We provided a module parameter, 
     87ath_segment_size, which has units of micoseconds, and specifies the maximum 
     88duration one segment in the retry chain can last. This module parameter has a 
     89default of 6000. Our view is that a segment size of between 4000 and 6000 
     90seems to fit most situations. 
     91 
     92There is some room for movement here - if the traffic is UDP then the limit of 
     9326ms for the retry chain length is "meaningless".  However, one may argue that 
     94if the packet was not transmitted after some time period, it should 
     95fail. Further, one does expect UDP packets to fail in transmission. We leave 
     96it as an area for future improvement. 
     97 
     98 
     99The (re)try segment chain is calculated in two possible manners. If this 
     100packet is a normal trnamission packet (90% of packets are this) then the retry 
     101count is best throughput, next best throughput, best probability, lowest 
     102baserate. If it is a sample packet (10% of packets are this), then the retry 
     103chain is random lookaround, best throughput, best probability, lowest base 
     104rate. In tabular format: 
     105 
     106        Try | lookaround rate    | Normal rate          
     107        ------------------------------------------------ 
     108         1  | Random lookaround  | Best throughput      
     109         2  | Best throughput    | Next best throughput 
     110         3  | Best probability   | Best probability     
     111         4  | Lowest Baserate    | Lowest Baserate      
     112 
     113The retry count is adjusted so that the transmission time for that section of 
     114the retry chain is less than 26 ms. 
     115 
     116After some discussion, we have adjusted the code so that the lowest rate is 
     117never used for the lookaround packet. Our view is that since this rate is used 
     118for management packets, this rate must be working. - Alternatively, the link 
     119is set up with management packets, data packets are acknowledged with 
     120management packets. Should the lowest rate stop working, the link is going to 
     121die reasonably soon. 
     122 
     123Analysis of information in the /proc/net/madwifi/athX/rate_info file 
     124showed that the system was sampling too hard at some rates. For those 
     125rates that never work (54mb, 500m range) there is no point in sending 
     12610 sample packets (<6ms time). Consequently, for the very very low 
     127probability rates, we sample at most twice. 
     128 
     129 
     130EWMA 
     131================================================================== 
     132 
     133The EWMA calculation is carried out 10 times a second, and is run for each 
     134rate. This calculation has a smoothing effect, so that new results have 
     135a reasonable (but not large) influence on the selected rate. However, with 
     136time, a series of new results in some particular direction will predominate.  
     137Given this smoothing, we can use words like inertia to describe the EWMA. 
     138 
     139By "new results", we mean the results collected in the just completed 100ms 
     140interval. Old results are the EWMA scaling values from before the just 
     141completed 100ms interval. 
     142 
     143EWMA scaling is set by the module parameter ath_ewma_level, and defaults to 
     14475%. A value of 0% means use only the new results, ignore the old results. 
     145A value of 99% means use the old results, with a tiny influence from the new 
     146results.  
     147 
     148 
     149 
     150The calculation (performed for each rate, at each timer interrupt) of the 
     151         probability of success is: 
     152 
     153         Psucces_this_time_interval * (100 - ath_ewma_level) + (Pold * ath_ewma_level) 
     154Pnew =  ------------------------------------------------------------------------------ 
     155                  100 
     156 
     157                            number_packets_sent_successfully_this_rate_time_interval 
     158Psuccess_this_time_interval=-------------------------------------------------------- 
     159                             number_packets_sent_this_rate_time_interval 
     160 
     161 
     162If no packets have been sent for a particular rate in a time interval, no 
     163calculation is carried out. The Psuccess value for this rate is not changed. 
     164 
     165If the new time interval is the first time interval (the module has just been 
     166inserted), then Pnew is calculated from above with Pold set to 0. 
     167 
     168The appropriate update interval was selected on the basis of choosing a comprimise 
     169between 
     170 *collecting enough success/failure information to be meaningful 
     171 *minimising the amount of cpu time spent do the updates 
     172 *providing a means to recover quickly enough from a bad rate selection. 
     173The first two points are self explanatory. When there is a sudden change in the radio 
     174environment, an update interval of 100ms will mean that the rates marked as optimal are 
     175very quickly marked as poor. Consequently, the sudden change in radio environment will 
     176mean that minstrel will very quickly switch to a better rate.  
     177 
     178A sudden change in the transmission probabilities will happen when the 
     179node has not transmitted any data for a while, and during that time 
     180the environment has changed. On starting to transmit, the probability 
     181of success at each rate will be quite different. The driver must adapt 
     182as quickly as possible, so as to not upset the higher TCP network 
     183layers. 
     184 
     185 
     186 
     187Module Parameters 
     188==================================================== 
     189The module has three parameters: 
     190 
     191name              default value    purpose 
     192ath_ewma_level      75%            rate of response to new data. A value of 100 is VERY responsive. 
     193ath_lookaround_rate 10%            percent of packets sent at non optimal speed. 
     194ath_segment_size   6000            maximum duration of a retry segment (microseconds) 
     195 
     196 
     197 
     198 
     199 
     200Test Network 
     201==================================================== 
     202We used three computers in our test network.  The first two, equipped with 
     203atheros cards running in adhoc mode. We used a program that sends a fixed 
     204number of TCP packets between computers, and reports on the data rate. The 
     205application reports on the data rate - at an application layer level, which is 
     206considerably lower than the level used in transmitting the packets. 
     207 
     208The third computer had an atheros card also, but was running network monitor 
     209mode with ethereal. The monitor computer was used to see what data rates were 
     210used on the air. This computer was a form of "logging of the connection" 
     211without introducing any additional load on the first two computers. 
     212 
     213It was from monitoring the results on the third computer that we started to 
     214get some confidence in the correctness of the code. We observed TCP 
     215backoffs (described above) on this box. There was much celebration when the 
     216throughput increased simply because the retry chain was finished in under 26 
     217ms. 
     218 
     219Our view was that throughput between the two computers should be as 
     220close as possible (or better than) what can be achieved by setting 
     221both ends to fixed rates. Thus, if setting the both ends to fixed 
     222rates significantly increases the throughput, a reasonable conclusion 
     223is that a fault exists in the adaptive rate rate. 
     224 
     225We recorded throughputs (with minstrel) that are within 10% of what is 
     226achieved with the experimentally determined optimum fixed rate.  
     227 
     228 
     229Notes on Timing 
     230==================================================== 
     231 
     232As noted above, Minstrel calculates the throughput for each rate. This 
     233calculation (using a packet of size 1200 bytes) determines the 
     234transmission time on the radio medium. In these calculations, we assume a 
     235contention window min and max value of 4 and 10 microseconds respectively. 
     236 
     237Further, calculation of the transmission time is required so that we can 
     238guarantee a packet is transmitted (or dropped) in a minimum time period. 
     239The transmission  time is used in determining how many times a packet 
     240is transmitted in each segment of the retry chain. 
     241 
     242Indeed, the card will supply the cwmin/cwmax values directly 
     243 iwpriv if_name get_cwmin <0|1|2|3> <0|1> 
     244 
     245We have not made direct calls to determine cwmin/cwmax - this is an area 
     246for future work. Indeed, the cwmin/cwmax determination code could check to 
     247see if the user has altered these values with the appropriate iwpriv. 
     248 
     249The contention window size does vary with traffic class. For example, 
     250video and voice have a contention window min of 3 and 2 microseconds 
     251respectively. Currently, minstrel does not check traffic class. 
     252 
     253Calculating the throughputs based on traffic class and bit rate and 
     254variable packet size will significantly complicate the code and require 
     255many more sample packets. More sample packets will lower the throughput 
     256achieved. Thus, our view is that for this release, we should take a simple 
     257(but reasonable) approach that works stably and gives good throughputs. 
     258 
     259 
     260Values of cwin/cwmax of 4 and 10 microseconds are from  
     261IEEE Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer 
     262(PHY) specifications, Amendment : Medium Access Control (MAC) Enhancements for 
     263Quality of Service (QoS) P802.11e/D12.0, November 2004. 
     264 
     265 
     266Internal variable reporting 
     267==================================================== 
     268The minstrel algorithm reports to the proc file system its internal 
     269statistics, which can be viewed as text. A sample output is below: 
     270 
     271cat /proc/net/madwifi/ath0/rate_info 
     272 
     273 
     274rate data for node:: 00:02:6f:43:8c:7a 
     275rate     throughput  ewma prob   this prob  this succ/attempt   success    attempts 
     276     1         0.0        0.0        0.0          0(  0)          0           0 
     277     2         1.6       92.4      100.0          0(  0)         11          11 
     278     5.5       3.9       89.9      100.0          0(  0)         11          11 
     279    11         6.5       86.6      100.0          0(  0)         10          11 
     280     6         4.8       92.4      100.0          0(  0)         11          11 
     281     9         6.9       92.4      100.0          0(  0)         11          11 
     282    12         9.0       92.4      100.0          0(  0)         11          11 
     283    18        12.1       89.9      100.0          0(  0)         11          11 
     284    24        15.5       92.4      100.0          0(  0)         11          11 
     285    36        20.6       92.4      100.0          0(  0)         11          11 
     286 t  48        23.6       89.9      100.0          0(  0)         12          12 
     287T P 54        27.1       96.2       96.2          0(  0)        996        1029 
     288 
     289 
     290Total packet count::    ideal 2344      lookaround 261 
     291 
     292There is a separate table for each node in the neighbor table, which will 
     293appear similar to above. 
     294 
     295The possible datarates for this node are listed in the column at the left. The 
     296calculated throughput and "ewma prob" are listed next, from which the rates 
     297used in retry chain are selected. The rates with the maximum throughput, 
     298second meximum throughput and maximum probability are indicated by the letters 
     299T, t, and P respectively. 
     300 
     301The statistics gathered in the last 100ms time period are displayed in the 
     302"this prob" and "this succ/attempt" columns. 
     303 
     304Finally, the number of packets transmitted at each rate, since module loading 
     305are listed in the last two columns. When interpreting the last four columns, 
     306note that we use the words "succ" or "success" to mean packets successfully 
     307sent from this node to the remote node. The driver determines success by 
     308analysing reports from the hal. The word "attempt" or "attempts" means the 
     309count of packets that we transmitted. Thus, the number in the success column 
     310will always be lower than the number in the attempts column.  
     311 
     312 
     313When the two nodes are brought closer together, the statistics start changing, 
     314and you see more successful attempts at the higher rates. The ewma prob at the 
     315higher rates increases and then most packets are conveyed at the higher rates. 
     316 
     317When the rate is not on auto, but fixed, this table is still 
     318available, and will report the throughput etc for the current bit 
     319rate. Changing the rate from auto to fixed to auto will completely 
     320reset this table, and the operation of the minstrel module. 
     321 
     322 
     323 
     324 
     325 
     326 
     327 
     328 
     329 
  • ath_rate/minstrel/Makefile.kernel

    old new  
     1# 
     2# Makefile for the Minstrel rate control algorithm. 
     3# 
     4# $Id: //depot/sw/linuxsrc/src/802_11/madwifi/madwifi/ath_rate/minstrel/Makefile.kernel#1 $ 
     5# 
     6 
     7src ?= . 
     8srctree ?= . 
     9 
     10TOP = $(srctree)/$(src)/../.. 
     11 
     12include $(TOP)/BuildCaps.inc 
     13 
     14ATH=    $(TOP)/ath 
     15ATH_HAL=$(TOP)/ath_hal 
     16COMPAT= $(TOP)/include 
     17HAL=    $(TOP)/hal 
     18 
     19INCS = -include $(COMPAT)/compat.h -I$(COMPAT) 
     20INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -I$(HAL) 
     21EXTRA_CFLAGS += $(INCS) $(COPTS) 
     22 
     23ifneq ($(VERSION).$(PATCHLEVEL),2.4) 
     24obj-$(CONFIG_ATHEROS) += ath_rate_minstrel.o 
     25ath_rate_minstrel-objs  := minstrel.o 
     26endif 
     27 
     28ifeq ($(VERSION).$(PATCHLEVEL),2.4) 
     29obj-$(CONFIG_ATHEROS) := minstrel.o 
     30 
     31export-objs     := minstrel.o 
     32list-multi      := ath_rate_minstrel.o 
     33 
     34O_TARGET        := ath_rate.o 
     35include $(TOPDIR)/Rules.make 
     36endif 
  • ath_rate/minstrel/Makefile

    old new  
     1# 
     2# Copyright (c) 2004 Sam Leffler, Errno Consulting 
     3# Copyright (c) 2004 Video54 Technologies, Inc. 
     4# All rights reserved. 
     5# 
     6# Redistribution and use in source and binary forms, with or without 
     7# modification, are permitted provided that the following conditions 
     8# are met: 
     9# 1. Redistributions of source code must retain the above copyright 
     10#    notice, this list of conditions and the following disclaimer, 
     11#    without modification. 
     12# 2. Redistributions in binary form must reproduce at minimum a disclaimer 
     13#    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 
     14#    redistribution must be conditioned upon including a substantially 
     15#    similar Disclaimer requirement for further binary redistribution. 
     16# 3. Neither the names of the above-listed copyright holders nor the names 
     17#    of any contributors may be used to endorse or promote products derived 
     18#    from this software without specific prior written permission. 
     19# 
     20# Alternatively, this software may be distributed under the terms of the 
     21# GNU General Public License ("GPL") version 2 as published by the Free 
     22# Software Foundation. 
     23# 
     24# NO WARRANTY 
     25# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     26# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     27# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 
     28# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
     29# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 
     30# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
     31# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
     32# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
     33# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
     34# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
     35# THE POSSIBILITY OF SUCH DAMAGES. 
     36# 
     37 
     38# 
     39# Makefile for the Atheros Rate Control Support. 
     40# 
     41ifeq ($(obj),) 
     42obj=    . 
     43endif 
     44 
     45TOP = $(obj)/../.. 
     46 
     47obj-m           += ath_rate_minstrel.o 
     48ath_rate_minstrel-objs  := minstrel.o 
     49 
     50include $(TOP)/Makefile.inc 
     51 
     52INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -I$(HAL) 
     53 
     54EXTRA_CFLAGS+= $(INCS) $(COPTS) 
     55 
     56-include $(TOPDIR)/Rules.make 
     57 
     58all: 
     59        $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules 
     60 
     61install: 
     62        test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH) 
     63        cp ath_rate_minstrel.$(KMODSUF) $(DESTDIR)/$(KMODPATH) 
     64 
     65clean: 
     66        -rm -f *~ *.o *.ko *.mod.c 
     67        -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd 
     68        -rm -rf .tmp_versions 
     69 
     70ath_rate_minstrel.o: $(ath_rate_minstrel-objs) 
     71        $(LD) $(LDOPTS) -o ath_rate_minstrel.$(KMODSUF) -r $(ath_rate_minstrel-objs) 
  • ath_rate/minstrel/minstrel.c

    old new  
     1/*- 
     2 *  And then Indranet Technologies Ltd sponsored Derek Smithies to work 
     3 * on this code. Derek Smithies (derek@indranet.co.nz) took parts of the  
     4 * adm module and pasted it into this code base.  
     5 * 
     6 * This version of John Bicket's code takes the experimental approach one 
     7 * step further. 
     8 * When in auto rate mode, packets are sent at the selected rate. 
     9 * The Hal asks for what alternative rate to use if the selected rate fails. 
     10 * We provide the alternative rate from a random selection of 1.. max rate. 
     11 * Given the probability of success, multiplied with the transmission time, 
     12 * we can determine the rate which maximises packet throughput. 
     13 * 
     14 * Different rates are used for every remote node - some nodes will work  
     15 * better on different rates. 
     16 * Every second, a timer fires, to assess the throughput at each rate with  
     17 *  each remote node. 
     18 * This timer will then determine the optimum rate for each remote node, based 
     19 * on the performance figures. 
     20 * 
     21 * This code is called minstrel, because we have taken a wandering minstrel 
     22 * apporoch. Wander around the different rates, singing wherever  
     23 * you can. And then, look at the performacnce, and make a choice. 
     24 * 
     25 * It is not an aimless search, there is some direction to the search 
     26 * pattern. But then, the minstels of old only sung where they thought 
     27 * they would get an income. Similarily, we direct thesearch a little. 
     28 * 
     29 *  Enjoy.  Derek Smithies. 
     30 * 
     31 *********************************************************************** 
     32 * Copyright (c) 2005 John Bicket 
     33 * All rights reserved. 
     34 * 
     35 * Redistribution and use in source and binary forms, with or without 
     36 * modification, are permitted provided that the following conditions 
     37 * are met: 
     38 * 1. Redistributions of source code must retain the above copyright 
     39 *    notice, this list of conditions and the following disclaimer, 
     40 *    without modification. 
     41 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 
     42 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 
     43 *    redistribution must be conditioned upon including a substantially 
     44 *    similar Disclaimer requirement for further binary redistribution. 
     45 * 3. Neither the names of the above-listed copyright holders nor the names 
     46 *    of any contributors may be used to endorse or promote products derived 
     47 *    from this software without specific prior written permission. 
     48 * 
     49 * Alternatively, this software may be distributed under the terms of the 
     50 * GNU General Public License ("GPL") version 2 as published by the Free 
     51 * Software Foundation. 
     52 * 
     53 * NO WARRANTY 
     54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     56 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 
     57 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
     58 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 
     59 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
     60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
     61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
     62 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
     63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
     64 * THE POSSIBILITY OF SUCH DAMAGES. 
     65 * 
     66 * 
     67 * $Id: minstrel.c 1525 2006-04-23 21:05:57Z dyqith $ 
     68 */ 
     69 
     70 
     71 
     72#ifndef AUTOCONF_INCLUDED 
     73#include <linux/config.h> 
     74#endif 
     75 
     76#include <linux/version.h> 
     77#include <linux/module.h> 
     78#include <linux/init.h> 
     79#include <linux/skbuff.h> 
     80#include <linux/netdevice.h> 
     81#include <linux/random.h> 
     82#include <linux/delay.h> 
     83#include <linux/cache.h> 
     84#include <linux/sysctl.h> 
     85#include <linux/proc_fs.h> 
     86#include <linux/if_arp.h> 
     87#include <linux/net.h> // for net_random 
     88#include <linux/vmalloc.h> 
     89 
     90#include <asm/uaccess.h> 
     91 
     92#include <net80211/if_media.h> 
     93#include <net80211/ieee80211_var.h> 
     94#include <net80211/ieee80211_rate.h> 
     95 
     96#include "if_athvar.h" 
     97#include "ah_desc.h" 
     98 
     99#include "minstrel.h" 
     100 
     101#define MINSTREL_DEBUG 10 
     102#ifdef MINSTREL_DEBUG 
     103enum { 
     104        ATH_DEBUG_RATE          = 0x00000010    /* rate control */ 
     105}; 
     106#define DPRINTF(sc, _fmt, ...) do {                             \ 
     107        /*      printk(_fmt, __VA_ARGS__);      */              \ 
     108} while (0) 
     109#else 
     110#define DPRINTF(sc, _fmt, ...) 
     111#endif 
     112 
     113#define ONE_SECOND (1000 * 1000)  /* 1 second, or 1000 milliseconds, eternity in other words */ 
     114/* 
     115 * This file is an implementation of the SampleRate algorithm 
     116 * in "Bit-rate Selection in Wireless Networks" 
     117 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps) 
     118 * 
     119 * SampleRate chooses the bit-rate it predicts will provide the most 
     120 * throughput based on estimates of the expected per-packet 
     121 * transmission time for each bit-rate.  SampleRate periodically sends 
     122 * packets at bit-rates other than the current one to estimate when 
     123 * another bit-rate will provide better performance. SampleRate 
     124 * switches to another bit-rate when its estimated per-packet 
     125 * transmission time becomes smaller than the current bit-rate's. 
     126 * SampleRate reduces the number of bit-rates it must sample by 
     127 * eliminating those that could not perform better than the one 
     128 * currently being used.  SampleRate also stops probing at a bit-rate 
     129 * if it experiences several successive losses. 
     130 * 
     131 * The difference between the algorithm in the thesis and the one in this 
     132 * file is that the one in this file uses a ewma instead of a window. 
     133 * 
     134 * Also, this implementation tracks the average transmission time for 
     135 * a few different packet sizes independently for each link. 
     136 * 
     137 */ 
     138 
     139#include "release.h" 
     140static char *version = "1.2 (" RELEASE_VERSION ")"; 
     141static char *dev_info = "ath_rate_minstrel"; 
     142 
     143 
     144#define STALE_FAILURE_TIMEOUT_MS 10000 
     145 
     146#define ENABLE_MRR 1 
     147 
     148static int ath_timer_interval = (1000/10); /** every 1/10 second, timer runs */ 
     149 
     150/**10% of the time, send a packet at something other than the optimal rate, which fills 
     151   the statistics tables nicely. This percentage is applied to the first packet of the 
     152   multi rate retry chain. */ 
     153static int ath_lookaround_rate = 10; 
     154static int ath_ewma_level      = 75; 
     155static int ath_segment_size    = 6000; 
     156static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *); 
     157 
     158/**Calculate the throughput and probability of success for each node 
     159   we are talking on, based on the statistics collected during the 
     160   last timer period. */ 
     161static void ath_rate_statistics(void *arg, struct ieee80211_node *ni); 
     162 
     163 
     164#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) 
     165MODULE_PARM(ath_lookaround_rate, "i"); 
     166MODULE_PARM(ath_ewma_level, "i"); 
     167MODULE_PARM(ath_segment_size, "i"); 
     168#else 
     169#include <linux/moduleparam.h> 
     170module_param(ath_lookaround_rate, int, 10); 
     171module_param(ath_ewma_level, int, 75); 
     172module_param(ath_segment_size, int, 6000); 
     173#endif 
     174MODULE_PARM_DESC(ath_lookaround_rate, " % of packets sent to fill statistics table (10) "); 
     175MODULE_PARM_DESC(ath_ewma_level, " scaling % used in ewma rolloff calculations  (75) "); 
     176MODULE_PARM_DESC(ath_segment_size, " max duration of time to spend in either of the first two mrr segments (6000)"); 
     177 
     178 
     179 
     180static void 
     181ath_timer_function(unsigned long data); 
     182 
     183 
     184static __inline int  
     185rate_to_ndx(struct minstrel_node *sn, int rate) 
     186{ 
     187        int x = 0; 
     188        for (x = 0; x < sn->num_rates; x++) 
     189                if (sn->rates[x].rate == rate) 
     190                        return x; 
     191        return -1; 
     192} 
     193 
     194/* 
     195 * Calculate the transmit duration of a frame. 
     196 */ 
     197static unsigned 
     198calc_usecs_unicast_packet(struct ath_softc *sc, int length,  
     199        int rix, int short_retries, int long_retries) 
     200{ 
     201        const HAL_RATE_TABLE *rt = sc->sc_currates; 
     202        int rts, cts; 
     203         
     204        unsigned t_slot = 20; 
     205        unsigned t_difs = 50;  
     206        unsigned t_sifs = 10;  
     207        struct ieee80211com *ic = &sc->sc_ic; 
     208        int tt = 0; 
     209        int x = 0; 
     210        int cw = WIFI_CW_MIN; 
     211        int cix = rt->info[rix].controlRate; 
     212        KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 
     213 
     214        if (!rt->info[rix].rateKbps) { 
     215                printk(KERN_WARNING "rix %d (%d) bad ratekbps %d mode %u\n", 
     216                       rix, rt->info[rix].dot11Rate, 
     217                       rt->info[rix].rateKbps, 
     218                       sc->sc_curmode); 
     219                return 0; 
     220        } 
     221        /*  
     222         * XXX getting mac/phy level timings should be fixed for turbo 
     223         * rates, and there is probably a way to get this from the 
     224         * hal... 
     225         */ 
     226        switch (rt->info[rix].phy) { 
     227        case IEEE80211_T_OFDM: 
     228                t_slot = 9; 
     229                t_sifs = 16; 
     230                t_difs = 28; 
     231                /* fall through */ 
     232        case IEEE80211_T_TURBO: 
     233                t_slot = 9; 
     234                t_sifs = 8; 
     235                t_difs = 28; 
     236                break; 
     237        case IEEE80211_T_DS: 
     238                /* fall through to default */ 
     239        default: 
     240                /* pg 205 ieee.802.11.pdf */ 
     241                t_slot = 20; 
     242                t_difs = 50; 
     243                t_sifs = 10; 
     244        } 
     245 
     246        rts = cts = 0; 
     247 
     248        if ((ic->ic_flags & IEEE80211_F_USEPROT) && 
     249            rt->info[rix].phy == IEEE80211_T_OFDM) { 
     250                if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 
     251                        rts = 1; 
     252                else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 
     253                        cts = 1; 
     254 
     255                cix = rt->info[sc->sc_protrix].controlRate; 
     256        } 
     257 
     258        if (0 /*length > ic->ic_rtsthreshold */) 
     259                rts = 1; 
     260 
     261        if (rts || cts) { 
     262                int ctsrate = rt->info[cix].rateCode; 
     263                int ctsduration = 0; 
     264 
     265                if (!rt->info[cix].rateKbps) { 
     266#if 0 
     267                        printk(KERN_WARNING "cix %d (%d) bad ratekbps %d mode %u\n", 
     268                               cix, rt->info[cix].dot11Rate, 
     269                               rt->info[cix].rateKbps, 
     270                               sc->sc_curmode); 
     271#endif 
     272                        return 0; 
     273                } 
     274                 
     275 
     276                ctsrate |= rt->info[cix].shortPreamble; 
     277                if (rts)                /* SIFS + CTS */ 
     278                        ctsduration += rt->info[cix].spAckDuration; 
     279 
     280                ctsduration += ath_hal_computetxtime(sc->sc_ah, 
     281                                                     rt, length, rix, AH_TRUE); 
     282 
     283                if (cts)        /* SIFS + ACK */ 
     284                        ctsduration += rt->info[cix].spAckDuration; 
     285 
     286                tt += (short_retries + 1) * ctsduration; 
     287        } 
     288        tt += t_difs; 
     289        tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration); 
     290        tt += (long_retries+1)*ath_hal_computetxtime(sc->sc_ah, rt, length,  
     291                                                rix, AH_TRUE); 
     292        for (x = 0; x <= short_retries + long_retries; x++) { 
     293                cw = MIN(WIFI_CW_MAX, (cw + 1) * 2); 
     294                tt += (t_slot * cw / 2); 
     295        } 
     296        return tt; 
     297} 
     298 
     299static void 
     300ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) 
     301{ 
     302        /* NB: assumed to be zero'd by caller */ 
     303        ath_rate_ctl_reset(sc, &an->an_node); 
     304} 
     305 
     306 
     307static void 
     308ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 
     309{ 
     310} 
     311 
     312#if 0 
     313static void 
     314ath_rate_node_copy(struct ath_softc *sc, 
     315        struct ath_node *dst, const struct ath_node *src) 
     316{ 
     317        struct minstrel_node *odst = ATH_NODE_MINSTREL(dst); 
     318        const struct minstrel_node *osrc = (const struct minstrel_node *)&src[1]; 
     319        memcpy(odst, osrc, sizeof(struct minstrel_node)); 
     320} 
     321#endif 
     322 
     323 
     324static void 
     325ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, 
     326        int shortPreamble, size_t frameLen, 
     327        u_int8_t *rix, int *try0, u_int8_t *txrate) 
     328{ 
     329        struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
     330        struct ieee80211com *ic = &sc->sc_ic; 
     331        int ndx, mrr; 
     332        int offset; 
     333        if (sn->num_rates <= 0) { 
     334                printk(KERN_WARNING "%s: no rates for %s?\n", 
     335                       dev_info, 
     336                       ether_sprintf(an->an_node.ni_macaddr)); 
     337                return; 
     338        } 
     339   
     340        mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR; 
     341 
     342        if (sn->static_rate_ndx != -1) { 
     343                ndx = sn->static_rate_ndx; 
     344        } else { 
     345                sn->packet_count++; 
     346                sn->random_n = (sn->a*sn->random_n) + sn->b; 
     347                offset = sn->random_n & 0xf; 
     348                if ((((100 * sn->sample_count)/(sn->sample_count + sn->packet_count)) < ath_lookaround_rate) && (offset < 2)) { 
     349                        sn->sample_count++; 
     350                        sn->is_sampling = 1; 
     351                        if (sn->packet_count >= (10000)) { 
     352                                sn->sample_count = 0; 
     353                                sn->packet_count = 0; 
     354                        }                                
     355 
     356                        /* Don't look for slowest rate (i.e. slowest 
     357                           base rate) We must presume that the slowest 
     358                           rate works fine, or else other management 
     359                           frames will also be failing - therefore the 
     360                           link will soon be broken anyway. Indeed, 
     361                           the slowest rate was used to establish the 
     362                           link in the first place. */ 
     363                        ndx = sn->rs_sampleTable[sn->rs_sampleIndex][sn->rs_sampleColumn]; 
     364                        if (ndx >= sn->num_rates) 
     365                            ndx = 1; 
     366                        sn->rs_sampleIndex++; 
     367                        if (sn->rs_sampleIndex > (sn->num_rates - 2)) { 
     368                                sn->rs_sampleIndex = 0; 
     369                                sn->rs_sampleColumn++; 
     370                                if (sn->rs_sampleColumn == MINSTREL_COLUMNS) 
     371                                        sn->rs_sampleColumn = 0; 
     372                        } 
     373                } else 
     374                        ndx = sn->max_tp_rate; 
     375 
     376         } 
     377 
     378        if (sn->static_rate_ndx != -1)  
     379                *try0 = ATH_TXMAXTRY; 
     380        else 
     381                *try0 = mrr ? sn->retry_adjusted_count[ndx] : ATH_TXMAXTRY; 
     382                  
     383 
     384 
     385        KASSERT(ndx >= 0 && ndx < sn->num_rates, 
     386                ("%s: bad ndx (%d/%d) for %s?\n", 
     387                 dev_info, ndx, sn->num_rates, 
     388                 ether_sprintf(an->an_node.ni_macaddr))); 
     389 
     390        *rix = sn->rates[ndx].rix; 
     391        if (shortPreamble) 
     392                *txrate = sn->rates[ndx].shortPreambleRateCode; 
     393        else 
     394                *txrate = sn->rates[ndx].rateCode; 
     395} 
     396 
     397 
     398static void 
     399ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 
     400        struct ath_desc *ds, int shortPreamble, size_t frame_size, u_int8_t rix) 
     401{ 
     402        struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
     403        int rc1, rc2, rc3;         /* Index into the rate table, so for example, it is  0..11 */ 
     404        int rixc1, rixc2, rixc3;   /* The actual bit rate used */ 
     405 
     406        if (sn->is_sampling) { 
     407                rc1 = sn->max_tp_rate; 
     408                sn->is_sampling = 0; 
     409        } else { 
     410                rc1 = sn->max_tp_rate2; 
     411        } 
     412         
     413        rc2 = sn->max_prob_rate; 
     414        rc3 = 0; 
     415 
     416        KASSERT(rc1 >= 0 && rc1 < sn->num_rates, 
     417                ("%s: bad rc1 (%d/%d) for %s?\n", 
     418                 dev_info, rc1, sn->num_rates, 
     419                 ether_sprintf(an->an_node.ni_macaddr))); 
     420 
     421        KASSERT(rc2 >= 0 && rc2 < sn->num_rates, 
     422                ("%s: bad rc2 (%d/%d) for %s?\n", 
     423                 dev_info, rc2, sn->num_rates, 
     424                 ether_sprintf(an->an_node.ni_macaddr))); 
     425 
     426        KASSERT(rc3 >= 0 && rc3 < sn->num_rates, 
     427                ("%s: bad rc3 (%d/%d) for %s?\n", 
     428                 dev_info, rc3, sn->num_rates, 
     429                 ether_sprintf(an->an_node.ni_macaddr))); 
     430 
     431 
     432        if (shortPreamble) { 
     433                rixc1 = sn->rates[rc1].shortPreambleRateCode; 
     434                rixc2 = sn->rates[rc2].shortPreambleRateCode; 
     435                rixc3 = sn->rates[rc3].shortPreambleRateCode; 
     436        } else { 
     437                rixc1 = sn->rates[rc1].rateCode; 
     438                rixc2 = sn->rates[rc2].rateCode; 
     439                rixc3 = sn->rates[rc3].rateCode; 
     440        } 
     441 
     442        ath_hal_setupxtxdesc(sc->sc_ah, ds, 
     443                             rixc1, sn->retry_adjusted_count[rc1],   /* series 1 */ 
     444                             rixc2, sn->retry_adjusted_count[rc2],   /* series 2 */ 
     445                             rixc3, sn->retry_adjusted_count[rc3]    /* series 3 */ 
     446                             ); 
     447} 
     448 
     449 
     450 
     451 
     452static void 
     453ath_rate_tx_complete(struct ath_softc *sc, 
     454        struct ath_node *an, const struct ath_desc *ds) 
     455{ 
     456        struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
     457        struct ieee80211com *ic = &sc->sc_ic; 
     458        const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0; 
     459        int final_rate = 0; 
     460        int tries = 0; 
     461        int ndx = -1; 
     462        int mrr; 
     463        int final_ndx; 
     464        int rate0, tries0, ndx0; 
     465        int rate1, tries1, ndx1; 
     466        int rate2, tries2, ndx2; 
     467        int rate3, tries3, ndx3; 
     468        /* This is the index in the retry chain we finish at. 
     469           With no retransmits, it is always 0. 
     470          int finalTSIdx = ads->final_ts_index;  
     471        */ 
     472        final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate; 
     473        final_ndx = rate_to_ndx(sn, final_rate); 
     474        if (final_ndx >= sn->num_rates) { 
     475                printk(KERN_ERR "final ndx too high\n"); 
     476                final_ndx = 0; 
     477        } 
     478        if (final_ndx < 0) { 
     479                printk(KERN_ERR "final ndx too low\n"); 
     480                final_ndx = 0; 
     481        }                
     482 
     483        /* tries is the total number of times we have endeavoured to 
     484           send this packet, and is a sum of the #attempts at each 
     485           level in the multi rate retry chain */ 
     486        tries = ds->ds_txstat.ts_shortretry + ds->ds_txstat.ts_longretry + 1; 
     487 
     488        if (sn->num_rates <= 0) { 
     489                DPRINTF(sc, "%s: %s %s no rates yet\n", dev_info,  
     490                        ether_sprintf(an->an_node.ni_macaddr), __func__); 
     491                return; 
     492        } 
     493 
     494        if (!ds->ds_txstat.ts_status)  /*Success when sending a packet*/ 
     495                sn->rs_ratesuccess[final_ndx]++; 
     496 
     497        mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR; 
     498 
     499        if (!mrr) { 
     500                if (ndx >= 0 && ndx < sn->num_rates) { 
     501                        sn->rs_rateattempts[ndx]++;/* only one rate was used */ 
     502                } 
     503                return; 
     504        } 
     505 
     506 
     507 
     508 
     509 
     510        /**Now, query the hal/hardware to find out the contents of the multirate retry chain. 
     511           If we have it set to 6,3,2,2, this call will always return 6,3,2,2. For some packets, we can 
     512           get a mrr of 0, -1, -1, -1, which indicates there is no chain installed for that packet */ 
     513        rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate; 
     514        tries0 = ads->xmit_tries0; 
     515        ndx0 = rate_to_ndx(sn, rate0); 
     516         
     517        rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate; 
     518        tries1 = ads->xmit_tries1; 
     519        ndx1 = rate_to_ndx(sn, rate1); 
     520         
     521        rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate; 
     522        tries2 = ads->xmit_tries2; 
     523        ndx2 = rate_to_ndx(sn, rate2); 
     524         
     525        rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate; 
     526        tries3 = ads->xmit_tries3; 
     527        ndx3 = rate_to_ndx(sn, rate3); 
     528 
     529        sn->rs_rateattempts[ndx0] += MIN(tries, tries0); 
     530        if (tries <= tries0) 
     531                return; 
     532 
     533        if  (tries1 < 0) 
     534                return; 
     535        tries = tries - tries0; 
     536        sn->rs_rateattempts[ndx1] += MIN(tries, tries1); 
     537        if (tries <= tries1) 
     538                return;  
     539 
     540        if  (tries2 < 0) 
     541                return; 
     542        tries = tries - tries1; 
     543        sn->rs_rateattempts[ndx2] += MIN(tries, tries2); 
     544        if (tries <= tries2) 
     545                return; 
     546 
     547        if  (tries3 < 0) 
     548                return; 
     549        tries = tries - tries2; 
     550        sn->rs_rateattempts[ndx3] += MIN(tries, tries3);         
     551} 
     552 
     553 
     554static void 
     555ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 
     556{ 
     557        DPRINTF(sc, "%s: %s %s\n", dev_info, 
     558                ether_sprintf(an->an_node.ni_macaddr), __func__); 
     559        if (isnew) 
     560                ath_rate_ctl_reset(sc, &an->an_node); 
     561} 
     562 
     563static void 
     564ath_fill_sample_table(struct minstrel_node *sn) 
     565{ 
     566        int num_sample_rates = sn->num_rates - 1; 
     567        int i, column_index; 
     568        int newIndex; 
     569        u_int8_t random_bytes[12]; 
     570 
     571        for(column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
     572                for (i = 0; i <= IEEE80211_RATE_MAXSIZE; i++) 
     573                        sn->rs_sampleTable[i][column_index] = 0; 
     574 
     575                for (i = 0; i < num_sample_rates; i++) { 
     576                        get_random_bytes(random_bytes, 8); 
     577                        newIndex = (i + (int)(random_bytes[i & 7])) % num_sample_rates; 
     578                        if (newIndex < 0) 
     579                                newIndex = 2; 
     580 
     581                        while (sn->rs_sampleTable[newIndex][column_index] != 0) { 
     582                                newIndex = ((int)(newIndex + 1)) % num_sample_rates; 
     583                                if (newIndex < 0) 
     584                                        newIndex = 2; 
     585                        } 
     586 
     587                        sn->rs_sampleTable[newIndex][column_index] = i + 1; 
     588                } 
     589        } 
     590 
     591        sn->rs_sampleColumn = 0; 
     592        sn->rs_sampleIndex = 0; 
     593 
     594   /**Seed value to random number geenrator, which determines when we 
     595      send a sample packet at some non optimal rate */ 
     596        sn->random_n = 1; 
     597        sn->a = 1664525; 
     598        sn->b = 1013904223; 
     599#if 0 
     600        char rates[200]; 
     601        char *p; 
     602        for(column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
     603                p = rates + sprintf(rates, "rates :: %d ", column_index); 
     604                for (i = 0; i < num_sample_rates; i++) 
     605                        p += sprintf(p, "%2d ", (int)sn->rs_sampleTable[i][column_index]) 
     606; 
     607                printk("%s\n", rates); 
     608        }; 
     609#endif 
     610} 
     611 
     612 
     613 
     614 
     615/* 
     616 * Initialize the tables for a node. 
     617 */ 
     618static void 
     619ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 
     620{ 
     621        struct ath_node *an = ATH_NODE(ni); 
     622        struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
     623        struct ieee80211vap *vap = ni->ni_vap; 
     624        const HAL_RATE_TABLE *rt = sc->sc_currates; 
     625        int x; 
     626        int retry_index, tx_time; 
     627        int srate; 
     628        sn->num_rates = 0; 
     629        sn->max_tp_rate = 0; 
     630        sn->max_tp_rate2 = 0; 
     631        sn->max_prob_rate = 0; 
     632        sn->packet_count = 0; 
     633        sn->sample_count = 0; 
     634        sn->is_sampling = 0; 
     635 
     636        if (rt == NULL) { 
     637                printk(KERN_WARNING "no rates yet! mode %u\n", sc->sc_curmode); 
     638                return; 
     639        } 
     640        sn->static_rate_ndx = -1; 
     641 
     642        sn->num_rates = ni->ni_rates.rs_nrates; 
     643        for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
     644 
     645                sn->rs_rateattempts[x] = 0; 
     646                sn->rs_thisprob    [x] = 0; 
     647                sn->rs_ratesuccess [x] = 0; 
     648                sn->rs_lastrateattempts[x] = 0; 
     649                sn->rs_lastratesuccess [x] = 0; 
     650                sn->rs_probability [x] = 0; 
     651                sn->rs_succ_hist   [x] = 0; 
     652                sn->rs_att_hist    [x] = 0; 
     653                sn->rs_this_tp     [x] = 0; 
     654 
     655                sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; 
     656                sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; 
     657                if (sn->rates[x].rix == 0xff) { 
     658                        DPRINTF(sc, "%s: %s ignore bogus rix at %d\n", 
     659                                dev_info, __func__, x); 
     660                        continue; 
     661                } 
     662                sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; 
     663                sn->rates[x].shortPreambleRateCode =  
     664                        rt->info[sn->rates[x].rix].rateCode |  
     665                        rt->info[sn->rates[x].rix].shortPreamble; 
     666        } 
     667 
     668        ath_fill_sample_table(sn); 
     669         
     670        ni->ni_txrate = 0; 
     671        sn->num_rates = ni->ni_rates.rs_nrates; 
     672 
     673        if (sn->num_rates <= 0) { 
     674                DPRINTF(sc, "%s: %s %s no rates (fixed %d) \n", 
     675                        dev_info, __func__, ether_sprintf(ni->ni_macaddr), 
     676                        vap->iv_fixed_rate); 
     677                /* there are no rates yet we're done */ 
     678                return; 
     679        } 
     680 
     681        if (vap->iv_fixed_rate != -1) { 
     682                srate = sn->num_rates - 1; 
     683 
     684                /* 
     685                 * A fixed rate is to be used; ic_fixed_rate is an 
     686                 * index into the supported rate set.  Convert this 
     687                 * to the index into the negotiated rate set for 
     688                 * the node.  We know the rate is there because the 
     689                 * rate set is checked when the station associates. 
     690                 */ 
     691                /* NB: the rate set is assumed sorted */ 
     692                for (; srate >= 0 && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--); 
     693 
     694                KASSERT(srate >= 0, 
     695                        ("fixed rate %d not in rate set", vap->iv_fixed_rate)); 
     696 
     697                sn->static_rate_ndx = srate; 
     698                ni->ni_txrate = srate; 
     699                DPRINTF(sc, "%s: %s %s fixed rate %d%sMbps\n", 
     700                        dev_info, __func__, ether_sprintf(ni->ni_macaddr),  
     701                        sn->rates[srate].rate / 2, 
     702                        (sn->rates[srate].rate % 0x1) ? ".5" : " "); 
     703                return; 
     704        } 
     705         
     706 
     707        int ndx = 0; 
     708         
     709        for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
     710                sn->rs_rateattempts [x] = 0; 
     711                sn->rs_thisprob     [x] = 0; 
     712                sn->rs_ratesuccess  [x] = 0; 
     713                sn->rs_probability  [x] = 0; 
     714                sn->rs_lastrateattempts[x] = 0; 
     715                sn->rs_lastratesuccess [x] = 0; 
     716                sn->rs_succ_hist    [x] = 0; 
     717                sn->rs_att_hist     [x] = 0; 
     718                sn->perfect_tx_time [x] =  
     719                        calc_usecs_unicast_packet(sc, 1200,  
     720                                                  sn->rates[x].rix, 
     721                                                  0, 0); 
     722 
     723                sn->retry_count     [x] = 1; 
     724                sn->retry_adjusted_count[x] = 1; 
     725                for (retry_index = 2; retry_index < 11; retry_index++) { 
     726                        tx_time = calc_usecs_unicast_packet(sc, 1200, sn->rates[x].rix, 0, retry_index); 
     727                        if (tx_time >  ath_segment_size)  
     728                                break; 
     729                        sn->retry_count[x] = retry_index; 
     730                        sn->retry_adjusted_count[x] = retry_index; 
     731                } 
     732        } 
     733 
     734        //      printk(KERN_ERR "Retry table for this node\n"); 
     735        //      for (x = 0; x < ni->ni_rates.rs_nrates; x++)  
     736        //           printk(KERN_ERR "%2d  %2d %6d  \n",x, sn->retry_count[x], sn->perfect_tx_time[x]); 
     737 
     738        /* set the initial rate */ 
     739        for (ndx = sn->num_rates-1; ndx > 0; ndx--) 
     740                if (sn->rates[ndx].rate <= 72) 
     741                        break; 
     742        sn->current_rate = ndx; 
     743 
     744        ni->ni_txrate = sn->current_rate; 
     745} 
     746 
     747static void 
     748ath_rate_cb(void *arg, struct ieee80211_node *ni) 
     749{ 
     750        ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni); 
     751} 
     752 
     753/* 
     754 * Reset the rate control state for each 802.11 state transition. 
     755 */ 
     756static void 
     757ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state newstate) 
     758{ 
     759        struct ieee80211com *ic = vap->iv_ic; 
     760         
     761        if (newstate == IEEE80211_S_RUN) { 
     762                if (ic->ic_opmode != IEEE80211_M_STA) { 
     763                        /* 
     764                         * Sync rates for associated stations and neighbors. 
     765                         */ 
     766                        ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL); 
     767                } 
     768                ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1); 
     769        } 
     770} 
     771 
     772 
     773static void 
     774ath_timer_function(unsigned long data) 
     775{ 
     776        struct minstrel_softc *ssc = (struct minstrel_softc *) data; 
     777        struct ath_softc *sc = ssc->sc; 
     778        int interval; 
     779        struct ieee80211com *ic; 
     780 
     781        struct net_device *dev = ssc->sc_dev; 
     782        struct timer_list *timer; 
     783        interval = ath_timer_interval; 
     784 
     785         
     786        if (dev == NULL)  
     787                printk(KERN_INFO "Dev is null in this timer \n"); 
     788 
     789        if (sc == NULL)  
     790                printk(KERN_INFO "sc is null in this timer\n"); 
     791 
     792 
     793        ic = &sc->sc_ic; 
     794 
     795        if (ssc->close_timer_now) 
     796                return; 
     797         
     798        if (dev->flags & IFF_RUNNING) { 
     799                sc->sc_stats.ast_rate_calls++; 
     800 
     801                if (ic->ic_opmode == IEEE80211_M_STA) { 
     802                        struct ieee80211vap *tmpvap; 
     803                        TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { 
     804                                ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */ 
     805                        } 
     806                } else 
     807                        ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc); 
     808 
     809        } 
     810        if (ic->ic_opmode == IEEE80211_M_STA) 
     811                interval = ath_timer_interval >> 1; 
     812        else 
     813                interval = ath_timer_interval; 
     814 
     815        timer  = &(ssc->timer); 
     816        if (timer == NULL)  
     817                printk(KERN_INFO "timer is null - leave it\n"); 
     818 
     819        timer->expires = jiffies + ((HZ * interval) / 1000); 
     820        add_timer(timer); 
     821} 
     822 
     823static void 
     824ath_rate_statistics(void *arg, struct ieee80211_node *ni) 
     825{ 
     826        struct ath_node *an; 
     827        struct minstrel_node *rn; 
     828        struct ieee80211_rateset *rs; 
     829        int i, rate, old_rate; 
     830        u_int32_t p; 
     831        u_int32_t micro_secs; 
     832        u_int32_t max_prob,    index_max_prob; 
     833        u_int32_t max_tp,      index_max_tp,      index_max_tp2; 
     834        /* Rate control 
     835         */ 
     836   
     837  
     838        an = (struct ath_node *)ni; 
     839        rn = ATH_NODE_MINSTREL(an); 
     840        rs = &ni->ni_rates; 
     841        old_rate = ni->ni_txrate; 
     842        rate = old_rate; 
     843 
     844        /*Calculate statistics for each date rate in the table */ 
     845        /*micro_secs is the time to transmit 1200 bytes, or 9600 bits.*/ 
     846        for (i = 0; i < rs->rs_nrates; i++) { 
     847                micro_secs = rn->perfect_tx_time[i]; 
     848                if (micro_secs == 0)  
     849                        micro_secs = ONE_SECOND; 
     850                 
     851                if (rn->rs_rateattempts[i] != 0) { 
     852                        p = (rn->rs_ratesuccess[i]*18000)/rn->rs_rateattempts[i]; 
     853                        rn->rs_succ_hist[i] += rn->rs_ratesuccess[i]; 
     854                        rn->rs_att_hist[i]  += rn->rs_rateattempts[i]; 
     855                        rn->rs_thisprob[i] = p; 
     856                        p = ((p * (100 - ath_ewma_level)) + (rn->rs_probability[i] * ath_ewma_level))/100; 
     857                        rn->rs_probability[i] = p; 
     858                        rn->rs_this_tp[i] = p * (ONE_SECOND/micro_secs); 
     859                        rn->rs_lastratesuccess[i] = rn->rs_ratesuccess[i]; 
     860                        rn->rs_lastrateattempts[i] = rn->rs_rateattempts[i]; 
     861                        rn->rs_ratesuccess[i] = 0; 
     862                        rn->rs_rateattempts[i] = 0; 
     863                }  else { 
     864                        rn->rs_lastratesuccess[i] = 0; 
     865                        rn->rs_lastrateattempts[i] = 0; 
     866                } 
     867 
     868                /* Sample less often below the 10% chance of success. 
     869                   Sample less often above the 95% chance of success. 
     870                rn->rs_probability is in units of 0..18000(100%), which avoids rounding issues.*/ 
     871                if ((rn->rs_probability[i] > 17100) || ( rn->rs_probability[i] < 1800)) { 
     872                        rn->retry_adjusted_count[i] = rn->retry_count[i]>> 1; 
     873                        if (rn->retry_adjusted_count[i] > 2) 
     874                                rn->retry_adjusted_count[i] = 2; 
     875                } else  
     876                        rn->retry_adjusted_count[i] = rn->retry_count[i]; 
     877                if (rn->retry_adjusted_count[i] == 0) 
     878                        rn->retry_adjusted_count[i] = 1; 
     879 
     880        } 
     881          
     882      /*The High speed rates (e.g 54mbps) is checked last. If 
     883        throughput is the same for two rates, we prefer the 
     884        lower rate, as this has a better chance of success.*/ 
     885        max_prob = 0;  
     886        index_max_prob = 0; 
     887        max_tp = 0;  
     888        index_max_tp  = 0; 
     889        index_max_tp2 = 0; 
     890         
     891        /**This code could have been moved up into the previous 
     892           loop. More readable to have it here */ 
     893        for (i = 0; i < rs->rs_nrates; i++) { 
     894 
     895                if (max_tp <= rn->rs_this_tp[i]) { 
     896                        index_max_tp = i; 
     897                        max_tp = rn->rs_this_tp[i]; 
     898                } 
     899 
     900                if (max_prob <= rn->rs_probability[i]) { 
     901                        index_max_prob = i; 
     902                        max_prob = rn->rs_probability[i]; 
     903                } 
     904        } 
     905          
     906        max_tp = 0; 
     907        for (i = 0; i < rs->rs_nrates; i++) { 
     908                if ((i != index_max_tp) && (max_tp <= rn->rs_this_tp[i])) { 
     909                        index_max_tp2 = i; 
     910                        max_tp = rn->rs_this_tp[i]; 
     911                } 
     912        } 
     913 
     914        rn->max_tp_rate   = index_max_tp; 
     915        rn->max_tp_rate2  = index_max_tp2; 
     916        rn->max_prob_rate = index_max_prob; 
     917        rn->current_rate  = index_max_tp; 
     918} 
     919 
     920 
     921 
     922static struct ath_ratectrl * 
     923ath_rate_attach(struct ath_softc *sc) 
     924{ 
     925        struct minstrel_softc *osc; 
     926        DPRINTF(sc, "%s: %s\n", dev_info, __func__); 
     927         
     928        _MOD_INC_USE(THIS_MODULE, return NULL); 
     929        osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC); 
     930        if (osc == NULL) { 
     931                _MOD_DEC_USE(THIS_MODULE); 
     932                return NULL; 
     933        } 
     934 
     935        osc->arc.arc_space = sizeof(struct minstrel_node); 
     936        osc->arc.arc_vap_space = 0; 
     937 
     938        osc->close_timer_now = 0; 
     939        init_timer(&osc->timer); 
     940        osc->sc          = sc; 
     941        osc->sc_dev      = sc->sc_dev; 
     942        osc->timer.function = ath_timer_function; 
     943        osc->timer.data = (unsigned long)osc; 
     944         
     945        osc->timer.expires = jiffies + HZ; 
     946        add_timer(&osc->timer); 
     947         
     948        return &osc->arc; 
     949} 
     950 
     951 
     952static void  
     953ath_rate_detach(struct ath_ratectrl *arc) 
     954{ 
     955        struct minstrel_softc *osc = (struct minstrel_softc *) arc; 
     956        osc->close_timer_now = 1; 
     957        del_timer(&osc->timer); 
     958        kfree(osc); 
     959        _MOD_DEC_USE(THIS_MODULE); 
     960} 
     961 
     962 
     963#ifdef CONFIG_SYSCTL 
     964static int 
     965ath_proc_read_nodes(struct ieee80211vap *vap, char *buf, int space) 
     966{ 
     967        char *p = buf; 
     968        struct ieee80211_node *ni; 
     969        struct ath_node *an; 
     970        struct minstrel_node *odst; 
     971        struct ieee80211_node_table *nt = 
     972                (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; 
     973        int x = 0; 
     974        int this_tp, this_prob, this_eprob; 
     975 
     976        TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 
     977                /* Assume each node needs 1500 bytes */ 
     978                if ((buf + space) < (p + 1500)) { 
     979                        if ((buf + space) > (p + 100)) { 
     980                                p += sprintf(p, "out of room for node %s\n\n", ether_sprintf(ni->ni_macaddr)); 
     981                                break; 
     982                        } 
     983                        printk("out of memeory to write tall of the nodes\n"); 
     984                        break; 
     985                } 
     986                an = ATH_NODE(ni); 
     987                odst = ATH_NODE_MINSTREL(an); 
     988                /* Skip ourself */ 
     989                if (memcmp(vap->iv_myaddr, ni->ni_macaddr, 
     990                                        IEEE80211_ADDR_LEN)==0) { 
     991                        continue; 
     992                } 
     993 
     994                p += sprintf(p, "rate data for node:: %s\n", ether_sprintf(ni->ni_macaddr)); 
     995                p += sprintf(p, "rate     throughput  ewma prob   this prob  this succ/attempt   success    attempts\n"); 
     996                for (x = 0; x < odst->num_rates; x++) { 
     997                        p += sprintf(p, "%s", 
     998                                        (x == odst->current_rate) ? "T" : " "); 
     999                         
     1000                        p += sprintf(p, "%s", 
     1001                                     (x == odst->max_tp_rate2) ? "t" : " "); 
     1002 
     1003                        p += sprintf(p, "%s", 
     1004                                     (x == odst->max_prob_rate) ? "P" : " "); 
     1005 
     1006                        p += sprintf(p, "%3d%s", 
     1007                                        odst->rates[x].rate/2, 
     1008                                        (odst->rates[x].rate & 0x1) != 0 ? ".5" : "  "); 
     1009 
     1010                        this_tp = ((odst->rs_this_tp[x] / 18000) * 96) >> 10; 
     1011                        this_prob = odst->rs_thisprob[x] / 18; 
     1012                        this_eprob = odst->rs_probability[x] / 18; 
     1013                        p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        %3u(%3u)   %8llu    %8llu\n", 
     1014                                     this_tp/10, this_tp%10, 
     1015                                     this_eprob/10, this_eprob%10, 
     1016                                     this_prob/10, this_prob%10, 
     1017                                     odst->rs_lastratesuccess[x], 
     1018                                     odst->rs_lastrateattempts[x], 
     1019                                     odst->rs_succ_hist[x], 
     1020                                     odst->rs_att_hist[x]); 
     1021                } 
     1022                p += sprintf(p, "\n"); 
     1023 
     1024                p += sprintf(p, "Total packet count::    ideal %d      lookaround %d\n\n", odst->packet_count, odst->sample_count); 
     1025        } 
     1026 
     1027        return (p - buf); 
     1028} 
     1029 
     1030int 
     1031ath_proc_ratesample_open(struct inode *inode, struct file *file) 
     1032{ 
     1033        struct proc_ieee80211_priv *pv = NULL; 
     1034        struct proc_dir_entry *dp = PDE(inode); 
     1035        struct ieee80211vap *vap = dp->data; 
     1036 
     1037        if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), 
     1038                                        GFP_KERNEL))) 
     1039                return -ENOMEM; 
     1040 
     1041        /* intially allocate both read and write buffers */ 
     1042        pv = (struct proc_ieee80211_priv *) file->private_data; 
     1043        memset(pv, 0, sizeof(struct proc_ieee80211_priv)); 
     1044        pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
     1045        if (!pv->rbuf) { 
     1046                kfree(pv); 
     1047                return -ENOMEM; 
     1048        } 
     1049        pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
     1050        if (!pv->wbuf) { 
     1051                vfree(pv->rbuf); 
     1052                kfree(pv); 
     1053                return -ENOMEM; 
     1054        } 
     1055 
     1056        memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE); 
     1057        memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE); 
     1058        pv->max_wlen = MAX_PROC_IEEE80211_SIZE; 
     1059        pv->max_rlen = MAX_PROC_IEEE80211_SIZE; 
     1060 
     1061        /* now read the data into the buffer */ 
     1062        pv->rlen = ath_proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE); 
     1063        return 0; 
     1064} 
     1065 
     1066static struct file_operations ath_proc_ratesample_ops = { 
     1067        .read = NULL, 
     1068        .write = NULL, 
     1069        .open = ath_proc_ratesample_open, 
     1070        .release = NULL, 
     1071}; 
     1072 
     1073static void  
     1074ath_rate_dynamic_proc_register(struct ieee80211vap *vap) 
     1075{ 
     1076        /* Create proc entries for the rate control algorithm */ 
     1077        ieee80211_proc_vcreate(vap, &ath_proc_ratesample_ops, "rate_info"); 
     1078} 
     1079 
     1080#endif /* CONFIG_SYSCTL */ 
     1081 
     1082 
     1083 
     1084static struct ieee80211_rate_ops ath_rate_ops = { 
     1085        .ratectl_id = IEEE80211_RATE_MINSTREL, 
     1086        .node_init = ath_rate_node_init, 
     1087        .node_cleanup = ath_rate_node_cleanup, 
     1088        .findrate = ath_rate_findrate, 
     1089        .setupxtxdesc = ath_rate_setupxtxdesc, 
     1090        .tx_complete = ath_rate_tx_complete, 
     1091        .newassoc = ath_rate_newassoc, 
     1092        .newstate = ath_rate_newstate, 
     1093        .attach = ath_rate_attach, 
     1094        .detach = ath_rate_detach, 
     1095        .dynamic_proc_register = ath_rate_dynamic_proc_register, 
     1096}; 
     1097 
     1098 
     1099MODULE_AUTHOR("John Bicket/Derek Smithies"); 
     1100MODULE_DESCRIPTION("Minstrel Rate bit-rate selection algorithm for Atheros devices"); 
     1101#ifdef MODULE_VERSION 
     1102MODULE_VERSION(RELEASE_VERSION); 
     1103#endif 
     1104#ifdef MODULE_LICENSE 
     1105MODULE_LICENSE("Dual BSD/GPL"); 
     1106#endif 
     1107 
     1108static int __init ath_rate_minstrel_init(void) 
     1109{ 
     1110        printk(KERN_INFO "%s: %s\n", dev_info, version); 
     1111        printk(KERN_ERR "\n"); 
     1112        printk(KERN_ERR "Minstrel automatic rate control algorithm.\n"); 
     1113        printk(KERN_ERR "\n"); 
     1114  
     1115        printk(KERN_ERR "Look around rate set to %d%%\n", ath_lookaround_rate); 
     1116        printk(KERN_ERR "EWMA rolloff level set to %d%%\n", ath_ewma_level); 
     1117        printk(KERN_ERR "Max Segment size in the mrr set to %d us\n", ath_segment_size); 
     1118 
     1119        printk(KERN_ERR "\n"); 
     1120        return ieee80211_rate_register(&ath_rate_ops); 
     1121} 
     1122module_init(ath_rate_minstrel_init); 
     1123 
     1124static void __exit ath_rate_minstrel_exit(void) 
     1125{ 
     1126        ieee80211_rate_unregister(&ath_rate_ops); 
     1127        printk(KERN_INFO "%s: unloaded\n", dev_info); 
     1128} 
     1129module_exit(ath_rate_minstrel_exit); 
     1130 
     1131/* The comment below is magic for those who use emacs to edit this file. */ 
     1132/* With the comment below, the tab key does auto indent to 8 spaces.     */ 
     1133  
     1134/* 
     1135 * Local Variables: 
     1136 * mode:c 
     1137 * c-file-style:linux 
     1138 * c-basic-offset:8 
     1139 * End: 
     1140 */ 
     1141  
     1142  
  • patches/2.4/Config.in

    old new  
    22if [ "$CONFIG_ATHEROS" = "y" ]; then 
    33 
    44   choice '    Atheros: Default Transmission Rate Control Algorithm'    \ 
    5         "Sample         CONFIG_ATHEROS_RATE_DEFAULT_SAMPLE \ 
     5        "Minstrel       CONFIG_ATHEROS_RATE_DEFAULT_MINSTREL \ 
     6         Sample         CONFIG_ATHEROS_RATE_DEFAULT_SAMPLE \ 
    67         Onoe           CONFIG_ATHEROS_RATE_DEFAULT_ONOE   \ 
    7          AMRR           CONFIG_ATHEROS_RATE_DEFAULT_AMRR" Sample 
     8         AMRR           CONFIG_ATHEROS_RATE_DEFAULT_AMRR" Minstrel 
    89 
    910  if [ "$CONFIG_ATHEROS_RATE_DEFAULT_AMRR" = "y" ]; then 
    1011    define_bool CONFIG_ATHEROS_RATE_AMRR y 
     
    3031        CONFIG_ATHEROS_RATE_SAMPLE $CONFIG_ATHEROS 
    3132  fi 
    3233 
     34  if [ "$CONFIG_ATHEROS_RATE_DEFAULT_MINSTREL" = "y" ]; then 
     35    define_bool CONFIG_ATHEROS_RATE_MINSTREL y 
     36    define_string CONFIG_ATHEROS_RATE_DEFAULT "minstrel" 
     37  else 
     38    dep_bool '    Minstrel Rate control algorithm' \ 
     39        CONFIG_ATHEROS_RATE_MINSTREL $CONFIG_ATHEROS 
     40  fi 
     41 
    3342fi 
  • patches/2.6/Kconfig

    old new  
    1919choice 
    2020        prompt "Atheros: Default Transmission Rate Control Algorithm" 
    2121        depends on ATHEROS 
    22         default ATHEROS_RATE_DEFAULT_SAMPLE 
     22        default ATHEROS_RATE_DEFAULT_MINSTREL 
    2323        help 
    2424          Select the rate control algorithm to be used by default.  You 
    2525          can select additional algorithms below. 
     
    3636                bool "Sample" 
    3737                select ATHEROS_RATE_SAMPLE 
    3838 
     39        config ATHEROS_RATE_DEFAULT_MINSTREL 
     40                bool "Minstrel" 
     41                select ATHEROS_RATE_MINSTREL 
     42 
    3943endchoice 
    4044 
    4145config ATHEROS_RATE_DEFAULT 
     
    4347        default "amrr" if ATHEROS_RATE_DEFAULT_AMRR 
    4448        default "onoe" if ATHEROS_RATE_DEFAULT_ONOE 
    4549        default "sample" if ATHEROS_RATE_DEFAULT_SAMPLE 
     50        default "minstrel" if ATHEROS_RATE_DEFAULT_MINSTREL 
    4651 
    4752config ATHEROS_RATE_AMRR 
    4853        bool "Adaptive Multi-Rate Retry control algorithm" 
     
    7580          the one currently being used. SampleRate also stops probing at 
    7681          a bitrate if it experiences several successive losses. 
    7782 
     83 
     84config ATHEROS_RATE_MINSTREL 
     85        bool "A wandering minstrel rate control algorithm" 
     86        depends on ATHEROS 
     87        default y 
     88        help 
     89          Similar to the SampleRate code base, except that it is 
     90          a)more carefully written 
     91          b)shown to give a throughput similar to what can be obtained by 
     92            manually fixing either end to fixed rates 
     93          c)verified by monitoring the network traffic with an ieee80211 
     94             enabled ethereal 
     95          d)responds to network changes and does modify the rate accordingly.  
     96            Thus, on moving the two nodes together/apart, the ideal rate will  
     97            be changed as appropriate. 
     98 
  • patches/2.6/Makefile

    old new  
     1obj-$(CONFIG_ATHEROS_RATE_AMRR)         += ath_rate/amrr/ 
     2obj-$(CONFIG_ATHEROS_RATE_MINSTREL)     += ath_rate/minstrel/ 
     3obj-$(CONFIG_ATHEROS_RATE_ONOE)         += ath_rate/onoe/ 
    14obj-$(CONFIG_ATHEROS_RATE_SAMPLE)       += ath_rate/sample/ 
    2 obj-$(CONFIG_ATHEROS_RATE_ONOE)         += ath_rate/onoe/ 
    3 obj-$(CONFIG_ATHEROS_RATE_AMRR)         += ath_rate/amrr/ 
    45obj-$(CONFIG_ATHEROS)                   += ath/ ath_hal/ net80211/ 
  • INSTALL

    old new  
    8383point to the output directory where .config is located, not to the 
    8484sources. 
    8585 
    86 MadWifi currently provides three different rate control algorithms, 
    87 ONOE, AMRR and SAMPLE.  SAMPLE is the most advanced one and is used by 
     86MadWifi currently provides four different rate control algorithms, 
     87ONOE, AMRR, SAMPLE and MINSTREL.  SAMPLE and MINSTREL are both very 
     88advanced, but MINSTREL is quite new.  Consequently, SAMPLE is used by 
    8889default.  In order to make MadWifi use e.g. AMRR instead, you have to 
    8990specify that as the module parameter e.g. 
    9091 
  • ath/if_ath.c

    old new  
    106106#ifdef CONFIG_ATHEROS_RATE_DEFAULT 
    107107#define DEF_RATE_CTL CONFIG_ATHEROS_RATE_DEFAULT 
    108108#else 
    109 #define DEF_RATE_CTL "sample
     109#define DEF_RATE_CTL "minstrel
    110110#endif 
    111111 
    112112enum { 
     
    308308MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode"); 
    309309MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability"); 
    310310MODULE_PARM_DESC(autocreate, "Create ath device in [sta|ap|wds|adhoc|ahdemo|monitor] mode. defaults to sta, use 'none' to disable"); 
    311 MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|onoe|sample], defaults to '" DEF_RATE_CTL "'"); 
     311MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], defaults to '" DEF_RATE_CTL "'"); 
    312312 
    313313static int      ath_debug = 0; 
    314314#ifdef AR_DEBUG 
     
    44094409 * handling, programs the sleep registers so the hardware 
    44104410 * will wake up in time to receive beacons, and configures 
    44114411 * the beacon miss handling so we'll receive a BMISS 
    4412  * interrupt when we stop seeing beacons from the AP 
     4412 * interrupt when we stop seeing beacons from the AP 
    44134413 * we've associated with. 
    44144414 */ 
    44154415static void 
     
    90399039        struct ath_softc *sc = dev->priv; 
    90409040        struct net_device_stats *stats = &sc->sc_devstats; 
    90419041 
    9042         /* update according to private statistics */ 
     9042        /* update according to private statistics */ 
    90439043        stats->tx_errors = sc->sc_stats.ast_tx_xretries 
    90449044                         + sc->sc_stats.ast_tx_fifoerr 
    90459045                         + sc->sc_stats.ast_tx_filtered;