Changeset 3361
- Timestamp:
- 02/21/08 23:04:34 (4 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
madwifi/branches/madwifi-dfs/ath_rate/minstrel/minstrel.c
r3255 r3361 125 125 #define DPRINTF(sc, _fmt, ...) do { \ 126 126 if (sc->sc_debug & ATH_DEBUG_RATE) \ 127 printk( _fmt, __VA_ARGS__);\127 printk("%s: " _fmt, SC_DEV_NAME(sc), __VA_ARGS__); \ 128 128 } while (0) 129 129 #else … … 141 141 #define ENABLE_MRR 1 142 142 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 145 static 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 149 151 static int ath_lookaround_rate = 10; 150 152 static int ath_ewma_level = 75; … … 335 337 sn->random_n = (sn->a * sn->random_n) + sn->b; 336 338 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)) { 338 341 sn->sample_count++; 339 342 sn->is_sampling = 1; … … 544 547 545 548 static 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 } 549 ath_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; 579 581 } 580 582 } 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. */ 594 static void 595 ath_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 } 581 710 582 711 #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]); 591 715 #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; 725 724 } 726 725 … … 749 748 ath_timer_function(unsigned long data) 750 749 { 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 } else778 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); 790 789 } 791 790 … … 793 792 ath_rate_statistics(void *arg, struct ieee80211_node *ni) 794 793 { 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 } else836 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. If842 * throughput is the same for two rates, we prefer the843 * 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 previous851 * 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; 876 875 } 877 876 … … 879 878 ath_rate_attach(struct ath_softc *sc) 880 879 { 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); 896 895 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; 905 904 } 906 905 … … 919 918 ath_proc_read_nodes(struct ieee80211vap *vap, char *buf, int space) 920 919 { 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; 941 937 } 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); 983 982 } 984 983 … … 986 985 ath_proc_ratesample_open(struct inode *inode, struct file *file) 987 986 { 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; 1019 1018 } 1020 1019 1021 1020 static 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, 1026 1025 }; 1027 1026 … … 1029 1028 ath_rate_dynamic_proc_register(struct ieee80211vap *vap) 1030 1029 { 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"); 1033 1032 } 1034 1033 … … 1036 1035 1037 1036 static 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, 1049 1048 }; 1050 1049 … … 1060 1059 static int __init ath_rate_minstrel_init(void) 1061 1060 { 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); 1071 1070 } 1072 1071 module_init(ath_rate_minstrel_init); … … 1074 1073 static void __exit ath_rate_minstrel_exit(void) 1075 1074 { 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); 1078 1077 } 1079 1078 module_exit(ath_rate_minstrel_exit); madwifi/branches/madwifi-dfs/ath_rate/minstrel/minstrel.txt
r2715 r3361 1 2 Minstrel 1 minstrel 3 2 4 3 Introduction 5 ================================================================== 4 ============================================================================== 5 6 6 This 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, 7 approach. Wander around the different rates, singing wherever you can. And 8 then, look at the performance, and make a choice. Note that the wandering 9 minstrel will always wander in directions where he/she feels he/she will get 10 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 15 1) An initial rate module we released in 2005, 15 16 http://sourceforge.net/mailarchive/forum.php?forum_id=33966&max_rows=25&style=flat&viewmonth=200501&viewday=5 16 17 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 20 The code released in 2005 had some algorithmic and implementation flaws (one 21 of which was that it was based on the old madwifi codebase) and was shown to 22 be unstable. Performance of the sample module is poor 23 (http://www.madwifi.org/ticket/989), and we have observed similar issues. 24 24 25 25 We 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 27 28 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 31 34 data rate, and would not move to a higher data rate. 32 35 33 We examined the code in sample, and decided the best approach was a 34 rewritebased on sample and the module we released in January 2005.36 We examined the code in sample, and decided the best approach was a rewrite 37 based on sample and the module we released in January 2005. 35 38 36 39 Theory of operation 37 ================================================================== 38 39 We defined the measure of successfulness (of packet transmission) as40 41 mega-bits-transmitted42 Prob_success_transmission * ---------------------- 43 elapsed time44 45 This measure of successfulness will therefore adjust the transmission speed to 40 ============================================================================== 41 42 We defined the measure of successfulness (of packet transmission) as 43 44 Mega bits transmitted 45 Prob_success_transmission * ----------------------- 46 elapsed time 47 48 This measure of successfulness will therefore adjust the transmission speed to 46 49 get the maximum number of data bits through the radio interface. Further, it 47 means that the 1 mb/secrate (which has a very high probability of successful48 transmission) will not be used in preference to the 11 mb/secrate.50 means that the 1 Mbits rate (which has a very high probability of successful 51 transmission) will not be used in preference to the 11 Mbits rate. 49 52 50 53 We decided that the module should record the successfulness of all packets … … 55 58 rates regarded as non optimal. 56 59 57 10 times a second (this frequency is alterable by changing the driver code) 58 atimer fires, which evaluates the statistics table. EWMA calculations60 10 times a second (this frequency is alterable by changing the driver code) a 61 timer fires, which evaluates the statistics table. EWMA calculations 59 62 (described below) are used to process the success history of each rate. On 60 63 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.64 best throughput, second best throughput, and highest probability of success. 62 65 This data is used for populating the retry chain during the next 100 ms. 63 66 64 67 As stated above, the minstrel algorithm collects statistics from all packet 65 attempts. Minstrel spends a particular percentage of frames, doing "look66 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 26 ms. Any73 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 68 attempts. Minstrel spends a particular percentage of frames, doing "look 69 around" i.e. randomly trying other rates, to gather statistics. The percentage 70 of "look around" frames, is set at boot time via the module parameter 71 "ath_lookaround_rate" and defaults to 10%. The distribution of lookaround 72 frames is also randomised somewhat to avoid any potential "strobing" of 73 lookaround between similar nodes. 74 75 TCP theory tells us that each packet sent must be delivered in under 26 76 ms. Any longer duration, and the TCP network layers will start to back off. A 77 delay of 26 ms implies that there is congestion in the network, and that fewer 78 packets should be injected to the device. Our conclusion was to adjust the 79 retry chain of each packet so the retry chain was guaranteed to be finished in 80 under 26 ms. 78 81 79 82 Retry Chain 80 ================================================================== 83 ============================================================================== 84 81 85 The HAL provides a multirate retry chain - which consists of four 82 86 segments. Each segment is an advisement to the HAL to try to send the current … … 84 88 successfully transmitted, the remainder of the retry chain is 85 89 ignored. Selection of the number of retry attempts was based on the desire to 86 get the packet out in under 26 ms, or fail. We provided a module parameter,90 get the packet out in under 26 ms, or fail. We provided a module parameter, 87 91 ath_segment_size, which has units of microseconds, and specifies the maximum 88 92 duration one segment in the retry chain can last. This module parameter has a … … 91 95 92 96 There is some room for movement here - if the traffic is UDP then the limit of 93 26 ms for the retry chain length is "meaningless".However, one may argue that97 26 ms for the retry chain length is "meaningless". However, one may argue that 94 98 if the packet was not transmitted after some time period, it should 95 99 fail. Further, one does expect UDP packets to fail in transmission. We leave … … 116 120 After some discussion, we have adjusted the code so that the lowest rate is 117 121 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 link119 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 diereasonably 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, wesample 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 s ampling 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 atthe 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 aresampled. The retry chain was modified as:122 for management packets, this rate must be working. Alternatively, the link is 123 set up with management packets, data packets are acknowledged with management 124 packets. Should the lowest rate stop working, the link is going to die 125 reasonably soon. 126 127 Analysis of information in the /proc/net/madwifi/athX/rate_info file showed 128 that the system was sampling too hard at some rates. For those rates that 129 never 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 131 sample at most twice. 132 133 The retry chain above does "work", but performance is suboptimal. The key 134 problem being that when the link is good, too much time is spent sampling the 135 slower rates. Thus, for two nodes adjacent to each other, the throughput 136 between them was several Mbits below using a fixed rate. The view was that 137 minstrel should not sample at the slower rates if the link is doing 138 well. However, if the link deteriorates, minstrel should immediately sample at 139 the lower rates. 140 141 Some time later, we realised that the only way to code this reliably was to 142 use the retry chain as the method of determining if the slower rates are 143 sampled. The retry chain was modified as: 140 144 141 145 Try | Lookaround rate | Normal rate … … 150 154 current best throughput, the randomly selected rate is placed second in the 151 155 chain. 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 54 mbs,153 the only time slower rates are sampled is when a packet fails in156 randomly selected rate. Thus, if the best throughput rate is currently 54 157 Mbits, the only time slower rates are sampled is when a packet fails in 154 158 transmission. Consequently, if the link is ideal, all packets will be sent at 155 the full rate of 54 mbs. Which is good.159 the full rate of 54 Mbits. Which is good. 156 160 157 161 EWMA 158 ================================================================== 162 ============================================================================== 159 163 160 164 The 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 Giventhis 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 100 ms165 rate. This calculation has a smoothing effect, so that new results have a 166 reasonable (but not large) influence on the selected rate. However, with time, 167 a series of new results in some particular direction will predominate. Given 168 this smoothing, we can use words like inertia to describe the EWMA. 169 170 By "new results", we mean the results collected in the just completed 100 ms 167 171 interval. Old results are the EWMA scaling values from before the just 168 completed 100 ms interval.172 completed 100 ms interval. 169 173 170 174 EWMA 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 175 75%. A value of 0% means use only the new results, ignore the old results. A 176 value of 99% means use the old results, with a tiny influence from the new 177 results. 176 178 177 179 The calculation (performed for each rate, at each timer interrupt) of the 178 probability of success is:180 probability of success is: 179 181 180 182 Psucces_this_time_interval * (100 - ath_ewma_level) + (Pold * ath_ewma_level) … … 193 195 inserted), then Pnew is calculated from above with Pold set to 0. 194 196 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. 197 The appropriate update interval was selected on the basis of choosing a 198 compromise 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 204 The first two points are self explanatory. When there is a sudden change in 205 the radio environment, an update interval of 100 ms will mean that the rates 206 marked as optimal are very quickly marked as poor. Consequently, the sudden 207 change in radio environment will mean that minstrel will very quickly switch 208 to a better rate. 204 209 205 210 A sudden change in the transmission probabilities will happen when the … … 210 215 layers. 211 216 212 213 214 217 Module Parameters 215 ==================================================== 218 ============================================================================== 216 219 The module has three parameters: 217 220 … … 226 229 227 230 Test Network 228 ==================================================== 229 We used three computers in our test network. The first two, equipped with 231 ============================================================================== 232 233 We used three computers in our test network. The first two, equipped with 230 234 atheros cards running in adhoc mode. We used a program that sends a fixed 231 235 number of TCP packets between computers, and reports on the data rate. The … … 239 243 240 244 It 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. 245 get 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 247 increased simply because the retry chain was finished in under 26 ms. 248 249 Our view was that throughput between the two computers should be as close as 250 possible (or better than) what can be achieved by setting both ends to fixed 251 rates. Thus, if setting the both ends to fixed rates significantly increases 252 the throughput, a reasonable conclusion is that a fault exists in the adaptive 253 rate rate. 251 254 252 255 We recorded throughputs (with minstrel) that are within 10% of what is 253 achieved with the experimentally determined optimum fixed rate. 256 achieved with the experimentally determined optimum fixed rate. 254 257 255 258 256 259 Notes on Timing 257 ==================================================== 258 259 As noted above, Minstrel calculates the throughput for each rate. This260 calculation (using a packet of size 1200 bytes) determines the 261 t ransmission time on the radio medium. In these calculations, we assume a262 contention windowmin and max value of 4 and 10 microseconds respectively.260 ============================================================================== 261 262 As noted above, minstrel calculates the throughput for each rate. This 263 calculation (using a packet of size 1200 bytes) determines the transmission 264 time on the radio medium. In these calculations, we assume a contention window 265 min and max value of 4 and 10 microseconds respectively. 263 266 264 267 Further, 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 istransmitted in each segment of the retry chain.268 guarantee a packet is transmitted (or dropped) in a minimum time period. The 269 transmission time is used in determining how many times a packet is 270 transmitted in each segment of the retry chain. 268 271 269 272 Indeed, the card will supply the cwmin/cwmax values directly 270 273 iwpriv if_name get_cwmin <0|1|2|3> <0|1> 271 274 272 We have not made direct calls to determine cwmin/cwmax - this is an area 273 f or future work. Indeed, the cwmin/cwmax determination code could check to274 see ifthe user has altered these values with the appropriate iwpriv.275 276 The contention window size does vary with traffic class. For example, 277 videoand voice have a contention window min of 3 and 2 microseconds275 We have not made direct calls to determine cwmin/cwmax - this is an area for 276 future work. Indeed, the cwmin/cwmax determination code could check to see if 277 the user has altered these values with the appropriate iwpriv. 278 279 The contention window size does vary with traffic class. For example, video 280 and voice have a contention window min of 3 and 2 microseconds 278 281 respectively. Currently, minstrel does not check traffic class. 279 282 280 Calculating the throughputs based on traffic class and bit rate and 281 variable packet size will significantly complicate the code and require282 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.283 Calculating the throughputs based on traffic class and bit rate and variable 284 packet size will significantly complicate the code and require many more 285 sample packets. More sample packets will lower the throughput achieved. Thus, 286 our view is that for this release, we should take a simple (but reasonable) 287 approach that works stably and gives good throughputs. 285 288 286 289 … … 292 295 293 296 Internal variable reporting 294 ==================================================== 297 ============================================================================== 298 295 299 The minstrel algorithm reports to the proc file system its internal 296 300 statistics, which can be viewed as text. A sample output is below: … … 326 330 T, t, and P respectively. 327 331 328 The statistics gathered in the last 100 ms time period are displayed in the332 The statistics gathered in the last 100 ms time period are displayed in the 329 333 "this prob" and "this succ/attempt" columns. 330 334 … … 335 339 analysing reports from the hal. The word "attempt" or "attempts" means the 336 340 count 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 341 will always be lower than the number in the attempts column. 342 343 When the two nodes are brought closer together, the statistics starts 344 changing, and you see more successful attempts at the higher rates. The ewma 345 prob at the higher rates increases and then most packets are conveyed at the 346 higher rates. 347 348 When the rate is not on auto, but fixed, this table is still available, and 349 will report the throughput etc for the current bit rate. Changing the rate 350 from auto to fixed to auto will completely reset this table, and the operation 351 of the minstrel module.
