我做网卡驱动,最主要的内容就是设计和改进速率调整算法,随着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来做速率的调整。

下面就依次介绍这两种算法:MinstrelAth9k

【Atheros】网卡驱动速率调整算法概述的更多相关文章

  1. 【Atheros】Ath9k速率调整算法源码走读

    上一篇文章介绍了驱动中minstrel_ht速率调整算法,atheros中提供了可选的的两种速率调整算法,分别是ath9k和minstrel,这两个算法分别位于: drivers\net\wirele ...

  2. 【Atheros】minstrel速率调整算法源码走读

    先说几个辅助的宏,因为内核不支持浮点运算,当然还有实现需要,minstrel对很多浮点值做了缩放: /* scaled fraction values */ #define MINSTREL_SCAL ...

  3. k-近邻算法概述

    2.1 k-近邻算法概述 k-近邻算法采用测量不同特征值之间的距离方法进行分类. 优点:精度高.对异常值不敏感.无数据输入假定. 确定:计算复杂度高.空间复杂度高. 适用数据范围:数值型和标称型. 工 ...

  4. 目标反射回波检测算法及其FPGA实现 之一:算法概述

    目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇 ...

  5. JS数据结构与算法-概述

    JS数据结构与算法概述 数据结构: 计算机存储, 组织数据的方式, 就像锅碗瓢盆 算法: 一系列解决问题的清晰指令, 就像食谱 两者关系: 程序 = 数据结构 + 算法 邂逅数据结构与算法 什么是数据 ...

  6. TF-IDF算法(1)—算法概述

    假设现在有一篇很长的文章,要从中提取出它的关键字,完全不人工干预,那么怎么做到呢?又有如如何判断两篇文章的相似性的这类问题,这是在数据挖掘,信息检索中经常遇到的问题,然而TF-IDF算法就可以解决.这 ...

  7. PS 图像调整算法——黑白

    这个算法是参考自 阿发伯 的博客: http://blog.csdn.net/maozefa 黑白调整 Photoshop CS的图像黑白调整功能,是通过对红.黄.绿.青.蓝和洋红等6种颜色的比例调节 ...

  8. PS 图像调整算法——饱和度调整

    算法参考自 阿发伯 的博客. http://blog.csdn.net/maozefa 饱和度调整 图像的饱和度调整有很多方法,最简单的就是判断每个象素的R.G.B值是否大于或小于128,大于加上调整 ...

  9. PS 图像调整算法——亮度调整

    这个算法是参考自 阿发伯 的博客,在此对 阿发伯 表示感谢, http://blog.csdn.net/maozefa 亮度调整 非线性亮度调整: 对于R,G,B三个通道,每个通道增加相同的增量. 线 ...

随机推荐

  1. 设计模式之单例模式(php实现)

    github地址:https://github.com/ZQCard/design_pattern 单例模式:顾名思义就就是创建单个实例的模式. 优点:保证一个类仅有一个实例,并提供一个访问它的全局访 ...

  2. oracle 被另一个用户锁定

    于是我就直接在上面改字段,在点打钩(记入改变)的时候提示,记录被另一个用户锁住,一开始还以为整个表被锁住了,后来发现,仅仅是这个字段不能改变,其他的字段可以. 网上找了资料,发现是:当多个用户并发地存 ...

  3. ios开发 Socket通信

    Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...

  4. python+ubuntu+selenium安装chrome和chromedriver

    请确保selenium已经安装成功,没安装的可以pip install selenium 安装chrome 在终端输入 下载安装包 wget https://dl.google.com/linux/d ...

  5. ISP模块之彩色图像增强--ACE算法 .

    ACE(Automatic Color Enhancement),自动色彩增强算法,是一种对于彩色图像增强十分行之有效的方法.它的改进算法以及快速实现在文章Automatic Color Enhanc ...

  6. 【Hadoop】Hadoop DataNode节点超时时间设置

    hadoop datanode节点超时时间设置 datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间 ...

  7. ImageSwitcher (图像切换器,显示图片)

    ImageSwitcher继承了ViewSwitcher,主要在切换图片时加入动画效果 使用方法: 1.为ImageSwitcher提供一个ViewFactory,该ViewFactory生成的Vie ...

  8. iOS开发:Framework的创建

    转载自:http://jonzzs.cn/2017/06/01/iOS%20开发笔记/[iOS%20开发]将自己的框架打包成%20Framework%20的方法/ 环境:Xcode 8 创建 Fram ...

  9. Oracle11g登陆sqlplus时一直提示密码错误

    我安装oracle的时候有自己设置帐号和密码,我也在服务里的oracleserver中查看了正在运行的用户名,是我注册时填的那个并已开启.但是为什么登陆Sqlplus老是说密码错误呢?我敢肯定密码没有 ...

  10. c语言用rand() 函数,实现random(int m)

    函数rand()是真正的随机数生成器.而srand()会设置供rand()使用的随机数种子. 假设你在第一次调用rand()之前没有调用srand(),那么系统会为你自己主动调用srand(). 注意 ...