Ticket #1222: minstrel.patch
| File minstrel.patch, 71.1 kB (added by mrenzmann, 5 years ago) |
|---|
-
net80211/ieee80211_rate.c
old new 46 46 #include <net80211/ieee80211_rate.h> 47 47 48 48 static 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" 52 53 }; 53 54 54 55 /* -
net80211/ieee80211_rate.h
old new 69 69 70 70 enum { 71 71 IEEE80211_RATE_AMRR, 72 IEEE80211_RATE_MINSTREL, 72 73 IEEE80211_RATE_ONOE, 73 74 IEEE80211_RATE_SAMPLE, 74 75 IEEE80211_RATE_MAX -
ath_rate/Makefile
old new 4 4 5 5 TOP = $(obj)/.. 6 6 7 obj-y := amrr/ onoe/ sample/7 obj-y := amrr/ minstrel/ onoe/ sample/ 8 8 9 9 include $(TOP)/Makefile.inc 10 10 -
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 */ 73 struct 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 91 struct rate_info { 92 int rate; 93 int rix; 94 int rateCode; 95 int shortPreambleRateCode; 96 }; 97 98 99 100 /* per-node state */ 101 struct 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 179 struct 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 2 Minstrel 3 4 Introduction 5 ================================================================== 6 This code is called minstrel, because we have taken a wandering minstrel 7 apporoch. Wander around the different rates, singing wherever you 8 can. And then, look at the performacnce, and make a choice. Note that the 9 wandering minstrel will always wander in directions where he/she feels he/she 10 will get paid the best for his/her work. 11 12 The Minstrel autorate selection algorithm is an EWMA based algorithm and is 13 derived 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 19 The code released in 2005 had some algorithmic and implementation 20 flaws (one of which was that it was based on the old madwifi codebase) 21 and was shown to be unstable. Performance of the sample module is poor 22 (http://www.madwifi.org/ticket/989), and we have observed similar 23 issues. 24 25 We 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 33 We examined the code in sample, and decided the best approach was a 34 rewrite based on sample and the module we released in January 2005. 35 36 Theory of operation 37 ================================================================== 38 39 We defined the measure of successfulnes (of packet transmission) as 40 41 mega-bits-transmitted 42 Prob_success_transmission * ---------------------- 43 elapsed time 44 45 This measure of successfulness will therefore adjust the transmission speed to 46 get the maximum number of data bits through the radio interface. Further, it 47 means that the 1mb/sec rate (which has a very high probability of successful 48 transmission) will not be used in preference to the 11mb/sec rate. 49 50 We decided that the module should record the successfulness of all packets 51 that are transmitted. From this data, the module has sufficient information to 52 decide which packets are more successful than others. However, a variability 53 element was required. We had to force the module to examine bit rates other 54 than optimal. Consquently, some percent of the packets have to be sent at 55 rates regarded as non optimal. 56 57 10 times a second (this frequency is alterable by changing the driver code) 58 a timer fires, which evaluates the statistics table. EWMA calculations 59 (described below) are used to process the success history of each rate. On 60 completion of the calculation, a decision is made as to the rate which has the 61 best throughput, second best throughput, and highest probability of success. 62 This data is used for populating the retry chain during the next 100 ms. 63 64 As stated above, the minstrel algorithm collects statistics from all packet 65 attempts. Minstrel spends a particular percentage of frames, doing "look 66 arounds" i.e. randomly trying other rates, to gather statistics. The 67 percentage of "look around" frames, is set at boot time via the module 68 parameter "ath_lookaround_rate" and defaults to 10%. The distribution of 69 lookaround frames is also randomised somewhat to avoid any potential 70 "strobing" of lookarounds between similar nodes. 71 72 TCP theory tells us that each packet sent must be delivered in under 26ms. Any 73 longer duration, and the TCP network layers will start to back off. A delay of 74 26ms implies that there is congestion in the network, and that fewer packets 75 should be injected to the device. Our conclusion was to adjust the retry chain 76 of each packet so the retry chain was guaranteed to be finished in under 26ms. 77 78 79 Retry Chain 80 ================================================================== 81 The HAL provides a multirate retry chain - which consists of four 82 segments. Each segment is an advisement to the HAL to try to send the current 83 packet at some rate, with a fixed number of retry attempts. Once the packet is 84 successfully transmitted, the remainder of the retry chain is 85 ignored. Selection of the number of retry attempts was based on the desire to 86 get the packet out in under 26ms, or fail. We provided a module parameter, 87 ath_segment_size, which has units of micoseconds, and specifies the maximum 88 duration one segment in the retry chain can last. This module parameter has a 89 default of 6000. Our view is that a segment size of between 4000 and 6000 90 seems to fit most situations. 91 92 There is some room for movement here - if the traffic is UDP then the limit of 93 26ms for the retry chain length is "meaningless". However, one may argue that 94 if the packet was not transmitted after some time period, it should 95 fail. Further, one does expect UDP packets to fail in transmission. We leave 96 it as an area for future improvement. 97 98 99 The (re)try segment chain is calculated in two possible manners. If this 100 packet is a normal trnamission packet (90% of packets are this) then the retry 101 count is best throughput, next best throughput, best probability, lowest 102 baserate. If it is a sample packet (10% of packets are this), then the retry 103 chain is random lookaround, best throughput, best probability, lowest base 104 rate. 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 113 The retry count is adjusted so that the transmission time for that section of 114 the retry chain is less than 26 ms. 115 116 After some discussion, we have adjusted the code so that the lowest rate is 117 never used for the lookaround packet. Our view is that since this rate is used 118 for management packets, this rate must be working. - Alternatively, the link 119 is set up with management packets, data packets are acknowledged with 120 management packets. Should the lowest rate stop working, the link is going to 121 die reasonably soon. 122 123 Analysis of information in the /proc/net/madwifi/athX/rate_info file 124 showed that the system was sampling too hard at some rates. For those 125 rates that never work (54mb, 500m range) there is no point in sending 126 10 sample packets (<6ms time). Consequently, for the very very low 127 probability rates, we sample at most twice. 128 129 130 EWMA 131 ================================================================== 132 133 The EWMA calculation is carried out 10 times a second, and is run for each 134 rate. This calculation has a smoothing effect, so that new results have 135 a reasonable (but not large) influence on the selected rate. However, with 136 time, a series of new results in some particular direction will predominate. 137 Given this smoothing, we can use words like inertia to describe the EWMA. 138 139 By "new results", we mean the results collected in the just completed 100ms 140 interval. Old results are the EWMA scaling values from before the just 141 completed 100ms interval. 142 143 EWMA scaling is set by the module parameter ath_ewma_level, and defaults to 144 75%. A value of 0% means use only the new results, ignore the old results. 145 A value of 99% means use the old results, with a tiny influence from the new 146 results. 147 148 149 150 The 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) 154 Pnew = ------------------------------------------------------------------------------ 155 100 156 157 number_packets_sent_successfully_this_rate_time_interval 158 Psuccess_this_time_interval=-------------------------------------------------------- 159 number_packets_sent_this_rate_time_interval 160 161 162 If no packets have been sent for a particular rate in a time interval, no 163 calculation is carried out. The Psuccess value for this rate is not changed. 164 165 If the new time interval is the first time interval (the module has just been 166 inserted), then Pnew is calculated from above with Pold set to 0. 167 168 The appropriate update interval was selected on the basis of choosing a comprimise 169 between 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. 173 The first two points are self explanatory. When there is a sudden change in the radio 174 environment, an update interval of 100ms will mean that the rates marked as optimal are 175 very quickly marked as poor. Consequently, the sudden change in radio environment will 176 mean that minstrel will very quickly switch to a better rate. 177 178 A sudden change in the transmission probabilities will happen when the 179 node has not transmitted any data for a while, and during that time 180 the environment has changed. On starting to transmit, the probability 181 of success at each rate will be quite different. The driver must adapt 182 as quickly as possible, so as to not upset the higher TCP network 183 layers. 184 185 186 187 Module Parameters 188 ==================================================== 189 The module has three parameters: 190 191 name default value purpose 192 ath_ewma_level 75% rate of response to new data. A value of 100 is VERY responsive. 193 ath_lookaround_rate 10% percent of packets sent at non optimal speed. 194 ath_segment_size 6000 maximum duration of a retry segment (microseconds) 195 196 197 198 199 200 Test Network 201 ==================================================== 202 We used three computers in our test network. The first two, equipped with 203 atheros cards running in adhoc mode. We used a program that sends a fixed 204 number of TCP packets between computers, and reports on the data rate. The 205 application reports on the data rate - at an application layer level, which is 206 considerably lower than the level used in transmitting the packets. 207 208 The third computer had an atheros card also, but was running network monitor 209 mode with ethereal. The monitor computer was used to see what data rates were 210 used on the air. This computer was a form of "logging of the connection" 211 without introducing any additional load on the first two computers. 212 213 It was from monitoring the results on the third computer that we started to 214 get some confidence in the correctness of the code. We observed TCP 215 backoffs (described above) on this box. There was much celebration when the 216 throughput increased simply because the retry chain was finished in under 26 217 ms. 218 219 Our view was that throughput between the two computers should be as 220 close as possible (or better than) what can be achieved by setting 221 both ends to fixed rates. Thus, if setting the both ends to fixed 222 rates significantly increases the throughput, a reasonable conclusion 223 is that a fault exists in the adaptive rate rate. 224 225 We recorded throughputs (with minstrel) that are within 10% of what is 226 achieved with the experimentally determined optimum fixed rate. 227 228 229 Notes on Timing 230 ==================================================== 231 232 As noted above, Minstrel calculates the throughput for each rate. This 233 calculation (using a packet of size 1200 bytes) determines the 234 transmission time on the radio medium. In these calculations, we assume a 235 contention window min and max value of 4 and 10 microseconds respectively. 236 237 Further, calculation of the transmission time is required so that we can 238 guarantee a packet is transmitted (or dropped) in a minimum time period. 239 The transmission time is used in determining how many times a packet 240 is transmitted in each segment of the retry chain. 241 242 Indeed, the card will supply the cwmin/cwmax values directly 243 iwpriv if_name get_cwmin <0|1|2|3> <0|1> 244 245 We have not made direct calls to determine cwmin/cwmax - this is an area 246 for future work. Indeed, the cwmin/cwmax determination code could check to 247 see if the user has altered these values with the appropriate iwpriv. 248 249 The contention window size does vary with traffic class. For example, 250 video and voice have a contention window min of 3 and 2 microseconds 251 respectively. Currently, minstrel does not check traffic class. 252 253 Calculating the throughputs based on traffic class and bit rate and 254 variable packet size will significantly complicate the code and require 255 many more sample packets. More sample packets will lower the throughput 256 achieved. 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 260 Values of cwin/cwmax of 4 and 10 microseconds are from 261 IEEE Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer 262 (PHY) specifications, Amendment : Medium Access Control (MAC) Enhancements for 263 Quality of Service (QoS) P802.11e/D12.0, November 2004. 264 265 266 Internal variable reporting 267 ==================================================== 268 The minstrel algorithm reports to the proc file system its internal 269 statistics, which can be viewed as text. A sample output is below: 270 271 cat /proc/net/madwifi/ath0/rate_info 272 273 274 rate data for node:: 00:02:6f:43:8c:7a 275 rate 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 287 T P 54 27.1 96.2 96.2 0( 0) 996 1029 288 289 290 Total packet count:: ideal 2344 lookaround 261 291 292 There is a separate table for each node in the neighbor table, which will 293 appear similar to above. 294 295 The possible datarates for this node are listed in the column at the left. The 296 calculated throughput and "ewma prob" are listed next, from which the rates 297 used in retry chain are selected. The rates with the maximum throughput, 298 second meximum throughput and maximum probability are indicated by the letters 299 T, t, and P respectively. 300 301 The statistics gathered in the last 100ms time period are displayed in the 302 "this prob" and "this succ/attempt" columns. 303 304 Finally, the number of packets transmitted at each rate, since module loading 305 are listed in the last two columns. When interpreting the last four columns, 306 note that we use the words "succ" or "success" to mean packets successfully 307 sent from this node to the remote node. The driver determines success by 308 analysing reports from the hal. The word "attempt" or "attempts" means the 309 count of packets that we transmitted. Thus, the number in the success column 310 will always be lower than the number in the attempts column. 311 312 313 When the two nodes are brought closer together, the statistics start changing, 314 and you see more successful attempts at the higher rates. The ewma prob at the 315 higher rates increases and then most packets are conveyed at the higher rates. 316 317 When the rate is not on auto, but fixed, this table is still 318 available, and will report the throughput etc for the current bit 319 rate. Changing the rate from auto to fixed to auto will completely 320 reset 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 7 src ?= . 8 srctree ?= . 9 10 TOP = $(srctree)/$(src)/../.. 11 12 include $(TOP)/BuildCaps.inc 13 14 ATH= $(TOP)/ath 15 ATH_HAL=$(TOP)/ath_hal 16 COMPAT= $(TOP)/include 17 HAL= $(TOP)/hal 18 19 INCS = -include $(COMPAT)/compat.h -I$(COMPAT) 20 INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -I$(HAL) 21 EXTRA_CFLAGS += $(INCS) $(COPTS) 22 23 ifneq ($(VERSION).$(PATCHLEVEL),2.4) 24 obj-$(CONFIG_ATHEROS) += ath_rate_minstrel.o 25 ath_rate_minstrel-objs := minstrel.o 26 endif 27 28 ifeq ($(VERSION).$(PATCHLEVEL),2.4) 29 obj-$(CONFIG_ATHEROS) := minstrel.o 30 31 export-objs := minstrel.o 32 list-multi := ath_rate_minstrel.o 33 34 O_TARGET := ath_rate.o 35 include $(TOPDIR)/Rules.make 36 endif -
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 # 41 ifeq ($(obj),) 42 obj= . 43 endif 44 45 TOP = $(obj)/../.. 46 47 obj-m += ath_rate_minstrel.o 48 ath_rate_minstrel-objs := minstrel.o 49 50 include $(TOP)/Makefile.inc 51 52 INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -I$(HAL) 53 54 EXTRA_CFLAGS+= $(INCS) $(COPTS) 55 56 -include $(TOPDIR)/Rules.make 57 58 all: 59 $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules 60 61 install: 62 test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH) 63 cp ath_rate_minstrel.$(KMODSUF) $(DESTDIR)/$(KMODPATH) 64 65 clean: 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 70 ath_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 103 enum { 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" 140 static char *version = "1.2 (" RELEASE_VERSION ")"; 141 static char *dev_info = "ath_rate_minstrel"; 142 143 144 #define STALE_FAILURE_TIMEOUT_MS 10000 145 146 #define ENABLE_MRR 1 147 148 static 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. */ 153 static int ath_lookaround_rate = 10; 154 static int ath_ewma_level = 75; 155 static int ath_segment_size = 6000; 156 static 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. */ 161 static void ath_rate_statistics(void *arg, struct ieee80211_node *ni); 162 163 164 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) 165 MODULE_PARM(ath_lookaround_rate, "i"); 166 MODULE_PARM(ath_ewma_level, "i"); 167 MODULE_PARM(ath_segment_size, "i"); 168 #else 169 #include <linux/moduleparam.h> 170 module_param(ath_lookaround_rate, int, 10); 171 module_param(ath_ewma_level, int, 75); 172 module_param(ath_segment_size, int, 6000); 173 #endif 174 MODULE_PARM_DESC(ath_lookaround_rate, " % of packets sent to fill statistics table (10) "); 175 MODULE_PARM_DESC(ath_ewma_level, " scaling % used in ewma rolloff calculations (75) "); 176 MODULE_PARM_DESC(ath_segment_size, " max duration of time to spend in either of the first two mrr segments (6000)"); 177 178 179 180 static void 181 ath_timer_function(unsigned long data); 182 183 184 static __inline int 185 rate_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 */ 197 static unsigned 198 calc_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 299 static void 300 ath_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 307 static void 308 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 309 { 310 } 311 312 #if 0 313 static void 314 ath_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 324 static void 325 ath_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 398 static void 399 ath_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 452 static void 453 ath_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 554 static void 555 ath_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 563 static void 564 ath_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 */ 618 static void 619 ath_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 747 static void 748 ath_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 */ 756 static void 757 ath_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 773 static void 774 ath_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 823 static void 824 ath_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 922 static struct ath_ratectrl * 923 ath_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 952 static void 953 ath_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 964 static int 965 ath_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 1030 int 1031 ath_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 1066 static struct file_operations ath_proc_ratesample_ops = { 1067 .read = NULL, 1068 .write = NULL, 1069 .open = ath_proc_ratesample_open, 1070 .release = NULL, 1071 }; 1072 1073 static void 1074 ath_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 1084 static 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 1099 MODULE_AUTHOR("John Bicket/Derek Smithies"); 1100 MODULE_DESCRIPTION("Minstrel Rate bit-rate selection algorithm for Atheros devices"); 1101 #ifdef MODULE_VERSION 1102 MODULE_VERSION(RELEASE_VERSION); 1103 #endif 1104 #ifdef MODULE_LICENSE 1105 MODULE_LICENSE("Dual BSD/GPL"); 1106 #endif 1107 1108 static 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 } 1122 module_init(ath_rate_minstrel_init); 1123 1124 static 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 } 1129 module_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 2 2 if [ "$CONFIG_ATHEROS" = "y" ]; then 3 3 4 4 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 \ 6 7 Onoe CONFIG_ATHEROS_RATE_DEFAULT_ONOE \ 7 AMRR CONFIG_ATHEROS_RATE_DEFAULT_AMRR" Sample8 AMRR CONFIG_ATHEROS_RATE_DEFAULT_AMRR" Minstrel 8 9 9 10 if [ "$CONFIG_ATHEROS_RATE_DEFAULT_AMRR" = "y" ]; then 10 11 define_bool CONFIG_ATHEROS_RATE_AMRR y … … 30 31 CONFIG_ATHEROS_RATE_SAMPLE $CONFIG_ATHEROS 31 32 fi 32 33 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 33 42 fi -
patches/2.6/Kconfig
old new 19 19 choice 20 20 prompt "Atheros: Default Transmission Rate Control Algorithm" 21 21 depends on ATHEROS 22 default ATHEROS_RATE_DEFAULT_ SAMPLE22 default ATHEROS_RATE_DEFAULT_MINSTREL 23 23 help 24 24 Select the rate control algorithm to be used by default. You 25 25 can select additional algorithms below. … … 36 36 bool "Sample" 37 37 select ATHEROS_RATE_SAMPLE 38 38 39 config ATHEROS_RATE_DEFAULT_MINSTREL 40 bool "Minstrel" 41 select ATHEROS_RATE_MINSTREL 42 39 43 endchoice 40 44 41 45 config ATHEROS_RATE_DEFAULT … … 43 47 default "amrr" if ATHEROS_RATE_DEFAULT_AMRR 44 48 default "onoe" if ATHEROS_RATE_DEFAULT_ONOE 45 49 default "sample" if ATHEROS_RATE_DEFAULT_SAMPLE 50 default "minstrel" if ATHEROS_RATE_DEFAULT_MINSTREL 46 51 47 52 config ATHEROS_RATE_AMRR 48 53 bool "Adaptive Multi-Rate Retry control algorithm" … … 75 80 the one currently being used. SampleRate also stops probing at 76 81 a bitrate if it experiences several successive losses. 77 82 83 84 config 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 1 obj-$(CONFIG_ATHEROS_RATE_AMRR) += ath_rate/amrr/ 2 obj-$(CONFIG_ATHEROS_RATE_MINSTREL) += ath_rate/minstrel/ 3 obj-$(CONFIG_ATHEROS_RATE_ONOE) += ath_rate/onoe/ 1 4 obj-$(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/4 5 obj-$(CONFIG_ATHEROS) += ath/ ath_hal/ net80211/ -
INSTALL
old new 83 83 point to the output directory where .config is located, not to the 84 84 sources. 85 85 86 MadWifi currently provides three different rate control algorithms, 87 ONOE, AMRR and SAMPLE. SAMPLE is the most advanced one and is used by 86 MadWifi currently provides four different rate control algorithms, 87 ONOE, AMRR, SAMPLE and MINSTREL. SAMPLE and MINSTREL are both very 88 advanced, but MINSTREL is quite new. Consequently, SAMPLE is used by 88 89 default. In order to make MadWifi use e.g. AMRR instead, you have to 89 90 specify that as the module parameter e.g. 90 91 -
ath/if_ath.c
old new 106 106 #ifdef CONFIG_ATHEROS_RATE_DEFAULT 107 107 #define DEF_RATE_CTL CONFIG_ATHEROS_RATE_DEFAULT 108 108 #else 109 #define DEF_RATE_CTL " sample"109 #define DEF_RATE_CTL "minstrel" 110 110 #endif 111 111 112 112 enum { … … 308 308 MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode"); 309 309 MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability"); 310 310 MODULE_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 "'");311 MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], defaults to '" DEF_RATE_CTL "'"); 312 312 313 313 static int ath_debug = 0; 314 314 #ifdef AR_DEBUG … … 4409 4409 * handling, programs the sleep registers so the hardware 4410 4410 * will wake up in time to receive beacons, and configures 4411 4411 * 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 4413 4413 * we've associated with. 4414 4414 */ 4415 4415 static void … … 9039 9039 struct ath_softc *sc = dev->priv; 9040 9040 struct net_device_stats *stats = &sc->sc_devstats; 9041 9041 9042 /* update according to private statistics */ 9042 /* update according to private statistics */ 9043 9043 stats->tx_errors = sc->sc_stats.ast_tx_xretries 9044 9044 + sc->sc_stats.ast_tx_fifoerr 9045 9045 + sc->sc_stats.ast_tx_filtered;
