【Atheros】如何禁用載波偵聽CSMA和BACKOFF


無線網絡上發包之前都要進行載波偵聽,如果未收到ACK,就指數級退避之后重傳。

有時候我們為了觀察網卡在全力發送數據包時的性能,要禁用CSMA和ACK,這一篇文章先來討論怎么禁用CSMA,這里提供兩種思路,一是通過設置幾個寄存器來完成禁CSMA和退避,,在drivers/net/wireless/ath/ath9k/hw.c的ath9k_hw_reset函數最后設置幾個寄存器:

REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_IGNORE_VIRT_CS);
REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);

我以前搜到過一個說法,設置AR_DIAG_SW寄存器的AR_DIAG_IGNORE_VIRT_CS來禁用虛擬載波偵聽,設置AR_DIAG_SW寄存器的AR_DIAG_FORCE_RX_CLEAR來禁止物理載波偵聽,,不過我設置FORCE_RX_CLEAR這個的時候有一定幾率崩潰,所以最終沒有采用。關於虛擬和物理載波偵聽,參考《下一代無線局域網-802.11n的吞吐率、強健性和可靠性》一書的解釋是:

CSMA/CA的基礎在於載波偵聽。DCF同時通過物理和虛擬的載波偵聽功能來判斷媒體狀態。物理載波偵聽功能位於PHY中,其通過能量檢測與帶幀長后延的前導碼檢測來判斷媒體是否繁忙。虛擬載波偵聽功能位於MAC中,其使用在MAC頭的“時長”字段中所承載的預訂信息,該信息聲明了對媒體的獨占接入。虛擬載波偵聽功能被稱為網絡分配向量(NAV)。只有在物理和虛擬載波偵聽機制都給出同樣結果的情況下,媒體才被判斷為空閑。

這個VIRT_CS位應該就是虛擬載波偵聽,而物理載波偵聽應該怎么來禁止,對於網上說的AR_DIAG_FORCE_RX_CLEAR這個標志,不了解具體作用。AR_DIAG_FORCE_CH_IDLE_HIGH而這個位則表明信道空閑,我覺得應該是和這個物理載波偵聽相對應的。

 

但是,本文下面分割線以后,提出了一個問題,那就是只用上面的前兩行來禁CSMA沒有問題,但是用第三行禁退避,就會出問題,用下文的設置skb->priority的方法能夠保證可以正常發送,系統不再panic,但是速率會很低,所以我用另外的方法來禁用退避,驅動有很多的發送隊列,針對每一個發送隊列,要設置自己的最大退避窗口,最小退避窗口,把這兩個值都設置成0就是禁用退避了,而且針對每個隊列,也有單獨禁用退避(backoff)的方式,在drivers/net/wireless/ath/ath9k/mac.c的ath9k_hw_resettxqueue函數里,隨便找個快結束的地方,加上:

REG_WRITE(ah, AR_DLCL_IFS(q),
        SM(0, AR_D_LCL_IFS_CWMIN) |
        SM(0, AR_D_LCL_IFS_CWMAX) |
        SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);

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

如果采用最前面的設置三個寄存器的方法來禁用CSMA,使用pktgen的時候還是會panic的。

決解思路:skb中有這么一個域,叫做nfctinfo,源代碼里對它的解釋是“Relationship of this skb to the connection”,在源代碼里它的類型是__u8,但是我在網上查找的資料,都是說這是一個枚舉型變量ip_conntrack_info的值。

nfctinfo是一個NetFilter相關的概念,我在驅動的庫里面找到了ip_conntrack_info枚舉類型的定義,如下:

/* Connection state tracking for netfilter.  This is separated from,
    but required by, the NAT layer; it can also be used by an iptables
    extension. */
enum ip_conntrack_info
{
    IP_CT_ESTABLISHED,    /*作為已建立的連接的一部分*/
    IP_CT_RELATED,        /*正在建立或已建立的連接,或ICMP錯誤*/
    IP_CT_NEW,            /*新連接或重傳*/
    IP_CT_IS_REPLY,        /*大於等着這個數的都是應答*/
    IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1    /*不同的IP_CT 類型*/
};

pktgen沒有對這個值做修改,是0,但是使用iperf進行發包時,經過一層層協議棧,這個值已經被賦為2,也就是新建連接來發送。

當禁用掉CSMA之后,更確切地說是忽略退避(設置標志位AR_D_GBL_IFS_MISC_IGNORE_BACKOFF)之后,如果這個nfctinfo的取值是IP_CT_ESTABLISHED則發不出包去。設置為2(IP_CT_NEW)之后就可以了。但是這兩者之間的具體關系不了解。在前一篇文章的最后,我講了在驅動里面為pktgen數據包強制設置發送隊列的方法,只需要在那里面再加一行(並且設置隊列也不是寫死一個2了,而是用驅動自己去選擇隊列):

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

但是這么做了之后pktgen的速率還是提不上去,最好還是用本文正文的方法去禁用BACKOFF。


免責聲明!

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



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