• 【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。

  • 相关阅读:
    ADLINK 8158控制程序-连续运动(VB.NET)
    .NET通信中的同步和异步处理
    Java 数据类型转换(转换成字节型)
    matlab中的三维坐标系与旋转
    maya和Unity中的坐标系旋转
    Android Volley完全解析(一),初识Volley的基本用法
    基于VLC的视频播放器(转载)
    android超快模拟器Ggenymotion的安装和配置
    真机在wifi下调试android程序
    Android图片异步加载框架Android-Universal-Image-Loader
  • 原文地址:https://www.cnblogs.com/smarterplanet/p/4082582.html
Copyright © 2020-2023  润新知