【Atheros】网卡驱动速率调整算法概述
我做网卡驱动,最主要的内容就是设计和改进速率调整算法,随着802.11协议簇的新标准越来越多,速率越来越高,调制编码方式也越来越多,一般来说,速率越高越可能丢包,速率越低越稳定,这是整体状况,但不是必然的规律,所以,只用固定的速率来发送显然是不合适的,这就需要速率调整算法来自己调节,信号比较好的时候,就用高速率来发送,信道状况不好了,就换用低速率来发,atheros驱动中提供了两种可选的速率调整算法,ath9k和minstrel,其中minstrel要好一些,后面我会分别根据源码解读minstrel和ath9k这两种算法,这一篇文章,只介绍一个重要的结构体,从而引出速率调整算法的任务。
接触过网络编程的朋友都不会对socket感到陌生,在数据链路层,有一个与之对应的结构体,叫做sk_buff,一般记作skb,skb中有一个域叫做control_buffer,也就是skb->cb,是一个48字节长度的内存区域,这个区域的设计,是为了协议栈中各个层存储一些私有的数据,数据包在不同层之间传递时,比如从网络层传输到链路层之后,这个域的数据就没有用了,可以放心地被链路层写入新的数据,链路层在把这个数据包交给物理层去发送的时候,需要指定一些参数,比如这个数据包要用20MHz还是40MHz去发送,用哪个速率去发送,如果发送失败了需要重传的话,最多重传多少次等等的信息,这些信息就存储在skb->cb中,存储的格式,是按照下面这个结构体来存的:
struct ieee80211_tx_info {
/* common information */
u32 flags;
u8 band;
u8 antenna_sel_tx;
u16 ack_frame_id;
union {
struct {
union {
/* rate control */
struct {
struct ieee80211_tx_rate rates[
IEEE80211_TX_MAX_RATES];
s8 rts_cts_rate_idx;
};
/* only needed before rate control */
unsigned long jiffies;
};
/* NB: vif can be NULL for injected frames */
struct ieee80211_vif *vif;
struct ieee80211_key_conf *hw_key;
struct ieee80211_sta *sta;
} control;
struct {
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
u8 ampdu_ack_len;
int ack_signal;
u8 ampdu_len;
/* 15 bytes free */
} status;
struct {
struct ieee80211_tx_rate driver_rates[
IEEE80211_TX_MAX_RATES];
void *rate_driver_data[
IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
};
void *driver_data[
IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)];
};
};
其中,很多字段的意义不需要操心,只需要关注其中union的一部分(标红的union),这段内存区域可以通过control和status等方式访问,这个control和status就是我们关注的重点!
他们的核心又是同样的一个字段:我标红的ieee80211_tx_rate:
struct ieee80211_tx_rate {
s8 idx;
u8 count;
u8 flags;
} __packed;
这个结构体代表一个速率,看字段名就很明显了:速率号、发送次数和一个标志位(标识带宽、SGI/LGI等),网卡可能会支持多速率重传,就是先用某个速率发送,如果几次都失败了就换第二个速率发,因此,底层在发包过程中,需要一个ieee80211_tx_rate的数组,速率调整算法的任务,就是把前面结构体中的这个字段填充好交给底层:
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
回到前面那个结构体tx_info,它拥有一个union,主要包括control和status两个部分,control部分是在发送过程中被使用的,速率调整算法会:
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rates = tx_info->control.rates; rates[].idx=0; rates[].count=2; rates[].flags=zzz0;
rates[].idx=1; rates[].count=4; rates[].flags=zzz1;
rates[].idx=2; rates[].count=8; rates[].flags=zzz2;
这样,我就指定了,发送时数据包依次使用0、1、2这三个速率最多发送2、4、8次,直到发送成功为止。那么发送完成之后,我们需要知道发送到底成功了没有,最后是哪个速率发送成功的等信息。所以这个结构体又会被底层返回给我们,此时,我们可以通过status访问之前设置的这些数据,只是每一项的count域被底层重写了,之前是表示每个速率的最大发送次数是多少,现在变成了每个速率的实际发送次数是多少。
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rates = tx_info->status.rates; // rates[0].count == 4
// rates[1].count == 1
// rates[2].count == 0
这就代表速率0发了4次,最终都失败了,速率1发了1次就成功了,当然速率2没有用到,发了0次。
所以速率调整算法的任务就是在发送过程中把tx_info->control.rates填充好,等发送结束后根据tx_info->status.rates来做速率的调整。
【Atheros】网卡驱动速率调整算法概述的更多相关文章
- 【Atheros】Ath9k速率调整算法源码走读
上一篇文章介绍了驱动中minstrel_ht速率调整算法,atheros中提供了可选的的两种速率调整算法,分别是ath9k和minstrel,这两个算法分别位于: drivers\net\wirele ...
- 【Atheros】minstrel速率调整算法源码走读
先说几个辅助的宏,因为内核不支持浮点运算,当然还有实现需要,minstrel对很多浮点值做了缩放: /* scaled fraction values */ #define MINSTREL_SCAL ...
- k-近邻算法概述
2.1 k-近邻算法概述 k-近邻算法采用测量不同特征值之间的距离方法进行分类. 优点:精度高.对异常值不敏感.无数据输入假定. 确定:计算复杂度高.空间复杂度高. 适用数据范围:数值型和标称型. 工 ...
- 目标反射回波检测算法及其FPGA实现 之一:算法概述
目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇 ...
- JS数据结构与算法-概述
JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...
- TF-IDF算法(1)—算法概述
假设现在有一篇很长的文章,要从中提取出它的关键字,完全不人工干预,那么怎么做到呢?又有如如何判断两篇文章的相似性的这类问题,这是在数据挖掘,信息检索中经常遇到的问题,然而TF-IDF算法就可以解决.这 ...
- PS 图像调整算法——黑白
这个算法是参考自 阿发伯 的博客: http://blog.csdn.net/maozefa 黑白调整 Photoshop CS的图像黑白调整功能,是通过对红.黄.绿.青.蓝和洋红等6种颜色的比例调节 ...
- PS 图像调整算法——饱和度调整
算法参考自 阿发伯 的博客. http://blog.csdn.net/maozefa 饱和度调整 图像的饱和度调整有很多方法,最简单的就是判断每个象素的R.G.B值是否大于或小于128,大于加上调整 ...
- PS 图像调整算法——亮度调整
这个算法是参考自 阿发伯 的博客,在此对 阿发伯 表示感谢, http://blog.csdn.net/maozefa 亮度调整 非线性亮度调整: 对于R,G,B三个通道,每个通道增加相同的增量. 线 ...
随机推荐
- 设计模式之单例模式(php实现)
github地址:https://github.com/ZQCard/design_pattern 单例模式:顾名思义就就是创建单个实例的模式. 优点:保证一个类仅有一个实例,并提供一个访问它的全局访 ...
- oracle 被另一个用户锁定
于是我就直接在上面改字段,在点打钩(记入改变)的时候提示,记录被另一个用户锁住,一开始还以为整个表被锁住了,后来发现,仅仅是这个字段不能改变,其他的字段可以. 网上找了资料,发现是:当多个用户并发地存 ...
- ios开发 Socket通信
Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...
- python+ubuntu+selenium安装chrome和chromedriver
请确保selenium已经安装成功,没安装的可以pip install selenium 安装chrome 在终端输入 下载安装包 wget https://dl.google.com/linux/d ...
- ISP模块之彩色图像增强--ACE算法 .
ACE(Automatic Color Enhancement),自动色彩增强算法,是一种对于彩色图像增强十分行之有效的方法.它的改进算法以及快速实现在文章Automatic Color Enhanc ...
- 【Hadoop】Hadoop DataNode节点超时时间设置
hadoop datanode节点超时时间设置 datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间 ...
- ImageSwitcher (图像切换器,显示图片)
ImageSwitcher继承了ViewSwitcher,主要在切换图片时加入动画效果 使用方法: 1.为ImageSwitcher提供一个ViewFactory,该ViewFactory生成的Vie ...
- iOS开发:Framework的创建
转载自:http://jonzzs.cn/2017/06/01/iOS%20开发笔记/[iOS%20开发]将自己的框架打包成%20Framework%20的方法/ 环境:Xcode 8 创建 Fram ...
- Oracle11g登陆sqlplus时一直提示密码错误
我安装oracle的时候有自己设置帐号和密码,我也在服务里的oracleserver中查看了正在运行的用户名,是我注册时填的那个并已开启.但是为什么登陆Sqlplus老是说密码错误呢?我敢肯定密码没有 ...
- c语言用rand() 函数,实现random(int m)
函数rand()是真正的随机数生成器.而srand()会设置供rand()使用的随机数种子. 假设你在第一次调用rand()之前没有调用srand(),那么系统会为你自己主动调用srand(). 注意 ...