队列优先级问题:
MAC层定义了四种IEEE80211接入优先级
/**
*enum ieee80211_ac_numbers - AC numbers as used in mac80211
*@IEEE80211_AC_VO: voice
*@IEEE80211_AC_VI: video
*@IEEE80211_AC_BE: best effort
*@IEEE80211_AC_BK: background
*/
enum ieee80211_ac_numbers {
IEEE80211_AC_VO = 0,
IEEE80211_AC_VI = 1,
IEEE80211_AC_BE = 2,
IEEE80211_AC_BK = 3,
};
对几种数据帧的子类型进行硬件队列分配的数组
enum ath_hw_txq_subtype {
ATH_TXQ_AC_BE= 0,
ATH_TXQ_AC_BK= 1,
ATH_TXQ_AC_VI= 2,
ATH_TXQ_AC_VO= 3,
};
可以看到有下列对应关系:
IEEE80211 硬件队列
BE 0
BK 1
VI 2
VO 3
在硬件队列中NUM越大的,优先级越高,这个和IEEE80211的四种接入级别也是相对应的。
但是实际上是没有用到这个的,这个在ath9k_hw_setuptxqueue函数中才是真正定义对不同类型的数据采用不同的队列。
//noted by shenlei 2014 12 13
switch(type) {
caseATH9K_TX_QUEUE_BEACON:
q= ATH9K_NUM_TX_QUEUES - 1;
break;
caseATH9K_TX_QUEUE_CAB:
q= ATH9K_NUM_TX_QUEUES - 2;
break;
caseATH9K_TX_QUEUE_PSPOLL:
q= 1;
break;
caseATH9K_TX_QUEUE_UAPSD:
q= ATH9K_NUM_TX_QUEUES - 3;
break;
caseATH9K_TX_QUEUE_DATA:
for(q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
if(ah->txq[q].tqi_type ==
ATH9K_TX_QUEUE_INACTIVE)
break;
if(q == ATH9K_NUM_TX_QUEUES) {
ath_err(common,"No available TX queue\n");
return-1;
}
break;
default:
ath_err(common,"Invalid TX queue type: %u\n", type);
return-1;
}
总之, beacon级别最高为9,data帧一般为2,PSPOLL为1.另外,探测帧qnum=0,这个在其他的地方初始化的。
也就是说四种接入级别只是初始化了,并没有真正根据传入类型进行判断从而选择队列。
可是我又重新跟踪了下一般数据包的发送流程,发现数据发送不是通过这个函数来完成的,而是根据MAC层投放数据的软件缓冲区的NUM完成的。
1.首先是函数ieee80211_tx_pending(tx.c)中先是遍历所有的软件缓冲区,一共4个。
for (i = 0; i < local->hw.queues;i++) {
2.接着是判断该缓冲区是否有缓冲数据包
while(!skb_queue_empty(&local->pending[i]))
3.如果有数据则把数据发送到驱动层:
txok = ieee80211_tx_pending_skb(local,skb);
4.到达驱动层之后可以看到ath_tx_start(main.c)
q= skb_get_queue_mapping(skb);
这里的q就是对应的硬件缓冲区,它是返回skb结构体中的一项queue_mapping,也就是说真是的对应的硬件发送对列实际上还是上层的skb包决定的。
在实际中抓到的包都是队列2所发出来的,也就是说在MAC层以上的层都是把数据存放在MAC层软件缓冲区的2号队列。