【Atheros】無線網卡驅動性能測試工具pktgen的使用


前言:從12年開始做無線驅動相關的工作,到13年大概做了一年半,現在歇了快一年了,以免白學那么久,最近重新整理了一下當時的資料,寫一點文章,這方面的帖子比較少,當時碰到過很多問題難以解決,我是用的linux2.6的內核,將來用其他版本的朋友也可能會碰到類似的問題,可以把我的解決方案做一個參考~主要內容是pktgen、iperf使用的注意事項、驅動禁用CSMA、BACKOFF、ACK的方法、速率調整算法源碼解讀等。后面的幾篇文章一一介紹,文章列表

測試無線性能的pktgen有專用的版本,編譯atheros固件的時候會自帶一個無線版本的pktgen,我一開始用pktgen官網提供的pktgen發送腳本,怎么發都是一運行內核就panic,或者開發板變得非常卡,有時候沒有崩潰的情況下,dmsg查看輸出,可以看到源碼里這一句打印了堆棧信息:

WARN_ON(tid->ac->txq != txq);

代碼位置不重要,反正可以看到是txq,也就是發送隊列有問題。正巧呢經過仔細觀察pktgen的統計信息:

發現里面有queue_map_min和queue_map_max這樣兩個參數,pktgen官方的腳本里沒有設置,我從pktgen官網上下載的源碼里面也沒有提這兩個參數,這倆就是關鍵,現在的2是我后來自己設置的,默認好像是0。這個發送隊列在代碼里對應的是這樣的取值:

/**
 * 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,
};

這是數據包對應於不同接入類別的幾個發送隊列,正常數據包都是使用盡力而為這種級別,只要把queue_map_min和queue_map_max都設置為2,pktgen的數據包都用這個AC來發就沒問題了。

==================================分割線=========================================

關於這個發送隊列,實際在使用pktgen的過程中還有一個后續問題,在這里分享一下:

雖然設置了queue_map,但是不知道為什么,生成的前兩個數據包仍然是隊列0和1的,后面才是我指定的2的,雖然影響不大,但是有兩個弊端:一是pktgen的clone_skb域只能設置為0或其它較小的數,如果設置為10000,那么最前面的將近20000個包的發送隊列都是不對的。而clone_skb的值越大,pktgen發送包的效率越高,當然,clone_skb為0時的效率已經夠我們用的了,所以這一點關系不大。在這里解釋一下clone_skb這個屬性,pktgen調用驅動的某個函數(假設函數是tx())來進行發包,並把封裝數據的sk_buff對象(skb)作為參數傳進去,那么如果一共發三個包,大概就是這樣的流程(下面的都是偽代碼):

struct sk_buff *skb = get_new_skb();//生成一個新的skb並填充數據
tx(skb);
struct sk_buff *skb = get_new_skb();
tx(skb);
struct sk_buff *skb = get_new_skb();
tx(skb);

這是clone_skb=0或1的情況,也就是說,發送的這三個數據包是相互獨立的,沒有重復使用,如果clone_skb=2就指定兩個包共用一個skb,就變成了下面這樣:

struct sk_buff *skb = get_new_skb();
tx(skb);
tx(skb);
struct sk_buff *skb = get_new_skb();
tx(skb);

因為沒有重復生成skb,也就提高了效率。這是第一個問題,第二個是在驅動里有一開始提到的WARN_ON的那一步判斷,如果發送隊列不是預期的值,會打印堆棧信息,這個打印操作是很耗時,在內核中,過於頻繁的printk都可以導致系統崩潰,如果太頻繁的打印堆棧信息,也是會導致崩潰的(這也是不設置pktgen的發送隊列時板子可能會崩潰的原因),現在clone_skb的值是0,用腳本自動切換MCS時,每次使用新的MCS之后前兩個包都會打印出堆棧信息,而堆棧信息又很長,這樣很影響我們觀察在驅動其它地方使用printk打印的輸出。

解決方法是不管queue_map_min和queue_map_max怎么設置了,統一在數據包剛進入鏈路層代碼的地方強制把這個字段置成2,當然如果是以真實使用為目的還要改回去,現在用pktgen做實驗用,就沒關系了,pktgen發包是通過調用atheros驅動的

ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)

這個函數,該函數在/net/mac80211/tx.c中,就在這個函數開始的位置判斷當前數據包是不是pktgen的數據包(通過pktgen頭部的magic number來進行判斷),如果是,就調用前面提到的skb_set_queue_mapping函數把它放到2號隊列里去。代碼片段如下:

if (skb->len > 58){
    __le32 *magic = &skb->data[42];
    if(*magic == 0xbe9be955)                /* magic number of pktgen */
        skb_set_queue_mapping(skb, 2);        /* BE */
}

pktgen的最小包長是14(MAC頭)+20(IP頭)+8(UDP頭)+16(Pktgen頭),大於該值才進行判斷,pktgen頭部是從第42字節開始,按小端序取出來和pktgen的magic number來進行比較,如果匹配,則設置發送隊列。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM