【Atheros】如何在驱动中禁用ACK

上一篇文章讲了如何禁用载波侦听(CSMA)和退避(BACKOFF)的方法,这一篇介绍如何禁用ACK。

禁用ACK主要分为三部分:

1. 在发送端设置不等待ACK回来就继续发送;

2. 在接收端设置收到数据帧之后不返回ACK;

3. (可选)有些地方针对不等待ACK的情况会有WARN等处理措施,把它们去掉。

下面分别来看,首先在发送端设置不等待ACK就继续发送,打开net/mac80211/tx.c,在ieee80211_tx_prepare函数中有这样的判断:

if (is_multicast_ether_addr(hdr->addr1)) {
    tx->flags &= ~IEEE80211_TX_UNICAST;
    info->flags |= IEEE80211_TX_CTL_NO_ACK;
} else
    tx->flags |= IEEE80211_TX_UNICAST;

这儿是说,如果当前的目标地址是多播地址,则去掉单播的标志位,并设置不等到ACK,因为多播广播是不需要ACK的嘛,如果不是多播,则加上单播的标志位,所以要在单播的时候也不等待ACK,只需要在else里面也加上IEEE80211_TX_CTL_NO_ACK就可以了:

if (is_multicast_ether_addr(hdr->addr1)) {
    tx->flags &= ~IEEE80211_TX_UNICAST;
    info->flags |= IEEE80211_TX_CTL_NO_ACK;
} else {
    tx->flags |= IEEE80211_TX_UNICAST;
    info->flags |= IEEE80211_TX_CTL_NO_ACK;
}

还有一个地方也有类似的控制,在net/mac80211/wme.c的ieee80211_set_qos_hdr中,设置QoS头的时候有判断:

if (is_multicast_ether_addr(hdr->addr1) ||
        sdata->noack_map & BIT(tid)) {
    ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
    info->flags |= IEEE80211_TX_CTL_NO_ACK;
}

同样是多播情况下设置禁用ACK,这里把if这个条件去掉,无论是不是多播都设置这两行就可以了。

2. 第二步,在接收方设置不返回ACK帧,打开drivers/net/wireless/ath/ath9k/hw.c,在ath9k_hw_reset函数中找一个位置设置:

REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_ACK_DIS);

3. 这一步可选,有很多地方对没有ACK的情况做了特殊处理,影响有大有小,先来看一个影响比较小的,net/mac80211/tx.c的ieee80211_tx_h_rate_ctrl函数中有:

if (WARN_ON_ONCE((info->control.rates[0].count > 1) &&
         (info->flags & IEEE80211_TX_CTL_NO_ACK)))
    info->control.rates[0].count = 1;

如果禁用了ACK并且发送速率的最大尝试次数大于1,则置为1,这里比较烦人的是这个WARN_ON_ONCE,本身它只打印一次堆栈信息,对性能影响不大,但是占用dmsg的输出,而且有时候看着有警告什么的特别烦,所以还是把这里删掉,最起码把WARN_ON_ONCE去掉。

再来看一个,在速率调整算法获取发送速率的时候,也就是get_rate函数开头的位置,都会调用net/mac80211/rate.c的rc_no_data_or_no_ack_use_min函数,当然了,一旦禁用了ACK,速率调整算法就不能用了,不过有时候我们固定MCS发送的时候可能被这里困扰,因为在这个函数里:

return (info->flags & (IEEE80211_TX_CTL_NO_ACK | IEEE80211_TX_CTL_USE_MINRATE)) ||
         !ieee80211_is_data(fc);

如果禁用了ACK,就会直接用传统的低速率发送,根据当前修改驱动的目的,可能会被这个问题耽误,注意一下就行,需要的时候把标红的部分删掉。

时间: 2024-10-10 11:07:59

【Atheros】如何在驱动中禁用ACK的相关文章

linux设备驱动第五篇:驱动中的并发与竟态

综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资源(硬件资源和软件上的全局.静态变量)的访问则容易导致竞态(race conditions).可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构.SMP是一种紧耦合.共享存储的系统模型,它的特点是多个CPU使用共

Linux设备驱动中的阻塞和非阻塞I/O

[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到条件满足. 2.非阻塞 非阻塞操作是指在进行设备操作是,若操作条件不满足并不会挂起,而是直接返回或重新查询(一直占用CPU资源)直到操作条件满足为止. 当用户空间的应用程序调用read(),write()等方法时,若设备的资源不能被获取,而用户又希望以阻塞的方式来访问设备,驱动程序应当在设备驱动层的

MongoDB官方C#驱动中查询条件Query用法

http://www.cnblogs.com/viprx/archive/2012/09/06/2673693.html MongoDB条件查询的基本语法. Query.All("name", "a", "b");//通过多个元素来匹配数组  Query.And(Query.EQ("name", "a"), Query.EQ("title", "t"));//同时满足

YJX_Driver_036_在驱动中使用链表sys部分

1. 在驱动中使用链表sys部分 A.链表结构 B.链表的初始化 C.在链表中插入数据(结点) D.链表数据的删除 E.链表的遍历 2. //链表指针结构LIST_ENTRY//初始化链表InitializeListHead//判断链表是否为空IsListEmpty//在头部插入结点InsertHeadList//在尾部插入结点 InsertTailList//从链表中删除 //头部删除RemoveHeadList //尾部删除RemoveTailList

linux设备驱动中的并发控制

并发指的是多个执行单元同时.并行被执行,而并发的执行单元对共享资源的访问则很容易导致竞态 linux内核中主要竞态1.多对称处理器的多个CPU  2.单CPU内进程与抢占它的进程 3.中断(硬中断.软中断.Tasklet.下半部)与进程之间访问共享内存资源的代码区称为“临界区”,临界区需要被以某种互斥机制加以保护,中断屏蔽.原子操作.自旋锁和信号量等是linux设备驱动中可采用的互斥途径. 这几个互斥的介绍: 1.中断屏蔽,这个主要用于单CPU,中断屏蔽将使得中断和进程之间的并发不再发生.使用方

【转】[内核/驱动]驱动中获取进程全路径和注册表全路径

转载地址: http://blog.sina.com.cn/s/blog_60a1a51d0100e78g.html 2008.07.05 经过这几天的努力,注册表保护驱动已经基本稳定.很多人都在网上问如何获取访问注册表的进程全路径和被访问的注册表的全路径,下面就将部分代码贴出来. //驱动中获取被访问注册表的全路径 BOOLEAN GetRegFullPath(HANDLE KeyHandle, PUNICODE_STRING pRegFullPath) { POBJECT pKey = NU

深入浅出~Linux设备驱动中的阻塞和非阻塞I/O

今天意外收到一个消息,真是惊呆我了,博客轩给我发了信息,说是俺的博客文章有特色可以出本书,,这简直让我受宠若惊,俺只是个大三的技术宅,写的博客也是自己所学的一些见解和在网上看到我一些博文以及帖子里综合起来写的,,总之这又给了额外的动力,让自己继续前进,,希望和大家能够分享一些自己的经验,,在最需要奋斗的年级以及在技术的领域踽踽独行的过程中有共同的伙伴继续前进~ 今天写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说就是对I/O操作的两种不同的方式,驱动程序可以灵活的

Zabbix中禁用guest用户

点击"Administration"-->Users,找到下面的guest用户,点击status的"Enabled" 可以看到guest用户被禁用了 Zabbix中禁用guest用户,布布扣,bubuko.com

已经在TCP/IP中禁用IPv6,为什么邮件头中仍然显示IPv6呢?

有时会出现尽管我们在TCP/IP中禁用了IPV6,但是邮件头中仍然有IPV6地址,如何来解决呢?好的首先如果您的IPv6是在安装完Exchange后才禁止的,那么我们在TCP/IP中禁止,或许有的时候不能奏效.我建议您通过注册表来禁止IPv6,试试是否还会出现问题: a. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters b. 新建DWORD(32-bits)并以"DisabledComponents&q