【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[0].idx=0; rates[0].count=2; rates[0].flags=zzz0;
rates[1].idx=1; rates[1].count=4; rates[1].flags=zzz1;
rates[2].idx=2; rates[2].count=8; rates[2].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

时间: 2024-10-06 23:37:51

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

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

先说几个辅助的宏,因为内核不支持浮点运算,当然还有实现需要,minstrel对很多浮点值做了缩放: /* scaled fraction values */ #define MINSTREL_SCALE 16 #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) MINSTREL_SCALE是一个放

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

上一篇文章介绍了驱动中minstrel_ht速率调整算法,atheros中提供了可选的的两种速率调整算法,分别是ath9k和minstrel,这两个算法分别位于: drivers\net\wireless\ath\ath9k\rc.c···················Ath9k net\mac80211\minstrel_ht.c···························Minstrel 无论从理论分析还是实验结果上看,minstrel都要胜ath9k一筹,为了一个完整性,这里也

泛型算法概述

顺序容器只定义了很少的操作:在多数情况下,我们可以添加和删除元素.访问首尾元素.确定容器是否为空以及获得指向首元素或尾元素之后位置的迭代器. 如果我们想要做:查找特定元素.替换或删除一个特定值.重排元素顺序等.标准库并未给每个容器都定义成员函数来实现这些操作,而是定义了一组泛型算法:称它们为“算法”,是因为它们实现了一些经典算法的公共接口,如排序和搜索:称它们是“泛型的”,是因为它们可用于不同类型的元素和多种容器类型(不仅包括标准库类型,如vector或list,还包括内置的数组类型). 概述

[笔记] Node-Link可视化图中移动Node后自动布局调整算法

Node-Link可视化图中移动Node后自动布局调整算法 如果按工程来说,HyperGraph的可视化,用Node-Link可以说已经比成熟了,不论是D3.js还是各种其他JavaScript库诸如sigma.js等.不过大部分的库还是SVG的,可能一方面是SVG比较方便绑定事件,另一方面SVG也便于定义CSS去扩展样式.基于Canvas的实现也不少,感觉目前比较好看点的是GoJS,虽然free但是不是那么开源的至少js文件uglify过,开源的很好的是VIS.js.不过最喜欢的还是Tenso

查找算法概述

本文关于排序算法概述引自<新编数据结构习题与解析>(李春葆等著)第10章. 被查找的对象是由一组记录组成的表或文件,每个记录由若干个数据项组成,并假设每个记录都有一个能唯一标识该记录的关键字. 查找的定义是:给定一个值k,在含有n个记录的表中找出关键字等于k的记录.若找到,则查找成功,返回该记录的信息或该记录在表中的位置:否则查找失败,返回相关的指示信息. 采用何种查找方法的相关因素如下: 1)使用哪种数据结构来表示“表”,即表中记录是按何种方式组织的: 2)表中关键字的次序,即对无序集合查找

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

目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇文章分享这个基于FPGA的回波识别算法的开发过程和原码,欢迎大家不吝赐教.以下原创内容欢迎网友转载,但请注明出处: https://www.cnblogs.com/helesheng.本文首先简要介绍基于FPGA的互相关反射回波检测算法的主要设计思路. 声呐测距的原理非常简单,如下图所示,抹香鲸在水

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

假设现在有一篇很长的文章,要从中提取出它的关键字,完全不人工干预,那么怎么做到呢?又有如如何判断两篇文章的相似性的这类问题,这是在数据挖掘,信息检索中经常遇到的问题,然而TF-IDF算法就可以解决.这两天因为要用到这个算法,就先学习了解一下.  TF-IDF概述    在接触一个新算法时,首先当然是先去了解这个算法的本质,在此,我们先引用百度百科上的解释:TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术.

流行的机器学习算法概述

本文我们会概述一些流行的机器学习算法. 机器学习算法很多,并且它们自身又有很多延伸.因此,如何确定解决一个问题的最好算法是很困难的. 下面我们先说基于学习方式对算法的分类和算法之间的相似性,让大家有个整体意识:接着再陈述各类算法. 一.基于学习方式对算法的分类 根据如何处理经验.环境或者任何我们称之为输入的数据,算法分为不同种类.机器学习和人工智能课本通常先考虑算法可以适应的学习方式. 这里只讨论几个主要的学习风格或学习模型,并且有几个基本的例子.这种分类或者组织的方法很好,因为它迫使你去思考输

游戏开发常用算法概述

游戏开发属于软件开发中的一种,但又是非常特殊的一种. 游戏开发几乎可以用到软件设计中的任何一种算法,任何一种设计模式,任何一种编程思想,较普通的软件开发,难度相对要大一些. 游戏几乎模拟出一个完整的世界. 下面是我收集的一些常用的算法.设计模式及变成思想,欢迎拍砖和补充. 一 算法 1 随机数 常用于抽装备,暴击,闪避等 2 最短路径 用于地图中寻找到达指定位置的最短路径,dota,LOL中,点击地图上任一可达的点,英雄单位就会找到最短的路径,到达指定点. 不知道有木有人玩起凡,起凡中的寻路算法