mac80211的模块初始化的时候,也初始化了minstrel,minstrel是调用速率控制函数模快,通过tx.c中的ieee80211_tx_h_rate_ctrl
句柄填充结构体ieee80211_tx_info
的速率变量ieee80211_tx_rate
。
模块初始化后调用了ieee80211_rate_control_register
进行速率控制注册,注册了定义好的速率控制操作结构体mac80211_minstrel_ht
,内容如下:
static const struct rate_control_ops mac80211_minstrel_ht = {
.name = "minstrel_ht",
.tx_status = minstrel_ht_tx_status,
.get_rate = minstrel_ht_get_rate,
.rate_init = minstrel_ht_rate_init,
.rate_update = minstrel_ht_rate_update,
.alloc_sta = minstrel_ht_alloc_sta,
.free_sta = minstrel_ht_free_sta,
.alloc = minstrel_ht_alloc,
.free = minstrel_ht_free,
#ifdef CPTCFG_MAC80211_DEBUGFS
.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
.remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
#endif
.get_expected_throughput = minstrel_ht_get_expected_throughput,
};
其中minstrel_ht_get_rate
函数,这个函数在高速率控制函数rc80211_minstrel_ht.c
文件中,内容如下:
static void
minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate_control *txrc)
{
const struct mcs_group *sample_group;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
struct ieee80211_tx_rate *rate = &info->status.rates[0];
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = &msp->ht;
struct minstrel_priv *mp = priv;
int sample_idx;
if (rate_control_send_low(sta, priv_sta, txrc))
return;
if (!msp->is_ht)
return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc);
info->flags |= mi->tx_flags;
minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
#ifdef CPTCFG_MAC80211_DEBUGFS
if (mp->fixed_rate_idx != -1)
return;
#endif
/* Don't use EAPOL frames for sampling on non-mrr hw */
if (mp->hw->max_rates == 1 &&
(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
sample_idx = -1;
else
sample_idx = minstrel_get_sample_rate(mp, mi);
mi->total_packets++;
/* wraparound */
if (mi->total_packets == ~0) {
mi->total_packets = 0;
mi->sample_packets = 0;
}
if (sample_idx < 0)
return;
sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
rate->count = 1;
if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
rate->idx = mp->cck_rates[idx];
rate->flags = 0;
return;
}
rate->idx = sample_idx % MCS_GROUP_RATES +
(sample_group->streams - 1) * 8;
rate->f