Changeset 3361

Show
Ignore:
Timestamp:
02/21/08 23:04:34 (4 years ago)
Author:
benoit
Message:

Reformatting.
Fixed a bug where the percentage of look around packets was not correct

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • madwifi/branches/madwifi-dfs/ath_rate/minstrel/minstrel.c

    r3255 r3361  
    125125#define DPRINTF(sc, _fmt, ...) do {             \ 
    126126                if (sc->sc_debug & ATH_DEBUG_RATE)      \ 
    127                         printk(_fmt, __VA_ARGS__);             
     127                        printk("%s: " _fmt, SC_DEV_NAME(sc), __VA_ARGS__);
    128128} while (0) 
    129129#else 
     
    141141#define ENABLE_MRR 1 
    142142 
    143 static int ath_timer_interval = (1000 / 10); /* every 1/10 second, timer runs */ 
    144 static void ath_timer_function(unsigned long data); 
    145  
    146 /* 10% of the time, send a packet at something other than the optimal rate, which fills 
    147  * the statistics tables nicely. This percentage is applied to the first packet of the 
    148  * multi rate retry chain. */ 
     143/* interval (in ms) between successive rate statistics, default to 100 ms */ 
     144 
     145static int ath_timer_interval = 100; 
     146 
     147/* 10% of the time, send a packet at something other than the optimal rate, 
     148 * which fills the statistics tables nicely. This percentage is applied to the 
     149 * first packet of the multi rate retry chain. */ 
     150 
    149151static int ath_lookaround_rate = 10; 
    150152static int ath_ewma_level      = 75; 
     
    335337                        sn->random_n = (sn->a * sn->random_n) + sn->b; 
    336338                        offset = sn->random_n & 0xf; 
    337                         if ((((100 * sn->sample_count) / (sn->sample_count + sn->packet_count)) < ath_lookaround_rate) && (offset < 2)) { 
     339 
     340                        if (((100 * sn->sample_count)/sn->packet_count < ath_lookaround_rate) && (offset < 2)) { 
    338341                                sn->sample_count++; 
    339342                                sn->is_sampling = 1; 
     
    544547 
    545548static void 
    546 ath_fill_sample_table(struct minstrel_node *sn) 
    547 
    548                 unsigned int num_sample_rates = (sn->num_rates - 1); 
    549                 /* newIndex varies as 0 .. (num_rates - 2)  
    550                  * The highest index rate is the slowest and is ignored */ 
    551                 unsigned int i, column_index, newIndex; 
    552                 u_int8_t random_bytes[8]; 
    553  
    554                 /* This should be unnecessary if we are assuming storage is provided 
    555                  * as zeroed */ 
    556                 memset(sn->rs_sampleTable, 0, sizeof(sn->rs_sampleTable)); 
    557  
    558                 sn->rs_sampleColumn = 0; 
    559                 sn->rs_sampleIndex = 0; 
    560  
    561                 /* Seed value to random number generator, which determines when we 
    562                  * send a sample packet at some non-optimal rate 
    563                  * FIXME: randomise? */ 
    564                 sn->random_n = 1; 
    565                 sn->a = 1664525; 
    566                 sn->b = 1013904223; 
    567  
    568                 if (sn->num_rates > 1) { 
    569                         for (column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
    570                                 for (i = 0; i < num_sample_rates; i++) { 
    571                                         get_random_bytes(random_bytes, 8); 
    572                                         newIndex = (i + random_bytes[i & 7]) % num_sample_rates; 
    573  
    574                                         while (sn->rs_sampleTable[newIndex][column_index] != 0) 
    575                                                 newIndex = (newIndex + 1) % num_sample_rates; 
    576  
    577                                         sn->rs_sampleTable[newIndex][column_index] = i + 1; 
    578                                 } 
     549ath_fill_sample_table(struct ath_softc *sc, struct minstrel_node *sn) 
     550
     551        unsigned int num_sample_rates = (sn->num_rates - 1); 
     552        /* newIndex varies as 0 .. (num_rates - 2)  
     553         * The highest index rate is the slowest and is ignored */ 
     554        unsigned int i, column_index, newIndex; 
     555        u_int8_t random_bytes[8]; 
     556 
     557        /* This should be unnecessary if we are assuming storage is provided 
     558         * as zeroed */ 
     559        memset(sn->rs_sampleTable, 0, sizeof(sn->rs_sampleTable)); 
     560 
     561        sn->rs_sampleColumn = 0; 
     562        sn->rs_sampleIndex = 0; 
     563 
     564        /* Seed value to random number generator, which determines when we 
     565         * send a sample packet at some non-optimal rate 
     566         * FIXME: randomise? */ 
     567        sn->random_n = 1; 
     568        sn->a = 1664525; 
     569        sn->b = 1013904223; 
     570 
     571        if (sn->num_rates > 1) { 
     572                for (column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
     573                        for (i = 0; i < num_sample_rates; i++) { 
     574                                get_random_bytes(random_bytes, 8); 
     575                                newIndex = (i + random_bytes[i & 7]) % num_sample_rates; 
     576 
     577                                while (sn->rs_sampleTable[newIndex][column_index] != 0) 
     578                                        newIndex = (newIndex + 1) % num_sample_rates; 
     579 
     580                                sn->rs_sampleTable[newIndex][column_index] = i + 1; 
    579581                        } 
    580582                } 
     583        } 
     584         
     585        for (column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
     586                for (i = 0; i < num_sample_rates && i < IEEE80211_RATE_MAXSIZE; i++) { 
     587                        DPRINTF(sc, "rs_sampleTable[%2u][%2u] = %2u\n", 
     588                                i, column_index, sn->rs_sampleTable[i][column_index]); 
     589                } 
     590        } 
     591} 
     592 
     593/* Initialize the tables for a node. */ 
     594static void 
     595ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 
     596{ 
     597        struct ath_node *an = ATH_NODE(ni); 
     598        struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
     599        struct ieee80211vap *vap = ni->ni_vap; 
     600        const HAL_RATE_TABLE *rt = sc->sc_currates; 
     601        unsigned int x; 
     602        int retry_index, tx_time; 
     603        int srate; 
     604        int ndx = 0; 
     605 
     606        sn->num_rates = 0; 
     607        sn->max_tp_rate = 0; 
     608        sn->max_tp_rate2 = 0; 
     609        sn->max_prob_rate = 0; 
     610        sn->packet_count = 0; 
     611        sn->sample_count = 0; 
     612        sn->is_sampling = 0; 
     613 
     614        if (rt == NULL) { 
     615                DPRINTF(sc, "no rates yet! mode %u\n", sc->sc_curmode); 
     616                return; 
     617        } 
     618        sn->static_rate_ndx = -1; 
     619 
     620        sn->num_rates = ni->ni_rates.rs_nrates; 
     621        for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
     622                sn->rs_rateattempts     [x] = 0; 
     623                sn->rs_thisprob         [x] = 0; 
     624                sn->rs_ratesuccess      [x] = 0; 
     625                sn->rs_lastrateattempts [x] = 0; 
     626                sn->rs_lastratesuccess  [x] = 0; 
     627                sn->rs_probability      [x] = 0; 
     628                sn->rs_succ_hist        [x] = 0; 
     629                sn->rs_att_hist         [x] = 0; 
     630                sn->rs_this_tp          [x] = 0; 
     631 
     632                sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; 
     633                sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; 
     634                if (sn->rates[x].rix == 0xff) { 
     635                        DPRINTF(sc, "%s: %s ignore bogus rix at %d\n", 
     636                                dev_info, __func__, x); 
     637                        continue; 
     638                } 
     639                sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; 
     640                sn->rates[x].shortPreambleRateCode = 
     641                        rt->info[sn->rates[x].rix].rateCode | 
     642                        rt->info[sn->rates[x].rix].shortPreamble; 
     643        } 
     644         
     645        ath_fill_sample_table(sc, sn); 
     646         
     647        ni->ni_txrate = 0; 
     648 
     649        if (sn->num_rates <= 0) { 
     650                DPRINTF(sc, "%s: %s " MAC_FMT " no rates (fixed %d) \n", 
     651                        dev_info, __func__, MAC_ADDR(ni->ni_macaddr), 
     652                        vap->iv_fixed_rate); 
     653                /* There are no rates yet; we're done */ 
     654                return; 
     655        } 
     656 
     657        if (vap->iv_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 
     658                srate = sn->num_rates - 1; 
     659 
     660                /* A fixed rate is to be used; ic_fixed_rate is an 
     661                 * index into the supported rate set.  Convert this 
     662                 * to the index into the negotiated rate set for 
     663                 * the node.  We know the rate is there because the 
     664                 * rate set is checked when the station associates. */ 
     665                /* NB: the rate set is assumed sorted */ 
     666                for (; (srate >= 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--); 
     667 
     668                KASSERT(srate >= 0, 
     669                        ("fixed rate %d not in rate set", vap->iv_fixed_rate)); 
     670 
     671                sn->static_rate_ndx = srate; 
     672                ni->ni_txrate = srate; 
     673                DPRINTF(sc, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n", 
     674                        dev_info, __func__, MAC_ADDR(ni->ni_macaddr), 
     675                        sn->rates[srate].rate / 2, 
     676                        (sn->rates[srate].rate % 2) ? ".5 " : " "); 
     677                return; 
     678        } 
     679 
     680        for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
     681                if (sn->rates[x].rix == 0xff) { 
     682                        DPRINTF(sc, "%s: %s ignore bogus rix at %d\n", 
     683                                dev_info, __func__, x); 
     684                        continue; 
     685                } 
     686 
     687                sn->rs_rateattempts     [x] = 0; 
     688                sn->rs_thisprob         [x] = 0; 
     689                sn->rs_ratesuccess      [x] = 0; 
     690                sn->rs_probability      [x] = 0; 
     691                sn->rs_lastrateattempts [x] = 0; 
     692                sn->rs_lastratesuccess  [x] = 0; 
     693                sn->rs_succ_hist        [x] = 0; 
     694                sn->rs_att_hist         [x] = 0; 
     695                sn->perfect_tx_time     [x] = 
     696                        calc_usecs_unicast_packet(sc, 1200, 
     697                                                  sn->rates[x].rix, 
     698                                                  0, 0); 
     699                sn->retry_count         [x] = 1; 
     700                sn->retry_adjusted_count[x] = 1; 
     701 
     702                for (retry_index = 2; retry_index < ATH_TXMAXTRY; retry_index++) { 
     703                        tx_time = calc_usecs_unicast_packet(sc, 1200, sn->rates[x].rix, 0, retry_index); 
     704                        if (tx_time > ath_segment_size) 
     705                                break; 
     706                        sn->retry_count[x] = retry_index; 
     707                        sn->retry_adjusted_count[x] = retry_index; 
     708                } 
     709        } 
    581710 
    582711#if 0 
    583                 char rates[200]; 
    584                 char *p; 
    585                 for (column_index = 0; column_index < MINSTREL_COLUMNS; column_index++) { 
    586                             p = rates + sprintf(rates, "rates :: %d ", column_index); 
    587                             for (i = 0; i < num_sample_rates; i++) 
    588                                     p += sprintf(p, "%2u ", sn->rs_sampleTable[i][column_index]); 
    589                             DPRINTF(sc, "%s\n", rates); 
    590                 }; 
     712        DPRINTF(sc, "%s: Retry table for this node\n", __func__); 
     713        for (x = 0; x < ni->ni_rates.rs_nrates; x++) 
     714                DPRINTF(sc, "%2d  %2d %6d  \n", x, sn->retry_count[x], sn->perfect_tx_time[x]); 
    591715#endif 
    592 
    593  
    594 /* Initialize the tables for a node. */ 
    595 static void 
    596 ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 
    597 
    598                 struct ath_node *an = ATH_NODE(ni); 
    599                 struct minstrel_node *sn = ATH_NODE_MINSTREL(an); 
    600                 struct ieee80211vap *vap = ni->ni_vap; 
    601                 const HAL_RATE_TABLE *rt = sc->sc_currates; 
    602                 unsigned int x; 
    603                 int retry_index, tx_time; 
    604                 int srate; 
    605                 int ndx = 0; 
    606  
    607                 sn->num_rates = 0; 
    608                 sn->max_tp_rate = 0; 
    609                 sn->max_tp_rate2 = 0; 
    610                 sn->max_prob_rate = 0; 
    611                 sn->packet_count = 0; 
    612                 sn->sample_count = 0; 
    613                 sn->is_sampling = 0; 
    614  
    615                 if (rt == NULL) { 
    616                         DPRINTF(sc, "no rates yet! mode %u\n", sc->sc_curmode); 
    617                         return; 
    618                 } 
    619                 sn->static_rate_ndx = -1; 
    620  
    621                 sn->num_rates = ni->ni_rates.rs_nrates; 
    622                 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
    623                         sn->rs_rateattempts     [x] = 0; 
    624                         sn->rs_thisprob         [x] = 0; 
    625                         sn->rs_ratesuccess      [x] = 0; 
    626                         sn->rs_lastrateattempts [x] = 0; 
    627                         sn->rs_lastratesuccess  [x] = 0; 
    628                         sn->rs_probability      [x] = 0; 
    629                         sn->rs_succ_hist        [x] = 0; 
    630                         sn->rs_att_hist         [x] = 0; 
    631                         sn->rs_this_tp          [x] = 0; 
    632  
    633                         sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; 
    634                         sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; 
    635                         if (sn->rates[x].rix == 0xff) { 
    636                                 DPRINTF(sc, "%s: %s ignore bogus rix at %d\n", 
    637                                         dev_info, __func__, x); 
    638                                 continue; 
    639                         } 
    640                         sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; 
    641                         sn->rates[x].shortPreambleRateCode = 
    642                                 rt->info[sn->rates[x].rix].rateCode | 
    643                                 rt->info[sn->rates[x].rix].shortPreamble; 
    644                 } 
    645  
    646                 ath_fill_sample_table(sn); 
    647  
    648                 ni->ni_txrate = 0; 
    649  
    650                 if (sn->num_rates <= 0) { 
    651                         DPRINTF(sc, "%s: %s " MAC_FMT " no rates (fixed %d) \n", 
    652                                 dev_info, __func__, MAC_ADDR(ni->ni_macaddr), 
    653                                 vap->iv_fixed_rate); 
    654                         /* There are no rates yet; we're done */ 
    655                         return; 
    656                 } 
    657  
    658                 if (vap->iv_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 
    659                         srate = sn->num_rates - 1; 
    660  
    661                         /* A fixed rate is to be used; ic_fixed_rate is an 
    662                          * index into the supported rate set.  Convert this 
    663                          * to the index into the negotiated rate set for 
    664                          * the node.  We know the rate is there because the 
    665                          * rate set is checked when the station associates. */ 
    666                         /* NB: the rate set is assumed sorted */ 
    667                         for (; (srate >= 0) && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--); 
    668  
    669                         KASSERT(srate >= 0, 
    670                                 ("fixed rate %d not in rate set", vap->iv_fixed_rate)); 
    671  
    672                         sn->static_rate_ndx = srate; 
    673                         ni->ni_txrate = srate; 
    674                         DPRINTF(sc, "%s: %s " MAC_FMT " fixed rate %d%sMbps\n", 
    675                                 dev_info, __func__, MAC_ADDR(ni->ni_macaddr), 
    676                                 sn->rates[srate].rate / 2, 
    677                                 (sn->rates[srate].rate % 2) ? ".5 " : " "); 
    678                         return; 
    679                 } 
    680  
    681                 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 
    682                         if (sn->rates[x].rix == 0xff) { 
    683                                 DPRINTF(sc, "%s: %s ignore bogus rix at %d\n", 
    684                                         dev_info, __func__, x); 
    685                                 continue; 
    686                         } 
    687  
    688                         sn->rs_rateattempts     [x] = 0; 
    689                         sn->rs_thisprob         [x] = 0; 
    690                         sn->rs_ratesuccess      [x] = 0; 
    691                         sn->rs_probability      [x] = 0; 
    692                         sn->rs_lastrateattempts [x] = 0; 
    693                         sn->rs_lastratesuccess  [x] = 0; 
    694                         sn->rs_succ_hist        [x] = 0; 
    695                         sn->rs_att_hist         [x] = 0; 
    696                         sn->perfect_tx_time     [x] = 
    697                                 calc_usecs_unicast_packet(sc, 1200, 
    698                                                           sn->rates[x].rix, 
    699                                                           0, 0); 
    700                         sn->retry_count         [x] = 1; 
    701                         sn->retry_adjusted_count[x] = 1; 
    702  
    703                         for (retry_index = 2; retry_index < ATH_TXMAXTRY; retry_index++) { 
    704                                 tx_time = calc_usecs_unicast_packet(sc, 1200, sn->rates[x].rix, 0, retry_index); 
    705                                 if (tx_time > ath_segment_size) 
    706                                         break; 
    707                                 sn->retry_count[x] = retry_index; 
    708                                 sn->retry_adjusted_count[x] = retry_index; 
    709                         } 
    710                 } 
    711  
    712 #if 0 
    713                 DPRINTF(sc, "%s: Retry table for this node\n", __func__); 
    714                   for (x = 0; x < ni->ni_rates.rs_nrates; x++) 
    715                              DPRINTF(sc, "%2d  %2d %6d  \n", x, sn->retry_count[x], sn->perfect_tx_time[x]); 
    716 #endif 
    717  
    718                 /* Set the initial rate */ 
    719                 for (ndx = sn->num_rates - 1; ndx > 0; ndx--) 
    720                         if (sn->rates[ndx].rate <= 72) 
    721                                 break; 
    722                 sn->current_rate = ndx; 
    723  
    724                 ni->ni_txrate = sn->current_rate; 
     716 
     717        /* Set the initial rate */ 
     718        for (ndx = sn->num_rates - 1; ndx > 0; ndx--) 
     719                if (sn->rates[ndx].rate <= 72) 
     720                        break; 
     721        sn->current_rate = ndx; 
     722 
     723        ni->ni_txrate = sn->current_rate; 
    725724} 
    726725 
     
    749748ath_timer_function(unsigned long data) 
    750749{ 
    751                struct minstrel_softc *ssc = (struct minstrel_softc *) data; 
    752                struct ath_softc *sc = ssc->sc; 
    753                struct ieee80211com *ic; 
    754                struct net_device *dev = ssc->sc_dev; 
    755                struct timer_list *timer; 
    756                unsigned int interval = ath_timer_interval; 
    757  
    758                if (dev == NULL) 
    759                        DPRINTF(sc, "%s: 'dev' is null in this timer \n", __func__); 
    760  
    761                if (sc == NULL) 
    762                        DPRINTF(sc, "%s: 'sc' is null in this timer\n", __func__); 
    763  
    764                ic = &sc->sc_ic; 
    765  
    766                if (ssc->close_timer_now) 
    767                        return; 
    768  
    769                if (dev->flags & IFF_RUNNING) { 
    770                        sc->sc_stats.ast_rate_calls++; 
    771  
    772                        if (ic->ic_opmode == IEEE80211_M_STA) { 
    773                                struct ieee80211vap *tmpvap; 
    774                                TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { 
    775                                        ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */ 
    776                                
    777                        } else 
    778                                     ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc); 
    779                
    780  
    781                if (ic->ic_opmode == IEEE80211_M_STA) 
    782                        interval = ath_timer_interval >> 1; 
    783  
    784                timer  = &(ssc->timer); 
    785                if (timer == NULL) 
    786                        DPRINTF(sc, "%s: timer is null - leave it\n", __func__); 
    787  
    788                timer->expires = jiffies + ((HZ * interval) / 1000); 
    789                add_timer(timer); 
     750        struct minstrel_softc *ssc = (struct minstrel_softc *) data; 
     751        struct ath_softc *sc = ssc->sc; 
     752        struct ieee80211com *ic; 
     753        struct net_device *dev = ssc->sc_dev; 
     754        struct timer_list *timer; 
     755        unsigned int interval = ath_timer_interval; 
     756 
     757        if (dev == NULL) 
     758                DPRINTF(sc, "%s: 'dev' is null in this timer \n", __func__); 
     759 
     760        if (sc == NULL) 
     761                DPRINTF(sc, "%s: 'sc' is null in this timer\n", __func__); 
     762 
     763        ic = &sc->sc_ic; 
     764 
     765        if (ssc->close_timer_now) 
     766                return; 
     767 
     768        if (dev->flags & IFF_RUNNING) { 
     769                sc->sc_stats.ast_rate_calls++; 
     770 
     771                if (ic->ic_opmode == IEEE80211_M_STA) { 
     772                        struct ieee80211vap *tmpvap; 
     773                        TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { 
     774                                ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */ 
     775                       
     776                } else 
     777                        ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc); 
     778       
     779 
     780        if (ic->ic_opmode == IEEE80211_M_STA) 
     781                interval = ath_timer_interval >> 1; 
     782 
     783        timer  = &(ssc->timer); 
     784        if (timer == NULL) 
     785                DPRINTF(sc, "%s: timer is null - leave it\n", __func__); 
     786 
     787        timer->expires = jiffies + ((HZ * interval) / 1000); 
     788        add_timer(timer); 
    790789} 
    791790 
     
    793792ath_rate_statistics(void *arg, struct ieee80211_node *ni) 
    794793{ 
    795                struct ath_node *an = (struct ath_node *) ni; 
    796                struct ieee80211_rateset *rs = &ni->ni_rates; 
    797                struct minstrel_node *rn = ATH_NODE_MINSTREL(an); 
    798                unsigned int i; 
    799                u_int32_t p; 
    800                u_int32_t micro_secs; 
    801                u_int32_t max_prob,    index_max_prob; 
    802                u_int32_t max_tp,      index_max_tp,      index_max_tp2; 
    803  
    804                /* Calculate statistics for each date rate in the table */ 
    805                /* 'micro_secs' is the time to transmit 1200 bytes, or 9600 bits. */ 
    806                for (i = 0; i < rs->rs_nrates; i++) { 
    807                        micro_secs = rn->perfect_tx_time[i]; 
    808                        if (micro_secs == 0) 
    809                                micro_secs = ONE_SECOND; 
    810  
    811                            if (rn->rs_rateattempts[i] != 0) { 
    812                                     p = (rn->rs_ratesuccess[i] * 18000) / rn->rs_rateattempts[i]; 
    813                                     rn->rs_succ_hist[i] += rn->rs_ratesuccess[i]; 
    814                                     rn->rs_att_hist[i]  += rn->rs_rateattempts[i]; 
    815                                rn->rs_thisprob[i] = p; 
    816                                p = ((p * (100 - ath_ewma_level)) + (rn->rs_probability[i] * ath_ewma_level)) / 100; 
    817                                rn->rs_probability[i] = p; 
    818                                rn->rs_this_tp[i] = p * (ONE_SECOND / micro_secs); 
    819                                rn->rs_lastratesuccess[i] = rn->rs_ratesuccess[i]; 
    820                                rn->rs_lastrateattempts[i] = rn->rs_rateattempts[i]; 
    821                                     rn->rs_ratesuccess[i] = 0; 
    822                                     rn->rs_rateattempts[i] = 0; 
    823                        } else { 
    824                                rn->rs_lastratesuccess[i] = 0; 
    825                                rn->rs_lastrateattempts[i] = 0; 
    826                        
    827  
    828                        /* Sample less often below the 10% chance of success. 
    829                         * Sample less often above the 95% chance of success. 
    830                         * 'rn->rs_probability' has a scale of 0 (0%) to 18000 (100%), which avoids rounding issues.*/ 
    831                        if ((rn->rs_probability[i] > 17100) || (rn->rs_probability[i] < 1800)) { 
    832                                rn->retry_adjusted_count[i] = rn->retry_count[i] >> 1; 
    833                                if (rn->retry_adjusted_count[i] > 2) 
    834                                        rn->retry_adjusted_count[i] = 2; 
    835                        } else 
    836                                rn->retry_adjusted_count[i] = rn->retry_count[i]; 
    837                        if (rn->retry_adjusted_count[i] == 0) 
    838                                rn->retry_adjusted_count[i] = 1; 
    839                
    840  
    841                /* The High speed rates (e.g 54Mbps) is checked last. If 
    842                 * throughput is the same for two rates, we prefer the 
    843                 * lower rate, as this has a better chance of success. */ 
    844                max_prob = 0; 
    845                index_max_prob = 0; 
    846                max_tp = 0; 
    847                index_max_tp  = 0; 
    848                index_max_tp2 = 0; 
    849  
    850                /* This code could have been moved up into the previous 
    851                 * loop. More readable to have it here */ 
    852                for (i = 0; i < rs->rs_nrates; i++) { 
    853                        if (max_tp < rn->rs_this_tp[i]) { 
    854                                index_max_tp = i; 
    855                                max_tp = rn->rs_this_tp[i]; 
    856                        
    857  
    858                        if (max_prob <  rn->rs_probability[i]) { 
    859                                index_max_prob = i; 
    860                                max_prob = rn->rs_probability[i]; 
    861                        
    862                
    863  
    864                max_tp = 0; 
    865                for (i = 0; i < rs->rs_nrates; i++) { 
    866                        if ((i != index_max_tp) && (max_tp < rn->rs_this_tp[i])) { 
    867                                index_max_tp2 = i; 
    868                                max_tp = rn->rs_this_tp[i]; 
    869                        
    870                
    871  
    872                rn->max_tp_rate   = index_max_tp; 
    873                rn->max_tp_rate2  = index_max_tp2; 
    874                rn->max_prob_rate = index_max_prob; 
    875                rn->current_rate  = index_max_tp; 
     794        struct ath_node *an = (struct ath_node *) ni; 
     795        struct ieee80211_rateset *rs = &ni->ni_rates; 
     796        struct minstrel_node *rn = ATH_NODE_MINSTREL(an); 
     797        unsigned int i; 
     798        u_int32_t p; 
     799        u_int32_t micro_secs; 
     800        u_int32_t max_prob,    index_max_prob; 
     801        u_int32_t max_tp,      index_max_tp,      index_max_tp2; 
     802 
     803        /* Calculate statistics for each date rate in the table */ 
     804        /* 'micro_secs' is the time to transmit 1200 bytes, or 9600 bits. */ 
     805        for (i = 0; i < rs->rs_nrates; i++) { 
     806                micro_secs = rn->perfect_tx_time[i]; 
     807                if (micro_secs == 0) 
     808                        micro_secs = ONE_SECOND; 
     809 
     810                if (rn->rs_rateattempts[i] != 0) { 
     811                        p = (rn->rs_ratesuccess[i] * 18000) / rn->rs_rateattempts[i]; 
     812                        rn->rs_succ_hist[i] += rn->rs_ratesuccess[i]; 
     813                        rn->rs_att_hist[i]  += rn->rs_rateattempts[i]; 
     814                        rn->rs_thisprob[i] = p; 
     815                        p = ((p * (100 - ath_ewma_level)) + (rn->rs_probability[i] * ath_ewma_level)) / 100; 
     816                        rn->rs_probability[i] = p; 
     817                        rn->rs_this_tp[i] = p * (ONE_SECOND / micro_secs); 
     818                        rn->rs_lastratesuccess[i] = rn->rs_ratesuccess[i]; 
     819                        rn->rs_lastrateattempts[i] = rn->rs_rateattempts[i]; 
     820                        rn->rs_ratesuccess[i] = 0; 
     821                        rn->rs_rateattempts[i] = 0; 
     822                } else { 
     823                        rn->rs_lastratesuccess[i] = 0; 
     824                        rn->rs_lastrateattempts[i] = 0; 
     825               
     826 
     827                /* Sample less often below the 10% chance of success. 
     828                * Sample less often above the 95% chance of success. 
     829                * 'rn->rs_probability' has a scale of 0 (0%) to 18000 (100%), which avoids rounding issues.*/ 
     830                if ((rn->rs_probability[i] > 17100) || (rn->rs_probability[i] < 1800)) { 
     831                        rn->retry_adjusted_count[i] = rn->retry_count[i] >> 1; 
     832                        if (rn->retry_adjusted_count[i] > 2) 
     833                                rn->retry_adjusted_count[i] = 2; 
     834                } else 
     835                        rn->retry_adjusted_count[i] = rn->retry_count[i]; 
     836                if (rn->retry_adjusted_count[i] == 0) 
     837                        rn->retry_adjusted_count[i] = 1; 
     838       
     839 
     840        /* The High speed rates (e.g 54Mbps) is checked last. If 
     841        * throughput is the same for two rates, we prefer the 
     842        * lower rate, as this has a better chance of success. */ 
     843        max_prob = 0; 
     844        index_max_prob = 0; 
     845        max_tp = 0; 
     846        index_max_tp  = 0; 
     847        index_max_tp2 = 0; 
     848 
     849        /* This code could have been moved up into the previous 
     850        * loop. More readable to have it here */ 
     851        for (i = 0; i < rs->rs_nrates; i++) { 
     852                if (max_tp < rn->rs_this_tp[i]) { 
     853                        index_max_tp = i; 
     854                        max_tp = rn->rs_this_tp[i]; 
     855               
     856 
     857                if (max_prob <  rn->rs_probability[i]) { 
     858                        index_max_prob = i; 
     859                        max_prob = rn->rs_probability[i]; 
     860               
     861       
     862 
     863        max_tp = 0; 
     864        for (i = 0; i < rs->rs_nrates; i++) { 
     865                if ((i != index_max_tp) && (max_tp < rn->rs_this_tp[i])) { 
     866                        index_max_tp2 = i; 
     867                        max_tp = rn->rs_this_tp[i]; 
     868               
     869       
     870 
     871        rn->max_tp_rate   = index_max_tp; 
     872        rn->max_tp_rate2  = index_max_tp2; 
     873        rn->max_prob_rate = index_max_prob; 
     874        rn->current_rate  = index_max_tp; 
    876875} 
    877876 
     
    879878ath_rate_attach(struct ath_softc *sc) 
    880879{ 
    881                struct minstrel_softc *osc; 
    882                DPRINTF(sc, "%s: %s\n", dev_info, __func__); 
    883  
    884                _MOD_INC_USE(THIS_MODULE, return NULL); 
    885                osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC); 
    886                if (osc == NULL) { 
    887                            _MOD_DEC_USE(THIS_MODULE); 
    888                        return NULL; 
    889                
    890  
    891                osc->arc.arc_space = sizeof(struct minstrel_node); 
    892                osc->arc.arc_vap_space = 0; 
    893  
    894                osc->close_timer_now = 0; 
    895                init_timer(&osc->timer); 
     880        struct minstrel_softc *osc; 
     881        DPRINTF(sc, "%s: %s\n", dev_info, __func__); 
     882 
     883        _MOD_INC_USE(THIS_MODULE, return NULL); 
     884        osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC); 
     885        if (osc == NULL) { 
     886                _MOD_DEC_USE(THIS_MODULE); 
     887                return NULL; 
     888       
     889 
     890        osc->arc.arc_space = sizeof(struct minstrel_node); 
     891        osc->arc.arc_vap_space = 0; 
     892 
     893        osc->close_timer_now = 0; 
     894        init_timer(&osc->timer); 
    896895        osc->sc          = sc; 
    897                osc->sc_dev      = sc->sc_dev; 
    898                osc->timer.function = ath_timer_function; 
    899                osc->timer.data = (unsigned long)osc; 
    900  
    901                osc->timer.expires = jiffies + HZ; 
    902                add_timer(&osc->timer); 
    903  
    904                return &osc->arc; 
     896        osc->sc_dev      = sc->sc_dev; 
     897        osc->timer.function = ath_timer_function; 
     898        osc->timer.data = (unsigned long)osc; 
     899 
     900        osc->timer.expires = jiffies + HZ; 
     901        add_timer(&osc->timer); 
     902 
     903        return &osc->arc; 
    905904} 
    906905 
     
    919918ath_proc_read_nodes(struct ieee80211vap *vap, char *buf, int space) 
    920919{ 
    921                 char *p = buf; 
    922                 struct ieee80211_node *ni; 
    923                 struct ath_node *an; 
    924                 struct minstrel_node *odst; 
    925                 struct ieee80211_node_table *nt = 
    926                             (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; 
    927                 unsigned int x = 0; 
    928                 unsigned int this_tp, this_prob, this_eprob; 
    929                         struct ath_softc *sc = vap->iv_ic->ic_dev->priv;; 
    930  
    931                 IEEE80211_NODE_TABLE_LOCK_IRQ(nt); 
    932                 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 
    933                         /* Assume each node needs 1500 bytes */ 
    934                         if ((buf + space) < (p + 1500)) { 
    935                                 if ((buf + space) > (p + 100)) { 
    936                                         p += sprintf(p, "out of room for node " MAC_FMT "\n\n", MAC_ADDR(ni->ni_macaddr)); 
    937                                         break; 
    938                                 } 
    939                                 DPRINTF(sc, "%s: out of memeory to write tall of the nodes\n", __func__); 
    940                                     break; 
     920        char *p = buf; 
     921        struct ieee80211_node *ni; 
     922        struct ath_node *an; 
     923        struct minstrel_node *odst; 
     924        struct ieee80211_node_table *nt = 
     925                (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; 
     926        unsigned int x = 0; 
     927        unsigned int this_tp, this_prob, this_eprob; 
     928        struct ath_softc *sc = vap->iv_ic->ic_dev->priv;; 
     929 
     930        IEEE80211_NODE_TABLE_LOCK_IRQ(nt); 
     931        TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 
     932                /* Assume each node needs 1500 bytes */ 
     933                if ((buf + space) < (p + 1500)) { 
     934                        if ((buf + space) > (p + 100)) { 
     935                                p += sprintf(p, "out of room for node " MAC_FMT "\n\n", MAC_ADDR(ni->ni_macaddr)); 
     936                                break; 
    941937                        } 
    942                         an = ATH_NODE(ni); 
    943                         odst = ATH_NODE_MINSTREL(an); 
    944                         /* Skip ourself */ 
    945                         if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ni->ni_macaddr)) 
    946                                 continue; 
    947  
    948                         p += sprintf(p, "rate data for node: " MAC_FMT "\n", MAC_ADDR(ni->ni_macaddr)); 
    949                         p += sprintf(p, "rate     throughput  ewma prob   this prob  this succ/attempt   success    attempts\n"); 
    950                         for (x = 0; x < odst->num_rates; x++) { 
    951                                 p += sprintf(p, "%s", 
    952                                              (x == odst->current_rate) ? "T" : " "); 
    953  
    954                                 p += sprintf(p, "%s", 
    955                                              (x == odst->max_tp_rate2) ? "t" : " "); 
    956  
    957                                 p += sprintf(p, "%s", 
    958                                              (x == odst->max_prob_rate) ? "P" : " "); 
    959  
    960                                 p += sprintf(p, "%3u%s", 
    961                                              odst->rates[x].rate / 2, 
    962                                              (odst->rates[x].rate & 0x1) != 0 ? ".5" : "  "); 
    963  
    964                                 this_tp = ((odst->rs_this_tp[x] / 18000) * 96) >> 10; 
    965                                 this_prob = odst->rs_thisprob[x] / 18; 
    966                                 this_eprob = odst->rs_probability[x] / 18; 
    967                                 p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        %3u(%3u)   %8llu    %8llu\n", 
    968                                              this_tp / 10, this_tp % 10, 
    969                                              this_eprob / 10, this_eprob % 10, 
    970                                              this_prob / 10, this_prob % 10, 
    971                                              odst->rs_lastratesuccess[x], 
    972                                              odst->rs_lastrateattempts[x], 
    973                                              (unsigned long long)odst->rs_succ_hist[x], 
    974                                              (unsigned long long)odst->rs_att_hist[x]); 
    975                         } 
    976                         p += sprintf(p, "\n"); 
    977  
    978                         p += sprintf(p, "Total packet count::    ideal %d      lookaround %d\n\n", odst->packet_count, odst->sample_count); 
    979                 } 
    980                 IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); 
    981  
    982                 return (p - buf); 
     938                        DPRINTF(sc, "%s: out of memeory to write tall of the nodes\n", __func__); 
     939                        break; 
     940                } 
     941                an = ATH_NODE(ni); 
     942                odst = ATH_NODE_MINSTREL(an); 
     943                /* Skip ourself */ 
     944                if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ni->ni_macaddr)) 
     945                        continue; 
     946 
     947                p += sprintf(p, "rate data for node: " MAC_FMT "\n", MAC_ADDR(ni->ni_macaddr)); 
     948                p += sprintf(p, "  rate   throughput ewma prob this prob this succ/attempt  success attempts\n"); 
     949                for (x = 0; x < odst->num_rates; x++) { 
     950                        p += sprintf(p, "%c", 
     951                                     (x == odst->current_rate) ? 'T' : ' '); 
     952 
     953                        p += sprintf(p, "%c", 
     954                                     (x == odst->max_tp_rate2) ? 't' : ' '); 
     955 
     956                        p += sprintf(p, "%c", 
     957                                     (x == odst->max_prob_rate) ? 'P' : ' '); 
     958 
     959                        p += sprintf(p, " %2u%s", 
     960                                     odst->rates[x].rate / 2, 
     961                                     (odst->rates[x].rate & 0x1) != 0 ? ".5" : "  "); 
     962 
     963                        this_tp = ((odst->rs_this_tp[x] / 18000) * 96) >> 10; 
     964                        this_prob = odst->rs_thisprob[x] / 18; 
     965                        this_eprob = odst->rs_probability[x] / 18; 
     966                        p += sprintf(p, "       %2u.%1u      %2u.%1u  %6u.%1u        %3u(%3u)   %8llu %8llu\n", 
     967                                     this_tp / 10, this_tp % 10, 
     968                                     this_eprob / 10, this_eprob % 10, 
     969                                     this_prob / 10, this_prob % 10, 
     970                                     odst->rs_lastratesuccess[x], 
     971                                     odst->rs_lastrateattempts[x], 
     972                                     (unsigned long long)odst->rs_succ_hist[x], 
     973                                     (unsigned long long)odst->rs_att_hist[x]); 
     974                } 
     975                p += sprintf(p, "\n"); 
     976 
     977                p += sprintf(p, "Total packet count::    ideal %d      lookaround %d\n\n", odst->packet_count, odst->sample_count); 
     978        } 
     979        IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); 
     980 
     981        return (p - buf); 
    983982} 
    984983 
     
    986985ath_proc_ratesample_open(struct inode *inode, struct file *file) 
    987986{ 
    988                struct proc_ieee80211_priv *pv = NULL; 
    989                struct proc_dir_entry *dp = PDE(inode); 
    990                struct ieee80211vap *vap = dp->data; 
    991  
    992                if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), 
    993                                                     GFP_KERNEL))) 
    994                            return -ENOMEM; 
    995  
    996                /* Initially allocate both read and write buffers */ 
    997                pv = (struct proc_ieee80211_priv *) file->private_data; 
    998                memset(pv, 0, sizeof(struct proc_ieee80211_priv)); 
    999                pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
    1000                if (!pv->rbuf) { 
    1001                            kfree(pv); 
    1002                            return -ENOMEM; 
    1003                
    1004                pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
    1005                if (!pv->wbuf) { 
    1006                            vfree(pv->rbuf); 
    1007                            kfree(pv); 
    1008                            return -ENOMEM; 
    1009                
    1010  
    1011                memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE); 
    1012                memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE); 
    1013                pv->max_wlen = MAX_PROC_IEEE80211_SIZE; 
    1014                pv->max_rlen = MAX_PROC_IEEE80211_SIZE; 
    1015  
    1016                /* Now read the data into the buffer */ 
    1017                pv->rlen = ath_proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE); 
    1018                return 0; 
     987        struct proc_ieee80211_priv *pv = NULL; 
     988        struct proc_dir_entry *dp = PDE(inode); 
     989        struct ieee80211vap *vap = dp->data; 
     990 
     991        if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), 
     992                                          GFP_KERNEL))) 
     993                return -ENOMEM; 
     994 
     995        /* Initially allocate both read and write buffers */ 
     996        pv = (struct proc_ieee80211_priv *) file->private_data; 
     997        memset(pv, 0, sizeof(struct proc_ieee80211_priv)); 
     998        pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
     999        if (!pv->rbuf) { 
     1000                kfree(pv); 
     1001                return -ENOMEM; 
     1002       
     1003        pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); 
     1004        if (!pv->wbuf) { 
     1005                vfree(pv->rbuf); 
     1006                kfree(pv); 
     1007                return -ENOMEM; 
     1008       
     1009 
     1010        memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE); 
     1011        memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE); 
     1012        pv->max_wlen = MAX_PROC_IEEE80211_SIZE; 
     1013        pv->max_rlen = MAX_PROC_IEEE80211_SIZE; 
     1014 
     1015        /* Now read the data into the buffer */ 
     1016        pv->rlen = ath_proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE); 
     1017        return 0; 
    10191018} 
    10201019 
    10211020static struct file_operations ath_proc_ratesample_ops = { 
    1022                .read = NULL, 
    1023                .write = NULL, 
    1024                .open = ath_proc_ratesample_open, 
    1025                .release = NULL, 
     1021        .read = NULL, 
     1022        .write = NULL, 
     1023        .open = ath_proc_ratesample_open, 
     1024        .release = NULL, 
    10261025}; 
    10271026 
     
    10291028ath_rate_dynamic_proc_register(struct ieee80211vap *vap) 
    10301029{ 
    1031                /* Create proc entries for the rate control algorithm */ 
    1032                ieee80211_proc_vcreate(vap, &ath_proc_ratesample_ops, "rate_info"); 
     1030        /* Create proc entries for the rate control algorithm */ 
     1031        ieee80211_proc_vcreate(vap, &ath_proc_ratesample_ops, "rate_info"); 
    10331032} 
    10341033 
     
    10361035 
    10371036static struct ieee80211_rate_ops ath_rate_ops = { 
    1038                .ratectl_id = IEEE80211_RATE_MINSTREL, 
    1039                .node_init = ath_rate_node_init, 
    1040                .node_cleanup = ath_rate_node_cleanup, 
    1041                .findrate = ath_rate_findrate, 
    1042                .get_mrr = ath_rate_get_mrr, 
    1043                .tx_complete = ath_rate_tx_complete, 
    1044                .newassoc = ath_rate_newassoc, 
    1045                .newstate = ath_rate_newstate, 
    1046                .attach = ath_rate_attach, 
    1047                .detach = ath_rate_detach, 
    1048                .dynamic_proc_register = ath_rate_dynamic_proc_register, 
     1037        .ratectl_id = IEEE80211_RATE_MINSTREL, 
     1038        .node_init = ath_rate_node_init, 
     1039        .node_cleanup = ath_rate_node_cleanup, 
     1040        .findrate = ath_rate_findrate, 
     1041        .get_mrr = ath_rate_get_mrr, 
     1042        .tx_complete = ath_rate_tx_complete, 
     1043        .newassoc = ath_rate_newassoc, 
     1044        .newstate = ath_rate_newstate, 
     1045        .attach = ath_rate_attach, 
     1046        .detach = ath_rate_detach, 
     1047        .dynamic_proc_register = ath_rate_dynamic_proc_register, 
    10491048}; 
    10501049 
     
    10601059static int __init ath_rate_minstrel_init(void) 
    10611060{ 
    1062                printk(KERN_INFO "%s: Minstrel automatic rate control " 
    1063                       "algorithm %s\n", dev_info, version); 
    1064                printk(KERN_INFO "%s: look around rate set to %d%%\n", 
    1065                       dev_info, ath_lookaround_rate); 
    1066                printk(KERN_INFO "%s: EWMA rolloff level set to %d%%\n", 
    1067                       dev_info, ath_ewma_level); 
    1068                printk(KERN_INFO "%s: max segment size in the mrr set " 
    1069                       "to %d us\n", dev_info, ath_segment_size); 
    1070                return ieee80211_rate_register(&ath_rate_ops); 
     1061        printk(KERN_INFO "%s: Minstrel automatic rate control " 
     1062               "algorithm %s\n", dev_info, version); 
     1063        printk(KERN_INFO "%s: look around rate set to %d%%\n", 
     1064               dev_info, ath_lookaround_rate); 
     1065        printk(KERN_INFO "%s: EWMA rolloff level set to %d%%\n", 
     1066               dev_info, ath_ewma_level); 
     1067        printk(KERN_INFO "%s: max segment size in the mrr set " 
     1068               "to %d us\n", dev_info, ath_segment_size); 
     1069        return ieee80211_rate_register(&ath_rate_ops); 
    10711070} 
    10721071module_init(ath_rate_minstrel_init); 
     
    10741073static void __exit ath_rate_minstrel_exit(void) 
    10751074{ 
    1076                ieee80211_rate_unregister(&ath_rate_ops); 
    1077                printk(KERN_INFO "%s: unloaded\n", dev_info); 
     1075        ieee80211_rate_unregister(&ath_rate_ops); 
     1076        printk(KERN_INFO "%s: unloaded\n", dev_info); 
    10781077} 
    10791078module_exit(ath_rate_minstrel_exit); 
  • madwifi/branches/madwifi-dfs/ath_rate/minstrel/minstrel.txt

    r2715 r3361  
    1  
    2 Minstrel 
     1minstrel 
    32 
    43Introduction 
    5 ================================================================== 
     4============================================================================== 
     5 
    66This code is called minstrel, because we have taken a wandering minstrel 
    7 approach. Wander around the different rates, singing wherever you 
    8 can. And then, look at the performance, 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, 
     7approach. Wander around the different rates, singing wherever you can. And 
     8then, look at the performance, and make a choice. Note that the wandering 
     9minstrel will always wander in directions where he/she feels he/she will get 
     10paid the best for his/her work. 
     11 
     12The minstrel autorate selection algorithm is an EWMA based algorithm and is 
     13derived from 
     14 
     15 1) An initial rate module we released in 2005, 
    1516  http://sourceforge.net/mailarchive/forum.php?forum_id=33966&max_rows=25&style=flat&viewmonth=200501&viewday=5 
    1617 
    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. 
     18 2) the "sample" module in the madwifi-ng source tree. 
     19 
     20The code released in 2005 had some algorithmic and implementation flaws (one 
     21of which was that it was based on the old madwifi codebase) and was shown to 
     22be unstable. Performance of the sample module is poor 
     23(http://www.madwifi.org/ticket/989), and we have observed similar issues. 
    2424 
    2525We noted: 
    26  1)The rate chosen by sample did not alter to match changes in the radio 
     26 
     27 1) The rate chosen by sample did not alter to match changes in the radio 
    2728    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 
     29 
     30 2) Higher throughput (between two nodes) could often be achieved by fixing 
     31    the bitrate of both nodes to some value. 
     32 
     33 3) After a long period of operation, "sample" appeared to be stuck in a low 
    3134    data rate, and would not move to a higher data rate. 
    3235 
    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. 
     36We examined the code in sample, and decided the best approach was a rewrite 
     37based on sample and the module we released in January 2005. 
    3538 
    3639Theory of operation 
    37 ================================================================== 
    38  
    39 We defined the measure of successfulness (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  
     40============================================================================== 
     41 
     42We defined the measure of successfulness (of packet transmission) as 
     43 
     44                                  Mega bits transmitted 
     45    Prob_success_transmission *  ----------------------- 
     46                                      elapsed time 
     47 
     48This measure of successfulness will therefore adjust the transmission speed to 
    4649get 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. 
     50means that the 1 Mbits rate (which has a very high probability of successful 
     51transmission) will not be used in preference to the 11 Mbits rate. 
    4952 
    5053We decided that the module should record the successfulness of all packets 
     
    5558rates regarded as non optimal. 
    5659 
    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 
     6010 times a second (this frequency is alterable by changing the driver code) a 
     61timer fires, which evaluates the statistics table. EWMA calculations 
    5962(described below) are used to process the success history of each rate. On 
    6063completion 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. 
     64best throughput, second best throughput, and highest probability of success. 
    6265This data is used for populating the retry chain during the next 100 ms. 
    6366 
    6467As stated above, the minstrel algorithm collects statistics from all packet 
    65 attempts. Minstrel spends a particular percentage of frames, doing "look 
    66 around" 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 lookaround 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  
     68attempts. Minstrel spends a particular percentage of frames, doing "look 
     69around" i.e. randomly trying other rates, to gather statistics. The percentage 
     70of "look around" frames, is set at boot time via the module parameter 
     71"ath_lookaround_rate" and defaults to 10%. The distribution of lookaround 
     72frames is also randomised somewhat to avoid any potential "strobing" of 
     73lookaround between similar nodes. 
     74 
     75TCP theory tells us that each packet sent must be delivered in under 26 
     76ms. Any longer duration, and the TCP network layers will start to back off. A 
     77delay of 26 ms implies that there is congestion in the network, and that fewer 
     78packets should be injected to the device. Our conclusion was to adjust the 
     79retry chain of each packet so the retry chain was guaranteed to be finished in 
     80under 26 ms. 
    7881 
    7982Retry Chain 
    80 ================================================================== 
     83============================================================================== 
     84 
    8185The HAL provides a multirate retry chain - which consists of four 
    8286segments. Each segment is an advisement to the HAL to try to send the current 
     
    8488successfully transmitted, the remainder of the retry chain is 
    8589ignored. 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, 
     90get the packet out in under 26 ms, or fail. We provided a module parameter, 
    8791ath_segment_size, which has units of microseconds, and specifies the maximum 
    8892duration one segment in the retry chain can last. This module parameter has a 
     
    9195 
    9296There 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 
     9726 ms for the retry chain length is "meaningless". However, one may argue that 
    9498if the packet was not transmitted after some time period, it should 
    9599fail. Further, one does expect UDP packets to fail in transmission. We leave 
     
    116120After some discussion, we have adjusted the code so that the lowest rate is 
    117121never 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 The retry chain above does "work", but performance is suboptimal. The 
    130 key problem being that when the link is good, too much time is spent 
    131 sampling the slower rates. Thus, for two nodes adjacent to each other, 
    132 the throughput between them was several megabits/sec below using a 
    133 fixed rate. The view was that minstrel should not sample at the slower 
    134 rates if the link is doing well. However, if the link deteriorates, 
    135 minstrel should immediately sample at the lower rates. 
    136  
    137 Some time later, we realised that the only way to code this reliably 
    138 was to use the retry chain as the method of determining if the slower 
    139 rates are sampled. The retry chain was modified as: 
     122for management packets, this rate must be working. Alternatively, the link is 
     123set up with management packets, data packets are acknowledged with management 
     124packets. Should the lowest rate stop working, the link is going to die 
     125reasonably soon. 
     126 
     127Analysis of information in the /proc/net/madwifi/athX/rate_info file showed 
     128that the system was sampling too hard at some rates. For those rates that 
     129never work (54mb, 500m range) there is no point in sending 10 sample packets 
     130(< 6 ms time). Consequently, for the very very low probability rates, we 
     131sample at most twice. 
     132 
     133The retry chain above does "work", but performance is suboptimal. The key 
     134problem being that when the link is good, too much time is spent sampling the 
     135slower rates. Thus, for two nodes adjacent to each other, the throughput 
     136between them was several Mbits below using a fixed rate. The view was that 
     137minstrel should not sample at the slower rates if the link is doing 
     138well. However, if the link deteriorates, minstrel should immediately sample at 
     139the lower rates. 
     140 
     141Some time later, we realised that the only way to code this reliably was to 
     142use the retry chain as the method of determining if the slower rates are 
     143sampled. The retry chain was modified as: 
    140144 
    141145Try |         Lookaround rate              | Normal rate          
     
    150154current best throughput, the randomly selected rate is placed second in the 
    151155chain. If the link is not good, then there will be data collected at the 
    152 randomly selected rate.  Thus, if the best throughput rate is currently 54mbs, 
    153 the only time slower rates are sampled is when a packet fails in 
     156randomly selected rate.  Thus, if the best throughput rate is currently 54 
     157Mbits, the only time slower rates are sampled is when a packet fails in 
    154158transmission. Consequently, if the link is ideal, all packets will be sent at 
    155 the full rate of 54mbs. Which is good. 
     159the full rate of 54 Mbits. Which is good. 
    156160 
    157161EWMA 
    158 ================================================================== 
     162============================================================================== 
    159163 
    160164The EWMA calculation is carried out 10 times a second, and is run for each 
    161 rate. This calculation has a smoothing effect, so that new results have 
    162 a reasonable (but not large) influence on the selected rate. However, with 
    163 time, a series of new results in some particular direction will predominate.  
    164 Given this smoothing, we can use words like inertia to describe the EWMA. 
    165  
    166 By "new results", we mean the results collected in the just completed 100ms 
     165rate. This calculation has a smoothing effect, so that new results have a 
     166reasonable (but not large) influence on the selected rate. However, with time, 
     167a series of new results in some particular direction will predominate. Given 
     168this smoothing, we can use words like inertia to describe the EWMA. 
     169 
     170By "new results", we mean the results collected in the just completed 100 ms 
    167171interval. Old results are the EWMA scaling values from before the just 
    168 completed 100ms interval. 
     172completed 100 ms interval. 
    169173 
    170174EWMA scaling is set by the module parameter ath_ewma_level, and defaults to 
    171 75%. A value of 0% means use only the new results, ignore the old results. 
    172 A value of 99% means use the old results, with a tiny influence from the new 
    173 results.  
    174  
    175  
     17575%. A value of 0% means use only the new results, ignore the old results.  A 
     176value of 99% means use the old results, with a tiny influence from the new 
     177results. 
    176178 
    177179The calculation (performed for each rate, at each timer interrupt) of the 
    178          probability of success is: 
     180probability of success is: 
    179181 
    180182         Psucces_this_time_interval * (100 - ath_ewma_level) + (Pold * ath_ewma_level) 
     
    193195inserted), then Pnew is calculated from above with Pold set to 0. 
    194196 
    195 The appropriate update interval was selected on the basis of choosing a compromise 
    196 between 
    197  *collecting enough success/failure information to be meaningful 
    198  *minimising the amount of cpu time spent do the updates 
    199  *providing a means to recover quickly enough from a bad rate selection. 
    200 The first two points are self explanatory. When there is a sudden change in the radio 
    201 environment, an update interval of 100ms will mean that the rates marked as optimal are 
    202 very quickly marked as poor. Consequently, the sudden change in radio environment will 
    203 mean that minstrel will very quickly switch to a better rate.  
     197The appropriate update interval was selected on the basis of choosing a 
     198compromise between 
     199 
     200 * collecting enough success/failure information to be meaningful 
     201 * minimising the amount of cpu time spent do the updates 
     202 * providing a means to recover quickly enough from a bad rate selection. 
     203 
     204The first two points are self explanatory. When there is a sudden change in 
     205the radio environment, an update interval of 100 ms will mean that the rates 
     206marked as optimal are very quickly marked as poor. Consequently, the sudden 
     207change in radio environment will mean that minstrel will very quickly switch 
     208to a better rate. 
    204209 
    205210A sudden change in the transmission probabilities will happen when the 
     
    210215layers. 
    211216 
    212  
    213  
    214217Module Parameters 
    215 ==================================================== 
     218============================================================================== 
    216219The module has three parameters: 
    217220 
     
    226229 
    227230Test Network 
    228 ==================================================== 
    229 We used three computers in our test network.  The first two, equipped with 
     231============================================================================== 
     232 
     233We used three computers in our test network. The first two, equipped with 
    230234atheros cards running in adhoc mode. We used a program that sends a fixed 
    231235number of TCP packets between computers, and reports on the data rate. The 
     
    239243 
    240244It was from monitoring the results on the third computer that we started to 
    241 get some confidence in the correctness of the code. We observed TCP 
    242 backoffs (described above) on this box. There was much celebration when the 
    243 throughput increased simply because the retry chain was finished in under 26 
    244 ms. 
    245  
    246 Our view was that throughput between the two computers should be as 
    247 close as possible (or better than) what can be achieved by setting 
    248 both ends to fixed rates. Thus, if setting the both ends to fixed 
    249 rates significantly increases the throughput, a reasonable conclusion 
    250 is that a fault exists in the adaptive rate rate. 
     245get some confidence in the correctness of the code. We observed TCP backoffs 
     246(described above) on this box. There was much celebration when the throughput 
     247increased simply because the retry chain was finished in under 26 ms. 
     248 
     249Our view was that throughput between the two computers should be as close as 
     250possible (or better than) what can be achieved by setting both ends to fixed 
     251rates. Thus, if setting the both ends to fixed rates significantly increases 
     252the throughput, a reasonable conclusion is that a fault exists in the adaptive 
     253rate rate. 
    251254 
    252255We recorded throughputs (with minstrel) that are within 10% of what is 
    253 achieved with the experimentally determined optimum fixed rate.  
     256achieved with the experimentally determined optimum fixed rate. 
    254257 
    255258 
    256259Notes on Timing 
    257 ==================================================== 
    258  
    259 As noted above, Minstrel calculates the throughput for each rate. This 
    260 calculation (using a packet of size 1200 bytes) determines the 
    261 transmission time on the radio medium. In these calculations, we assume a 
    262 contention window min and max value of 4 and 10 microseconds respectively. 
     260============================================================================== 
     261 
     262As noted above, minstrel calculates the throughput for each rate. This 
     263calculation (using a packet of size 1200 bytes) determines the transmission 
     264time on the radio medium. In these calculations, we assume a contention window 
     265min and max value of 4 and 10 microseconds respectively. 
    263266 
    264267Further, calculation of the transmission time is required so that we can 
    265 guarantee a packet is transmitted (or dropped) in a minimum time period. 
    266 The transmission  time is used in determining how many times a packet 
    267 is transmitted in each segment of the retry chain. 
     268guarantee a packet is transmitted (or dropped) in a minimum time period.  The 
     269transmission time is used in determining how many times a packet is 
     270transmitted in each segment of the retry chain. 
    268271 
    269272Indeed, the card will supply the cwmin/cwmax values directly 
    270273 iwpriv if_name get_cwmin <0|1|2|3> <0|1> 
    271274 
    272 We have not made direct calls to determine cwmin/cwmax - this is an area 
    273 for future work. Indeed, the cwmin/cwmax determination code could check to 
    274 see if the user has altered these values with the appropriate iwpriv. 
    275  
    276 The contention window size does vary with traffic class. For example, 
    277 video and voice have a contention window min of 3 and 2 microseconds 
     275We have not made direct calls to determine cwmin/cwmax - this is an area for 
     276future work. Indeed, the cwmin/cwmax determination code could check to see if 
     277the user has altered these values with the appropriate iwpriv. 
     278 
     279The contention window size does vary with traffic class. For example, video 
     280and voice have a contention window min of 3 and 2 microseconds 
    278281respectively. Currently, minstrel does not check traffic class. 
    279282 
    280 Calculating the throughputs based on traffic class and bit rate and 
    281 variable packet size will significantly complicate the code and require 
    282 many more sample packets. More sample packets will lower the throughput 
    283 achieved. Thus, our view is that for this release, we should take a simple 
    284 (but reasonable) approach that works stably and gives good throughputs. 
     283Calculating the throughputs based on traffic class and bit rate and variable 
     284packet size will significantly complicate the code and require many more 
     285sample packets. More sample packets will lower the throughput achieved. Thus, 
     286our view is that for this release, we should take a simple (but reasonable) 
     287approach that works stably and gives good throughputs. 
    285288 
    286289 
     
    292295 
    293296Internal variable reporting 
    294 ==================================================== 
     297============================================================================== 
     298 
    295299The minstrel algorithm reports to the proc file system its internal 
    296300statistics, which can be viewed as text. A sample output is below: 
     
    326330T, t, and P respectively. 
    327331 
    328 The statistics gathered in the last 100ms time period are displayed in the 
     332The statistics gathered in the last 100 ms time period are displayed in the 
    329333"this prob" and "this succ/attempt" columns. 
    330334 
     
    335339analysing reports from the hal. The word "attempt" or "attempts" means the 
    336340count of packets that we transmitted. Thus, the number in the success column 
    337 will always be lower than the number in the attempts column.  
    338  
    339  
    340 When the two nodes are brought closer together, the statistics start changing, 
    341 and you see more successful attempts at the higher rates. The ewma prob at the 
    342 higher rates increases and then most packets are conveyed at the higher rates. 
    343  
    344 When the rate is not on auto, but fixed, this table is still 
    345 available, and will report the throughput etc for the current bit 
    346 rate. Changing the rate from auto to fixed to auto will completely 
    347 reset this table, and the operation of the minstrel module. 
    348  
    349  
    350  
    351  
    352  
    353  
    354  
    355  
    356  
     341will always be lower than the number in the attempts column. 
     342 
     343When the two nodes are brought closer together, the statistics starts 
     344changing, and you see more successful attempts at the higher rates. The ewma 
     345prob at the higher rates increases and then most packets are conveyed at the 
     346higher rates. 
     347 
     348When the rate is not on auto, but fixed, this table is still available, and 
     349will report the throughput etc for the current bit rate. Changing the rate 
     350from auto to fixed to auto will completely reset this table, and the operation 
     351of the minstrel module.