mac80211 子系统 (高级)

本书这一部分包含的信息仅对 mac80211 与驱动程序的高级交互感兴趣,以利用更多的硬件功能并提高性能。

LED 支持

Mac80211 支持各种 LED 闪烁方式。在任何可能的情况下,设备 LED 都应作为 LED 类设备公开,并连接到适当的触发器,然后由 mac80211 适当触发。

吞吐量闪烁描述

定义:

struct ieee80211_tpt_blink {
    int throughput;
    int blink_time;
};

成员

吞吐量

吞吐量,单位为 Kbit/秒

闪烁时间

闪烁时间,单位为毫秒 (完整周期,即一个关闭周期 + 一个开启周期)

enum ieee80211_tpt_led_trigger_flags

吞吐量触发标志

常量

IEEE80211_TPT_LEDTRIG_FL_RADIO

启用无线电闪烁

IEEE80211_TPT_LEDTRIG_FL_WORK

启用工作时闪烁

IEEE80211_TPT_LEDTRIG_FL_CONNECTED

当至少一个接口以某种方式连接时启用闪烁,包括作为 AP

const char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)

获取 TX LED 的名称

参数

struct ieee80211_hw *hw

要获取 LED 触发器名称的硬件

描述

mac80211 为每个无线硬件创建一个传输 LED 触发器,如果您的驱动程序注册了一个 LED 设备,则可以使用该触发器来驱动 LED。此函数返回触发器的名称 (或 NULL,如果未配置 LED),以便您可以自动链接 LED 设备。

返回

LED 触发器的名称。 NULL,如果未配置 LED。

const char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)

获取 RX LED 的名称

参数

struct ieee80211_hw *hw

要获取 LED 触发器名称的硬件

描述

mac80211 为每个无线硬件创建一个接收 LED 触发器,如果您的驱动程序注册了一个 LED 设备,则可以使用该触发器来驱动 LED。此函数返回触发器的名称 (或 NULL,如果未配置 LED),以便您可以自动链接 LED 设备。

返回

LED 触发器的名称。 NULL,如果未配置 LED。

const char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)

获取关联 LED 的名称

参数

struct ieee80211_hw *hw

要获取 LED 触发器名称的硬件

描述

mac80211 为每个无线硬件创建一个关联 LED 触发器,如果您的驱动程序注册了一个 LED 设备,则可以使用该触发器来驱动 LED。此函数返回触发器的名称 (或 NULL,如果未配置 LED),以便您可以自动链接 LED 设备。

返回

LED 触发器的名称。 NULL,如果未配置 LED。

const char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)

获取无线电 LED 的名称

参数

struct ieee80211_hw *hw

要获取 LED 触发器名称的硬件

描述

mac80211 为每个无线硬件创建一个无线电更改 LED 触发器,如果您的驱动程序注册了一个 LED 设备,则可以使用该触发器来驱动 LED。此函数返回触发器的名称 (或 NULL,如果未配置 LED),以便您可以自动链接 LED 设备。

返回

LED 触发器的名称。 NULL,如果未配置 LED。

const char *ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags, const struct ieee80211_tpt_blink *blink_table, unsigned int blink_table_len)

创建吞吐量 LED 触发器

参数

struct ieee80211_hw *hw

要为其创建触发器的硬件

unsigned int flags

触发标志,请参阅 enum ieee80211_tpt_led_trigger_flags

const struct ieee80211_tpt_blink *blink_table

闪烁表 -- 需要按吞吐量排序

unsigned int blink_table_len

闪烁表的大小

返回

NULL (如果出错或未配置 LED 触发器) 或新触发器的名称。

注意

必须在 ieee80211_register_hw() 之前调用此函数。

硬件加密加速

mac80211 能够利用许多硬件加速设计来进行加密和解密操作。

为给定设备的 struct ieee80211_ops 中的 set_key() 回调用于启用加密和解密的硬件加速。回调采用一个 sta 参数,该参数对于默认密钥或仅用于传输的密钥将为 NULL,或者指向对等方的电台信息的指针,以用于单独的密钥。当为接入点配置 VLAN 时,可以使用具有相同密钥索引的多个传输密钥。

传输时,TX 控制数据将使用驱动程序通过修改由 key 参数指向的 struct ieee80211_key_conf (传递给 set_key() 函数) 选择的 hw_key_idx

如果密钥现在正在使用,则 SET_KEY 命令的 set_key() 调用应返回 0;如果无法添加密钥,则返回 -EOPNOTSUPP 或 -ENOSPC;如果返回 0,则必须将 hw_key_idx 分配给硬件密钥索引。您可以自由使用完整的 u8 范围。

请注意,如果设置了 IEEE80211_HW_SW_CRYPTO_CONTROL 标志,如果启用硬件加密失败,mac80211 将不会自动回退到软件加密。set_key() 调用也可能返回值 1,以允许在软件中完成此特定密钥/算法。

当 cmd 为 DISABLE_KEY 时,它必须成功。

请注意,即使已将密钥上传到硬件,也可以不解密帧。堆栈不会根据是否已上传密钥做出任何决定,而是根据接收标志做出决定。

key 参数指向的 struct ieee80211_key_conf 结构保证在另一次 set_key() 调用将其删除之前有效,但它只能用作区分密钥的 Cookie。

在 TKIP 中,某些硬件需要提供一个第 1 阶段密钥,用于 RX 解密加速 (即 iwlwifi)。这些驱动程序应提供 update_tkip_key 处理程序。update_tkip_key() 调用使用新的第 1 阶段密钥更新驱动程序。每当 iv16 回绕时 (每 65536 个数据包),就会发生这种情况。set_key() 调用对于每个密钥仅发生一次 (除非 AP 重新密钥);它不会包含有效的第 1 阶段密钥。有效的第 1 阶段密钥仅由 update_tkip_key 提供。触发 mac80211 调用此处理程序的原因是软件解密和 iv16 的回绕。

set_default_unicast_key() 调用更新为 WEP 加密类型配置到硬件的默认 WEP 密钥索引。这是支持数据包卸载的设备 (例如,ARP 响应) 所必需的。

当 Mac80211 驱动程序能够按照以下要求替换正在使用的 PTK 密钥时,应设置 NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 标志:1) 它们不会将使用旧密钥解密的帧传递给 mac80211

enum ieee80211_key_flags

密钥标志

常量

IEEE80211_KEY_FLAG_GENERATE_IV_MGMT

对于 CCMP/GCMP 密钥,驱动程序应设置此标志,以指示它仅需要管理帧 (MFP) 的 IV 生成。

IEEE80211_KEY_FLAG_GENERATE_IV

驱动程序应设置此标志,以指示它需要此特定密钥的 IV 生成。设置此标志并不一定意味着 SKB 将具有足够的尾部空间用于 ICV 或 MIC。

IEEE80211_KEY_FLAG_GENERATE_MMIC

如果 TKIP 密钥需要在软件中生成 Michael MIC,驱动程序应设置此标志。

IEEE80211_KEY_FLAG_PAIRWISE

由 mac80211 设置,此标志指示密钥是成对密钥而不是共享密钥。

IEEE80211_KEY_FLAG_SW_MGMT_TX

如果 CCMP/GCMP 密钥需要在软件中完成管理帧 (MFP) 的 CCMP/GCMP 加密,驱动程序应设置此标志。

IEEE80211_KEY_FLAG_PUT_IV_SPACE

如果应为 IV 准备空间,但不应生成 IV 本身,驱动程序应设置此标志。不要与同一密钥上的 IEEE80211_KEY_FLAG_GENERATE_IV 一起设置。设置此标志并不一定意味着 SKB 将具有足够的尾部空间用于 ICV 或 MIC。

IEEE80211_KEY_FLAG_RX_MGMT

此密钥将用于解密收到的管理帧。该标志可以帮助那些硬件加密实现无法正确处理管理帧的驱动程序,方法是允许它们不将密钥上传到硬件并回退到软件加密。请注意,此标志仅处理 RX,如果您的加密引擎无法处理 TX,您还可以设置 IEEE80211_KEY_FLAG_SW_MGMT_TX 标志以在 SW 中加密此类帧。

IEEE80211_KEY_FLAG_RESERVE_TAILROOM

对于密钥,驱动程序应设置此标志,以指示必须始终为 ICV 或 MIC 保留足够的尾部空间,即使启用了 HW 加密也是如此。

IEEE80211_KEY_FLAG_PUT_MIC_SPACE

如果 TKIP 密钥仅需要 MIC 空间,驱动程序应设置此标志。不要与同一密钥上的 IEEE80211_KEY_FLAG_GENERATE_MMIC 一起设置。

IEEE80211_KEY_FLAG_NO_AUTO_TX

密钥需要显式 Tx 激活。

IEEE80211_KEY_FLAG_GENERATE_MMIE

对于 AES_CMAC 或 AES_GMAC 密钥,驱动程序应设置此标志,以指示它仅需要序列号生成

IEEE80211_KEY_FLAG_SPP_AMSDU

SPP A-MSDU 可以与此密钥一起使用 (由 mac80211 从 sta->spp_amsdu 标志设置)

描述

这些标志用于驱动程序和 mac80211 之间关于密钥的通信,使用 struct ieee80211_key_confflags 参数。

struct ieee80211_key_conf

密钥信息

定义:

struct ieee80211_key_conf {
    atomic64_t tx_pn;
    u32 cipher;
    u8 icv_len;
    u8 iv_len;
    u8 hw_key_idx;
    s8 keyidx;
    u16 flags;
    s8 link_id;
    u8 keylen;
    u8 key[];
};

成员

tx_pn

用于 TX 密钥的 PN,如果驱动程序需要自行进行软件 PN 分配 (例如,由于 TSO),也可以由驱动程序使用

密码

密钥的密码套件选择器。

icv_len

此密钥类型的 ICV 长度

iv_len

此密钥类型的 IV 长度

hw_key_idx

要由驱动程序设置,这是驱动程序希望在传输帧并需要在硬件中加密时给出的密钥索引。

keyidx

密钥索引 (0-7)

标志

密钥标志,请参阅 enum ieee80211_key_flags

link_id

链路 ID,对于非 MLO 为 0,对于成对密钥为 -1

keylen

密钥材料长度

密钥

密钥材料。对于 ALG_TKIP,密钥编码为 256 位 (32 字节) 数据块:- 临时加密密钥 (128 位) - 临时身份验证器 Tx MIC 密钥 (64 位) - 临时身份验证器 Rx MIC 密钥 (64 位)

描述

此密钥信息由 mac80211 通过 struct ieee80211_ops 中的 set_key() 回调提供给驱动程序。

enum set_key_cmd

密钥命令

常量

SET_KEY

设置密钥

DISABLE_KEY

必须禁用密钥

描述

struct ieee80211_ops 中的 set_key() 回调一起使用,这指示密钥是被删除还是被添加。

void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf, u32 iv32, u16 *p1k)

获取 IV32 的 TKIP 第 1 阶段密钥

参数

struct ieee80211_key_conf *keyconf

与设置密钥一起传递的参数

u32 iv32

要为其获取 P1K 的 IV32

u16 *p1k

将向其写入密钥的缓冲区,作为 5 个 u16 值

描述

此函数返回给定 IV32 的 TKIP 第 1 阶段密钥。

void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf, struct sk_buff *skb, u16 *p1k)

获取 TKIP 第 1 阶段密钥

参数

struct ieee80211_key_conf *keyconf

与设置密钥一起传递的参数

struct sk_buff *skb

要从中获取 IV32 值的数据包,该值将使用此 P1K 加密

u16 *p1k

将向其写入密钥的缓冲区,作为 5 个 u16 值

描述

此函数返回从给定数据包中获取的 IV32 的 TKIP 第 1 阶段密钥。

void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, struct sk_buff *skb, u8 *p2k)

获取 TKIP 第 2 阶段密钥

参数

struct ieee80211_key_conf *keyconf

与设置密钥一起传递的参数

struct sk_buff *skb

要从中获取 IV32/IV16 值的数据包,该值将使用此密钥加密

u8 *p2k

将向其写入密钥的缓冲区,16 字节

描述

此函数计算数据包中 IV 值的 TKIP RC4 密钥。

省电支持

mac80211 支持各种省电实现。

首先,它可以支持自行处理所有省电的硬件;此类硬件应简单地设置 IEEE80211_HW_SUPPORTS_PS 硬件标志。在这种情况下,它将被告知所需的省电模式,其中 IEEE80211_CONF_PS 标志取决于关联状态。硬件必须在必要时发送 nullfunc 帧,即在进入和离开省电模式时。硬件需要查看信标中的 AID,并在找到定向到它的流量时向 AP 发出它已唤醒的信号。

启用的 IEEE80211_CONF_PS 标志意味着启用了 IEEE 802.11-2007 第 11.2 节中定义的省电模式。这不应与硬件唤醒和睡眠状态混淆。驱动程序负责在向硬件发出命令之前唤醒硬件,并在适当的时间将其恢复睡眠状态。

启用 PS 后,硬件需要唤醒以接收信标,并在信标后接收缓冲的多播/广播帧。此外,必须可以发送帧并接收确认帧。

其他硬件设计无法自行发送 nullfunc 帧,还需要软件支持来解析 TIM 位图。mac80211 通过组合 IEEE80211_HW_SUPPORTS_PSIEEE80211_HW_PS_NULLFUNC_STACK 标志来支持这一点。当然,仍然需要硬件来传递信标。硬件仍然需要处理为多播流量唤醒;如果它不能,驱动程序必须尽可能地处理它;mac80211 太慢而无法做到这一点。

动态省电是正常省电的扩展,其中硬件在发送帧后保持唤醒用户指定的时间段,以便无需缓冲回复帧,因此不会延迟到下一次唤醒。这是在存在数据流量时获得足够好的延迟,并且在空闲期间仍然显着节省电量的一种折衷方案。

动态省电只需通过 mac80211 基于流量启用和禁用 PS 来支持。驱动程序只需要设置 IEEE80211_HW_SUPPORTS_PS 标志,mac80211 将自动处理一切。此外,具有动态 PS 功能支持的硬件可以设置 IEEE80211_HW_SUPPORTS_DYNAMIC_PS 标志,以指示它可以自行支持动态 PS 模式。驱动程序需要查看 dynamic_ps_timeout 硬件配置值,并在设置 IEEE80211_CONF_PS 时使用该值。在这种情况下,mac80211 将禁用堆栈中的动态 PS 功能,并且只要用户启用了省电,就会保持 IEEE80211_CONF_PS 启用。

驱动程序通过启用 IEEE80211_VIF_SUPPORTS_UAPSD 标志来通知 U-APSD 客户端支持。该模式通过 conf_tx() 操作中的 uapsd 参数进行配置。硬件需要发送 QoS Nullfunc 帧,并保持唤醒状态直到服务期结束。要利用 U-APSD,voip AC 的动态省电将被禁用,并且来自该 AC 的所有帧都将在启用省电的情况下传输。

注意:IEEE80211_HW_PS_NULLFUNC_STACK 尚不支持 U-APSD 客户端模式。

信标过滤器支持

某些硬件具有信标过滤器支持,以减少主机 CPU 唤醒,这将降低系统功耗。它通常的工作方式是固件创建信标的校验和,但省略所有不断变化的元素 (TSF、TIM 等)。每当校验和更改时,信标都会转发到主机,否则它将被丢弃。这样,主机将仅接收其中某些相关信息 (例如 ERP 保护或 WMM 设置) 已更改的信标。

信标过滤器支持通过 IEEE80211_VIF_BEACON_FILTER 接口功能进行广播。每当启用省电时,驱动程序都需要启用信标过滤器支持,即设置 IEEE80211_CONF_PS。启用省电后,堆栈将不检查信标丢失,并且驱动程序需要通过 ieee80211_beacon_loss() 通知信标丢失。

在固件通知驱动程序信标丢失事件之前的时间 (或错过的信标数量) (这反过来会导致驱动程序调用 ieee80211_beacon_loss()) 应该是可配置的,并且将来将由 mac80211 和漫游算法控制。

由于可能存在软件堆栈中没有任何内容关心的不断变化的信息元素,因此在将来,我们将让 mac80211 告诉驱动程序哪些信息元素是有趣的,因为我们希望看到其中的更改。这将包括

  • 信息元素 ID 列表

  • 供应商信息元素的 OUI 列表

理想情况下,硬件将过滤掉任何未请求元素中发生更改的信标,但如果它无法支持这一点,则可能会以牺牲一些效率为代价,仅过滤掉一个子集。例如,如果设备不支持检查 OUI,它应该传递所有供应商信息元素中的所有更改。

请注意,为简化起见,更改还包括信息元素从信标中出现或消失。

某些硬件支持“忽略列表”来代替。只需确保忽略列表中没有任何请求的内容,并在忽略列表中包含常用更改的信息元素 ID,例如 11 (BSS 负载) 和具有未知内容的各种供应商分配的 IE (128、129、133-136、149、150、155、156、173、176、178、179、219);为了向前兼容,它还可以包括一些当前未使用的 ID。

除了这些功能之外,硬件还应该支持通知主机信标 RSSI 的更改。这与在没有流量流动时实施漫游相关 (当流量流动时,我们会看到收到的数据包的 RSSI)。这可以包括在 RSSI 显着变化或低于或高于可配置阈值时通知主机。将来,这些阈值也将由 mac80211 (从用户空间获取它们) 配置,以根据漫游算法的要求实施它们。

如果硬件无法实现这一点,驱动程序应要求它定期将信标帧传递给主机,以便软件可以进行信号强度阈值检查。

void ieee80211_beacon_loss(struct ieee80211_vif *vif)

通知硬件未接收到信标

参数

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

描述

当使用 IEEE80211_VIF_BEACON_FILTER 启用信标过滤并设置 IEEE80211_CONF_PS 时,只要硬件未使用此函数接收到信标,驱动程序就需要通知。

多个队列和 QoS 支持

待定

struct ieee80211_tx_queue_params

传输队列配置

定义:

struct ieee80211_tx_queue_params {
    u16 txop;
    u16 cw_min;
    u16 cw_max;
    u8 aifs;
    bool acm;
    bool uapsd;
    bool mu_edca;
    struct ieee80211_he_mu_edca_param_ac_rec mu_edca_param_rec;
};

成员

txop

最大突发时间,单位为 32 微秒,0 表示禁用

cw_min

最小竞争窗口 [范围 1..32767 中形式为 2^n-1 的值]

cw_max

最大竞争窗口 [如 cw_min]

aifs

仲裁帧间间距 [0..255]

acm

访问类别是否需要强制准入控制

uapsd

是否为队列启用 U-APSD 模式

mu_edca

是否配置了 MU EDCA

mu_edca_param_rec

HE 的 MU EDCA 参数记录

描述

QoS 传输队列配置需要此结构中提供的信息。Cf. IEEE 802.11 7.3.2.29。

接入点模式支持

待定

应在此处讨论 if_conf 的某些部分

在此处或在 hw 加密章节中插入有关带有 hw 加密的 VLAN 接口的说明。

对省电客户端的支持

为了实现 AP 和 P2P GO 模式,mac80211 支持客户端节能,包括“传统”PS(PS-Poll/null data)和 uAPSD。目前不支持 sAPSD。

mac80211 有一个假设,即客户端不会同时使用 PS-Poll 进行轮询和使用 uAPSD 进行触发。两者都受支持,并且可以由同一客户端使用,但不能由同一客户端同时使用。这简化了驱动程序代码。

首先要记住的是,有一个用于完整驱动程序实现的标志:IEEE80211_HW_AP_LINK_PS。如果设置了此标志,mac80211 会期望驱动程序处理大多数节能客户端的状态机,并且会忽略传入帧中的 PM 位。然后,驱动程序使用 ieee80211_sta_ps_transition() 来通知 mac80211 站点的节能转换。在此模式下,mac80211 也不处理 PS-Poll/uAPSD。

在没有 IEEE80211_HW_AP_LINK_PS 的模式下,mac80211 将检查传入帧中的 PM 位以进行客户端节能转换。当站点进入睡眠状态时,我们将停止向其传输数据。但是,存在竞争条件:在硬件队列上有数据缓冲时,站点可能会进入睡眠状态。如果设备支持此功能,它将拒绝帧,并且驱动程序应将带有 IEEE80211_TX_STAT_TX_FILTERED 标志的帧返回给 mac80211,这将导致 mac80211 在站点唤醒时重试该帧。驱动程序还会通过调用其 sta_notify 回调来收到节能转换的通知。

当站点处于睡眠状态时,它有三个选择:它可以唤醒、可以使用 PS-Poll 进行轮询,或者可以启动 uAPSD 服务周期。唤醒是通过简单地将所有缓冲的(和过滤的)帧传输到站点来实现的。这是最简单的情况。当站点发送 PS-Poll 或 uAPSD 触发帧时,mac80211 将通过 allow_buffered_frames 回调通知驱动程序;此回调是可选的。然后,mac80211 将像往常一样传输帧,并在每个帧上设置 IEEE80211_TX_CTL_NO_PS_BUFFER。服务周期中的最后一个帧(或对 PS-Poll 的唯一响应)也设置了 IEEE80211_TX_STATUS_EOSP,以指示它结束了服务周期;由于此帧必须具有 TX 状态报告,因此它还会设置 IEEE80211_TX_CTL_REQ_TX_STATUS。当报告此帧的 TX 状态时,服务周期将被标记为已结束,并且对等方可以启动新的服务周期。

此外,mac80211 还可以传输带有 IEEE80211_TX_CTL_NO_PS_BUFFER 的不可缓冲 MMPDU。

在某些设备(如 iwlwifi)上,当有帧在队列中等待站点并且站点唤醒或轮询时,可能会出现另一个竞争条件;已经排队的帧最终可能会首先被传输,从而导致 EOSP 的重新排序和/或错误处理。原因是允许将帧传输到特定站点的行为是与设备的带外通信。为了解决此问题,如果站点进入睡眠状态时有帧被缓冲,驱动程序可以调用 ieee80211_sta_block_awake()。当所有这些帧都被过滤(参见上文)时,它必须再次调用该函数以指示该站点不再被阻止。

如果驱动程序以任何方式缓冲驱动程序中的帧以进行聚合,则当收到站点进入睡眠状态的通知时,它必须使用 ieee80211_sta_set_buffered() 调用来通知 mac80211 哪些 TID 有帧缓冲。请注意,当站点唤醒时,此信息会被重置(因此需要在收到站点进入睡眠状态的通知时调用它)。然后,当任何原因启动服务周期时,将调用 release_buffered_frames,其中包含要释放的帧数以及要从中释放帧的 TID。在这种情况下,驱动程序负责在释放的帧中设置 EOSP(对于 uAPSD)和 MORE_DATA 位。为了提供帮助,more_data 参数被传递以告知驱动程序其他 TID 上是否有更多数据——从其释放帧的 TID 被忽略,因为 mac80211 不知道这些 TID 的缓冲区包含多少帧。

如果驱动程序还实现了 GO 模式,其中不存在周期可能会缩短服务周期(或中止 PS-Poll 响应),则它必须过滤这些响应帧,除非这些帧被缓冲在驱动程序中——这些帧必须保持缓冲以避免重新排序。因为在这种情况下可能没有帧被释放,所以驱动程序必须调用 ieee80211_sta_eosp() 以指示 mac80211 服务周期无论如何都已结束。

最后,如果从 mac80211 释放了来自多个 TID 的帧,但驱动程序可能会重新排序它们,则它必须清除并设置相应的标志(只有最后一个帧可能具有 IEEE80211_TX_STATUS_EOSP),并且还需要注意帧中的 EOSP 和 MORE_DATA 位。驱动程序也可以在这种情况下使用 ieee80211_sta_eosp()

请注意,如果驱动程序缓冲了除 QoS 数据帧之外的其他帧,则必须注意永远不要将非 QoS 数据帧作为服务周期中的最后一个帧发送,如果需要,在非 QoS 数据帧之后添加 QoS 空数据帧。

enum ieee80211_frame_release_type

帧释放原因

常量

IEEE80211_FRAME_RELEASE_PSPOLL

为 PS-Poll 释放的帧

IEEE80211_FRAME_RELEASE_UAPSD

由于在启用触发器的 AC 上接收到帧而释放的帧

int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)

已连接站点的 PS 转换

参数

struct ieee80211_sta *sta

当前已连接的站点

bool start

启动或停止 PS

描述

当以 AP 模式运行且设置了 IEEE80211_HW_AP_LINK_PS 标志时,请使用此函数来通知 mac80211 已连接的站点进入/离开 PS 模式。

不得在 IRQ 上下文中或启用软中断的情况下调用此函数。

必须同步针对单个硬件的此函数的调用。

返回

成功时返回 0。当请求的 PS 模式已设置时,返回 -EINVAL。

int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, bool start)

已连接站点的 PS 转换(在进程上下文中)

参数

struct ieee80211_sta *sta

当前已连接的站点

bool start

启动或停止 PS

描述

ieee80211_sta_ps_transition() 类似,但可以在进程上下文中调用(内部禁用下半部)。并发调用限制仍然适用。

返回

ieee80211_sta_ps_transition() 类似。

void ieee80211_sta_set_buffered(struct ieee80211_sta *sta, u8 tid, bool buffered)

通知 mac80211 驱动程序缓冲的帧

参数

struct ieee80211_sta *sta

睡眠站点的 struct ieee80211_sta 指针

u8 tid

具有缓冲帧的 TID

bool buffered

指示是否为此 TID 缓冲了帧

描述

如果驱动程序缓冲了节能站点的帧,而不是将它们传递回 mac80211 以进行重传,则可能仍然需要通过 TIM 位告知该站点存在缓冲帧。

此函数告知 mac80211 在驱动程序中是否缓冲了给定 TID 的帧;然后,mac80211 可以使用此数据来设置 TIM 位(注意:这可能会回调到驱动程序的 set_tim 调用中!请注意锁定!)

如果所有帧都已释放到站点(由于 PS-poll 或 uAPSD),则驱动程序需要通知 mac80211 不再有帧被缓冲。但是,当站点唤醒时,mac80211 假定所有缓冲的帧都将被传输并清除此数据,驱动程序需要确保它们在睡眠转换(sta_notify(),带有 STA_NOTIFY_SLEEP)时通知 mac80211 所有缓冲的帧。

请注意,从技术上讲,mac80211 只需要知道每个 AC(而不是每个 TID)的此信息,但是由于驱动程序缓冲不可避免地会按 TID 发生(因为它与聚合相关),因此使 mac80211 将 TID 映射到所需的 AC 更容易,而不是在所有使用此 API 的驱动程序中进行跟踪。

struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id)

信标生成函数

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

unsigned int link_id

信标所属的链接 ID(对于未与 AP MLD 关联的 AP STA,则为 0)。

描述

请参阅 ieee80211_beacon_get_tim()。

返回

请参阅 ieee80211_beacon_get_tim()。

struct sk_buff *ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif)

访问缓冲的广播和多播帧

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

描述

用于访问缓冲的广播和多播帧的函数。如果硬件/固件未在节能时实现广播/多播帧的缓冲,则 802.11 代码会将它们缓冲在主机内存中。底层驱动程序使用此函数获取下一个缓冲帧。在大多数情况下,这在生成信标帧时使用。

返回

指向下一个缓冲 skb 的指针,如果没有更多缓冲帧可用,则为 NULL。

注意

仅在使用 ieee80211_beacon_get() 生成 DTIM 信标帧后才返回缓冲帧,因此底层驱动程序必须首先调用 ieee80211_beacon_get()。如果先前生成的信标不是 DTIM,则 ieee80211_get_buffered_bc() 返回 NULL,因此底层驱动程序不需要单独检查 DTIM 信标,并且应该能够对所有信标使用通用代码。

void ieee80211_sta_block_awake(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, bool block)

阻止站点唤醒

参数

struct ieee80211_hw *hw

硬件

struct ieee80211_sta *pubsta

站点

bool block

是否阻止或取消阻止

描述

某些设备要求在可以将轮询响应或站点唤醒后的帧传递到队列中之前,必须刷新特定站点的所有帧。请注意,此类帧必须被驱动程序拒绝为已过滤,并带有适当的状态标志。

此函数允许以无竞争的方式实现此模式。

为此,驱动程序必须跟踪仍为特定站点排队的帧数。如果站点进入睡眠状态时此数字不为零,则驱动程序必须调用此函数以强制 mac80211 认为该站点处于睡眠状态,而不管该站点的实际状态如何。一旦未完成帧的数量达到零,驱动程序必须再次调用此函数以取消阻止该站点。这将导致 mac80211 能够发送 ps-poll 响应,并且如果该站点在此期间进行了查询,则也将发送帧。此外,无论站点在被阻止时是否实际唤醒,驱动程序都会收到该站点在取消阻止后一段时间唤醒的通知。

void ieee80211_sta_eosp(struct ieee80211_sta *pubsta)

通知 mac80211 SP 结束

参数

struct ieee80211_sta *pubsta

站点

描述

当设备以一种无法在 TX 状态下告知 mac80211 EOSP 的方式传输帧时,它必须清除 IEEE80211_TX_STATUS_EOSP 位并改为调用此函数。这适用于 PS-Poll 以及 uAPSD。

请注意,就像使用 _tx_status() 和 _rx() 一样,驱动程序不得混合调用 irqsafe/non-irqsafe 版本,此函数也不得与这些版本混合使用。使用所有 irqsafe 或所有 non-irqsafe,不要混合使用!

注意:此函数的 _irqsafe 版本不存在,目前没有

驱动程序需要它。如果您需要 _irqsafe 版本,请勿调用此函数,查看 git 历史记录并恢复 _irqsafe 版本!

支持多个虚拟接口

待定

注意:具有相同 MAC 地址的 WDS 几乎总是可以的

在此处插入有关具有不同 MAC 地址的多个虚拟接口的注释,请注意 mac80211 支持哪些配置,添加有关使用它支持硬件加密的注释。

void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, u32 iter_flags, void (*iterator)(void *data, u8 *mac, struct ieee80211_vif *vif), void *data)

迭代活动接口

参数

struct ieee80211_hw *hw

应该在其上迭代接口的硬件结构

u32 iter_flags

迭代标志,请参阅 enum ieee80211_interface_iteration_flags

void (*iterator)(void *data, u8 *mac, struct ieee80211_vif *vif)

要调用的迭代器函数

void *data

迭代器函数的第一个参数

描述

此函数迭代与给定硬件关联的当前活动的接口,并为它们调用回调。当迭代器函数可以休眠时,可以使用原子迭代器函数 ieee80211_iterate_active_interfaces_atomic。在 add_interface() 期间不会迭代新接口。

void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, u32 iter_flags, void (*iterator)(void *data, u8 *mac, struct ieee80211_vif *vif), void *data)

迭代活动接口

参数

struct ieee80211_hw *hw

应该在其上迭代接口的硬件结构

u32 iter_flags

迭代标志,请参阅 enum ieee80211_interface_iteration_flags

void (*iterator)(void *data, u8 *mac, struct ieee80211_vif *vif)

要调用的迭代器函数,无法休眠

void *data

迭代器函数的第一个参数

描述

此函数迭代与给定硬件关联的当前活动的接口,并为它们调用回调。此函数要求迭代器回调函数是原子的,如果不希望这样,请改用 ieee80211_iterate_active_interfaces。在 add_interface() 期间不会迭代新接口。

站点处理

TODO

struct ieee80211_sta

站点表条目

定义:

struct ieee80211_sta {
    u8 addr[ETH_ALEN] ;
    u16 aid;
    u16 max_rx_aggregation_subframes;
    bool wme;
    u8 uapsd_queues;
    u8 max_sp;
    struct ieee80211_sta_rates __rcu *rates;
    bool tdls;
    bool tdls_initiator;
    bool mfp;
    bool mlo;
    bool spp_amsdu;
    u8 max_amsdu_subframes;
    u16 eml_cap;
    struct ieee80211_sta_aggregates *cur;
    bool support_p2p_ps;
    struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
    u16 valid_links;
    struct ieee80211_link_sta deflink;
    struct ieee80211_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
    u8 drv_priv[] ;
};

成员

addr

MAC 地址

aid

如果我是 AP,则分配给站点的 AID

max_rx_aggregation_subframes

此站点允许传输给我们的单个 AMPDU 中的最大帧数。可以由驱动程序修改。

wme

指示 STA 是否支持 QoS/WME(如果本地设备支持,否则始终为 false)

uapsd_queues

为 uapsd 配置的队列的位图。仅当支持 wme 时才有效。位的顺序类似于 IEEE80211_WMM_IE_STA_QOSINFO_AC_*。

max_sp

最大服务周期。仅当支持 wme 时才有效。

rates

速率控制选择表

tdls

指示 STA 是否为 TDLS 对等方

tdls_initiator

指示 STA 是否为 TDLS 链接的发起方。仅当 STA 首先是 TDLS 对等方时才有效。

mfp

指示 STA 是否使用管理帧保护。

mlo

指示 STA 是否为 MLO 站点。

spp_amsdu

指示 STA 是否使用 SPP A-MSDU。

max_amsdu_subframes

指示单个 A-MSDU 中的 MSDU 最大数量。取自扩展功能元素。0 表示无限制。

eml_cap

此 MLO 站点的 EML 功能

cur

当前有效数据,是从活动链接聚合的。对于非 MLO STA,它将指向 deflink 数据。对于 MLO STA,必须调用 ieee80211_sta_recalc_aggregates() 才能更新它。

support_p2p_ps

指示 STA 是否支持 P2P PS 机制。

txq

每个 TID 数据 TX 队列;请注意,最后一个条目 (IEEE80211_NUM_TIDS) 用于非数据帧

valid_links

有效链接的位图,对于非 MLO,则为 0

deflink

这保存默认链接 STA 信息,对于非 MLO STA,所有链接特定的 STA 信息都通过 deflink 或通过指向 deflink 地址的 link[0] 访问。对于 MLO Link STA,第一个添加的链接 STA 将指向 deflink。

link

对 Link Sta 条目的引用。对于 Non MLO STA,除了第一个链接(即 link[0])之外,所有链接默认都将被分配为 NULL,并且将通过 deflink 或 link[0] 访问链接信息。对于 MLO STA,正在添加的第一个链接 STA 将其链接指针指向 deflink 地址,其余链接将被分配,并且该地址将被分配给 link[link_id],其中 link_id 是由 AP 分配的 ID。

drv_priv

用于驱动程序使用的数据区域,将始终与 sizeof(void *) 对齐,大小在硬件信息中确定。

描述

站点表条目表示我们可能与之通信的站点。由于站点在 mac80211 中是 RCU 管理的,因此您访问的任何 ieee80211_sta 指针都必须受到 rcu_read_lock() 的显式或隐式保护,或者您必须注意在调用 sta_remove 回调(已删除它)后不要使用此类指针。这也表示 MLO 关联情况下的 MLD STA,并保存指向各种链接 STA 的指针

enum sta_notify_cmd

sta 通知命令

常量

STA_NOTIFY_SLEEP

站点现在正在睡眠

STA_NOTIFY_AWAKE

睡眠站点已唤醒

描述

struct ieee80211_ops 中的 sta_notify() 回调一起使用,指示关联的站点是否进行了电源状态转换。

struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, const u8 *addr)

查找站点

参数

struct ieee80211_vif *vif

在其上查找站点的虚拟接口

const u8 *addr

站点的地址

返回

如果找到,则为站点。否则为 NULL

注意

此函数必须在 RCU 锁下调用,并且结果指针也仅在 RCU 锁下有效。

struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw, const u8 *addr, const u8 *localaddr)

在硬件上查找站点

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针

const u8 *addr

远程站点地址

const u8 *localaddr

本地地址 (vif->sdata->vif.addr)。对于“任意”地址,使用 NULL。

返回

如果找到,则为站点。否则为 NULL

注意

此函数必须在 RCU 锁下调用,并且结果指针也仅在 RCU 锁下有效。

注意

您可以为 localaddr 传递 NULL,但这样您只能获得

与远程地址“addr”匹配的第一个 STA。我们可以有多个 STA 与多个逻辑站相关联(例如,考虑一个站点在同一 AP 硬件上连接到另一个 BSSID,而无需先断开连接)。在这种情况下,当 localaddr 为 NULL 时,此方法的结果不可靠。

描述

如果可能,请不要使用 localaddr 为 NULL 的此函数。

硬件扫描卸载

待定

void ieee80211_scan_completed(struct ieee80211_hw *hw, struct cfg80211_scan_info *info)

硬件扫描完成

参数

struct ieee80211_hw *hw

完成扫描的硬件

struct cfg80211_scan_info *info

有关已完成扫描的信息

描述

当使用硬件扫描卸载时(即,已分配 hw_scan() 回调),驱动程序需要调用此函数以通知 mac80211 扫描已完成。可以从任何上下文调用此函数,包括硬中断上下文。

聚合

TX A-MPDU 聚合

TX 端的聚合需要设置硬件标志 IEEE80211_HW_AMPDU_AGGREGATION。然后,驱动程序将收到带有标志的包,指示 A-MPDU 聚合。驱动程序或设备负责实际聚合帧,以及决定聚合多少帧和哪些帧。

当 TX 聚合由某些子系统启动时(通常速率控制算法是合适的),通过调用 ieee80211_start_tx_ba_session() 函数,驱动程序将通过其 ampdu_action 函数收到通知,并带有 IEEE80211_AMPDU_TX_START 操作。

作为对此的响应,稍后需要驱动程序调用 ieee80211_start_tx_ba_cb_irqsafe() 函数,该函数将在对等方也响应后真正启动聚合会话。如果对等方响应为否定,则会话将立即再次停止。请注意,聚合会话可能在驱动程序指示其已完成设置之前停止,在这种情况下,它不得指示设置完成。

另请注意,由于我们还需要等待来自对等方的响应,因此驱动程序会通过 ampdu_action 回调的 IEEE80211_AMPDU_TX_OPERATIONAL 操作来通知握手完成。

类似地,当聚合会话被对等方或调用 ieee80211_stop_tx_ba_session() 的某些内容停止时,将使用操作 IEEE80211_AMPDU_TX_STOP 调用驱动程序的 ampdu_action 函数。在这种情况下,调用不得失败,并且驱动程序稍后必须调用 ieee80211_stop_tx_ba_cb_irqsafe()。请注意,sta 可能会在 BA 拆卸完成之前被销毁。

RX A-MPDU 聚合

RX 端的聚合仅需要实现 ampdu_action 回调,该回调用于启动/停止 RX 聚合的任何块确认会话。

当 RX 聚合由对等方启动时,会通过 ampdu_action 函数收到通知,并带有 IEEE80211_AMPDU_RX_START 操作,并且可以拒绝该请求,在这种情况下,会向对等方发送否定响应,如果接受该请求,则发送肯定响应。

在会话处于活动状态时,设备/驱动程序需要取消聚合帧,并将它们逐个传递给 mac80211,这将处理重新排序缓冲区。

当聚合会话再次被对等方或我们自己停止时,将使用操作 IEEE80211_AMPDU_RX_STOP 调用驱动程序的 ampdu_action 函数。在这种情况下,调用不得失败。

enum ieee80211_ampdu_mlme_action

A-MPDU 操作

常量

IEEE80211_AMPDU_RX_START

启动 RX 聚合

IEEE80211_AMPDU_RX_STOP

停止 RX 聚合

IEEE80211_AMPDU_TX_START

启动 TX 聚合,驱动程序必须调用 ieee80211_start_tx_ba_cb_irqsafe() 或调用 ieee80211_start_tx_ba_cb_irqsafe(),状态为 IEEE80211_AMPDU_TX_START_DELAY_ADDBA,以在调用 ieee80211_start_tx_ba_cb_irqsafe 后延迟 addba,或者仅返回特殊状态 IEEE80211_AMPDU_TX_START_IMMEDIATE

IEEE80211_AMPDU_TX_STOP_CONT

停止 TX 聚合,但继续传输排队的包,现在未聚合。在传输所有包后,驱动程序必须调用 ieee80211_stop_tx_ba_cb_irqsafe()

IEEE80211_AMPDU_TX_STOP_FLUSH

停止 TX 聚合并刷新所有包,当删除站点时调用。在这种情况下,无需或没有理由调用 ieee80211_stop_tx_ba_cb_irqsafe(),因为 mac80211 假定会话已消失并删除站点。

IEEE80211_AMPDU_TX_STOP_FLUSH_CONT

当停止 TX 聚合但驱动程序尚未调用 ieee80211_stop_tx_ba_cb_irqsafe() 时,以及现在连接已断开且站点将被删除时调用。驱动程序应清理并删除剩余的包。

IEEE80211_AMPDU_TX_OPERATIONAL

TX 聚合已变为可操作

描述

这些标志与 struct ieee80211_ops 中的 ampdu_action() 回调一起使用,以指示所需的操作。

请注意,驱动程序必须能够处理 TX 聚合会话的停止,即使在他们通过调用 ieee80211_start_tx_ba_cb_irqsafe 来确认启动它之前,因为对等方可能会收到 addBA 帧并立即发送 delBA!

空间复用省电 (SMPS)

SMPS(空间复用省电)是一种在 802.11n 实现中节省电能的机制。有关该机制和基本原理的详细信息,请参阅 802.11(由 802.11n-2009 修订)“11.2.3 SM 省电”。

mac80211 实现能够发送操作帧以更新 AP 关于站点的 SMPS 模式,并将指示驱动程序进入特定模式。它还将在关联握手期间宣布请求的 SMPS 模式。需要对此功能的硬件支持,并且可以通过硬件标志指示。

默认模式将为“自动”,nl80211/cfg80211 将其定义为(常规)省电模式下的动态 SMPS,否则 SMPS 将关闭。

为了支持此功能,驱动程序必须设置适当的硬件支持标志,并将 SMPS 标志处理到 config() 操作。然后,在此机制下,将指示它在关联到 HT AP 时进入请求的 SMPS 模式。

enum ieee80211_smps_mode

空间复用省电模式

常量

IEEE80211_SMPS_AUTOMATIC

自动

IEEE80211_SMPS_OFF

关闭

IEEE80211_SMPS_STATIC

静态

IEEE80211_SMPS_DYNAMIC

动态

IEEE80211_SMPS_NUM_MODES

内部,请勿使用

void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id, enum ieee80211_smps_mode smps_mode)

请求 SM PS 转换

参数

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

unsigned int link_id

MLO 的链接 ID,或 0

enum ieee80211_smps_mode smps_mode

新的 SM PS 模式

描述

这允许驱动程序在托管模式下请求 SM PS 转换。当驱动程序比堆栈具有更多关于可能干扰的信息时,例如通过蓝牙,这非常有用。

待定

本书的这一部分描述了速率控制算法接口以及它如何与 mac80211 和驱动程序相关。

速率控制 API

待定

enum ieee80211_rate_control_changed

指示更改内容的标志

常量

IEEE80211_RC_BW_CHANGED

可用于传输到此站点的带宽已更改。实际带宽位于站点信息中 -- 对于 HT20/40,IEEE80211_HT_CAP_SUP_WIDTH_20_40 标志会更改,对于 HT 和 VHT,带宽字段会更改。

IEEE80211_RC_SMPS_CHANGED

站点的 SMPS 状态已更改。

IEEE80211_RC_SUPP_RATES_CHANGED

由于发现有关对等方的更多信息,此对等方的支持速率集已更改(在 IBSS 模式下)。

IEEE80211_RC_NSS_CHANGED

N_SS(空间流的数量)已由对等方更改

int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid, u16 timeout)

启动 tx 块确认会话。

参数

struct ieee80211_sta *sta

要为其启动 BA 会话的站点

u16 tid

要在其上进行 BA 的 TID。

u16 timeout

会话超时值(以 TU 为单位)

返回

如果已发送 addBA 请求,则成功,否则失败

描述

虽然 mac80211/低级驱动程序/用户空间应用程序可以估计在特定 RA/TID 上启动聚合的需要,但会话级别将由 mac80211 管理。

void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, u16 tid)

低级驱动程序已准备好聚合。

参数

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针

const u8 *ra

BA 会话接收者的接收方地址。

u16 tid

要在其上进行 BA 的 TID。

描述

一旦低级驱动程序完成 BA 会话的准备工作,就必须调用此函数。可以从任何上下文调用它。

int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid)

停止块确认会话。

参数

struct ieee80211_sta *sta

要停止其 BA 会话的站点

u16 tid

要停止 BA 的 TID。

返回

如果 TID 无效,或者没有活动的聚合,则返回负错误

描述

虽然 mac80211/低级驱动程序/用户空间应用程序可以估计在特定 RA/TID 上停止聚合的需要,但会话级别将由 mac80211 管理。

void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, u16 tid)

低级驱动程序已准备好停止聚合。

参数

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针

const u8 *ra

BA 会话接收者的接收方地址。

u16 tid

要在其上进行 BA 的所需 TID。

描述

一旦低级驱动程序完成 BA 会话拆卸的准备工作,就必须调用此函数。可以从任何上下文调用它。

struct ieee80211_tx_rate_control

来自/用于 RC 算法的速率控制信息

定义:

struct ieee80211_tx_rate_control {
    struct ieee80211_hw *hw;
    struct ieee80211_supported_band *sband;
    struct ieee80211_bss_conf *bss_conf;
    struct sk_buff *skb;
    struct ieee80211_tx_rate reported_rate;
    bool rts, short_preamble;
    u32 rate_idx_mask;
    u8 *rate_idx_mcs_mask;
    bool bss;
};

成员

hw

为其调用算法的硬件。

sband

正在其上发送此帧的频段。

bss_conf

当前 BSS 配置

skb

将要发送的 skb,需要在其中填写控制信息

reported_rate

速率控制算法可以填写此项以指示应向用户空间报告哪个速率作为当前速率,并用于网状网络中的速率计算。

rts

是否将对此帧使用 RTS,因为它长于 RTS 阈值

short_preamble

如果所选速率支持短前导码传输,mac80211 是否会请求短前导码传输

rate_idx_mask

用户请求的(旧版)速率掩码

rate_idx_mcs_mask

用户请求的 MCS 速率掩码(如果未使用,则为 NULL)

bss

此帧是否以 AP 或 IBSS 模式发送

待定

本书的这一部分描述了 mac80211 内部结构。

密钥处理

密钥处理基础知识

mac80211 中的密钥处理基于每个接口 (sub_if_data) 密钥和每个站点密钥完成。由于每个站点都属于一个接口,因此每个站点密钥也属于该接口。

硬件加速是以最大努力的方式为软件中实现的算法完成的,对于每个密钥,都会要求硬件启用该密钥以进行卸载,但如果硬件无法执行此操作,则只会保留该密钥以进行软件加密(除非它是用于软件中未实现的算法)。目前除了查看 debugfs 之外,没有办法知道密钥是在 SW 还是 HW 中处理的。

所有密钥管理都在内部由互斥锁保护。在 mac80211 的所有其他部分中,密钥引用就像 STA 结构引用一样,受到 RCU 的保护。但是请注意,有些事情是不受保护的,即硬件加速函数中的 key->sta 解引用。这意味着 sta_info_destroy() 必须删除密钥,该密钥等待 RCU 宽限期。

更多待定

待定

接收处理

待定

传输处理

待定

站点信息处理

编程信息

enum ieee80211_sta_info_flags

站点标志

常量

WLAN_STA_AUTH

站点已通过身份验证。

WLAN_STA_ASSOC

站点已关联。

WLAN_STA_PS_STA

站点处于省电模式

WLAN_STA_AUTHORIZED

站点已授权发送/接收流量。始终检查此位,因此对于未使用虚拟端口控制的所有站点都需要启用此位。

WLAN_STA_SHORT_PREAMBLE

站点能够接收短前导码帧。

WLAN_STA_WDS

站点是我们 WDS 对等方之一。

WLAN_STA_CLEAR_PS_FILT

当向此站点发送下一个帧时,清除硬件中的 PS 过滤器(使用 IEEE80211_TX_CTL_CLEAR_PS_FILT 控制标志)。

WLAN_STA_MFP

管理帧保护用于此 STA。

WLAN_STA_BLOCK_BA

用于在挂起/恢复和站点移除期间拒绝 ADDBA 请求(TX 和 RX)。

WLAN_STA_PS_DRIVER

驱动程序需要逻辑上将此站点保持在省电模式,以刷新可能仍在队列中的帧

WLAN_STA_PSPOLL

当驱动程序将站点保持在省电模式时,站点发送了 PS-poll,在驱动程序解除阻塞时回复。

WLAN_STA_TDLS_PEER

站点是 TDLS 对等方。

WLAN_STA_TDLS_PEER_AUTH

此 TDLS 对等方已授权发送直接数据包。这意味着已启用链接。

WLAN_STA_TDLS_INITIATOR

我们是与此站点的 TDLS 链接的发起者。

WLAN_STA_TDLS_CHAN_SWITCH

此 TDLS 对等方支持 TDLS 通道切换

WLAN_STA_TDLS_OFF_CHANNEL

本地 STA 当前与此 TDLS 对等方断开通道

WLAN_STA_TDLS_WIDER_BW

此 TDLS 对等方支持在 BSS 基本通道上使用更宽的 bw。

WLAN_STA_UAPSD

当驱动程序将站点保持在省电模式时,站点请求了计划外的 SP,在驱动程序解除阻塞站点时回复。

WLAN_STA_SP

站点处于服务期,因此不要尝试回复其他 uAPSD 触发帧或 PS-Poll。

WLAN_STA_4ADDR_EVENT

已为此帧发送了 4 地址事件。

WLAN_STA_INSERTED

此站点已插入到哈希表中。

WLAN_STA_RATE_CONTROL

已为此站点初始化速率控制。

WLAN_STA_TOFFSET_KNOWN

为此站点计算的 toffset 有效。

WLAN_STA_MPSP_OWNER

本地 STA 是网状网络对等方服务期的所有者。

WLAN_STA_MPSP_RECIPIENT

本地 STA 是 MPSP 的接收者。

WLAN_STA_PS_DELIVER

站点已唤醒,但在传送挂起的帧之前,我们仍在阻止 TX

WLAN_STA_USES_ENCRYPTION

此站点配置为加密,因此稍后会删除所有没有密钥的数据包。

WLAN_STA_DECAP_OFFLOAD

此站点使用 rx 解封装卸载

NUM_WLAN_STA_FLAGS

已定义的标志数

描述

这些标志与 struct sta_infoflags 成员一起使用,但仅间接与 set_sta_flag() 及其朋友一起使用。

struct sta_info

STA 信息

定义:

struct sta_info {
    struct list_head list, free_list;
    struct rcu_head rcu_head;
    struct rhlist_head hash_node;
    u8 addr[ETH_ALEN];
    struct ieee80211_local *local;
    struct ieee80211_sub_if_data *sdata;
    struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
    u8 ptk_idx;
    struct rate_control_ref *rate_ctrl;
    void *rate_ctrl_priv;
    spinlock_t rate_ctrl_lock;
    spinlock_t lock;
    struct ieee80211_fast_tx __rcu *fast_tx;
    struct ieee80211_fast_rx __rcu *fast_rx;
#ifdef CONFIG_MAC80211_MESH;
    struct mesh_sta *mesh;
#endif;
    struct work_struct drv_deliver_wk;
    u16 listen_interval;
    bool dead;
    bool removed;
    bool uploaded;
    enum ieee80211_sta_state sta_state;
    unsigned long _flags;
    spinlock_t ps_lock;
    struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
    struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
    unsigned long driver_buffered_tids;
    unsigned long txq_buffered_tids;
    u64 assoc_at;
    long last_connected;
    __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
    u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
    struct airtime_info airtime[IEEE80211_NUM_ACS];
    u16 airtime_weight;
    struct sta_ampdu_mlme ampdu_mlme;
#ifdef CONFIG_MAC80211_DEBUGFS;
    struct dentry *debugfs_dir;
#endif;
    u8 reserved_tid;
    s8 amsdu_mesh_control;
    struct cfg80211_chan_def tdls_chandef;
    struct ieee80211_fragment_cache frags;
    struct ieee80211_sta_aggregates cur;
    struct link_sta_info deflink;
    struct link_sta_info __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
    struct ieee80211_sta sta;
};

成员

list

全局链表条目

free_list

用于跟踪要释放的站点的列表条目

rcu_head

用于释放此站点结构的 RCU 头

hash_node

用于 rhashtable 的哈希节点

addr

站点的 MAC 地址 - 从公共部分复制,以便哈希表仅使用单个缓存行

local

指向全局信息的指针

sdata

此站点所属的虚拟接口

ptk

与此站点协商的对等方密钥(如果有)

ptk_idx

上次安装的对等方密钥索引

rate_ctrl

速率控制算法引用

rate_ctrl_priv

每个 STA 的速率控制私有指针

rate_ctrl_lock

用于保护速率控制数据的自旋锁(算法内部的数据,因此串行化对算法的调用)

lock

用于锁定所有需要锁定的字段,请参阅头文件中的注释。

fast_tx

TX 快速路径信息

fast_rx

RX 快速路径信息

mesh

网状网络 STA 信息

drv_deliver_wk

用于在驱动程序 PS 解除阻塞后传送帧

listen_interval

此站点的侦听间隔,当我们充当 AP 时

dead

当 sta 取消链接时设置为 true

removed

当 sta 从 sta_list 中删除时设置为 true

uploaded

当 sta 上传到驱动程序时设置为 true

sta_state

复制有关站点状态的信息(用于调试)

_flags

STA 标志,请参阅 enum ieee80211_sta_info_flags,请勿直接使用

ps_lock

用于省电(当 mac80211 是 AP 时)相关的锁定

ps_tx_buf

当站点离开省电状态或轮询时,要传输到此站点的帧缓冲区(每个 AC)

tx_filtered

由于 STA 已进入省电状态,我们已尝试传输但被硬件过滤的帧缓冲区(每个 AC),当站点离开省电状态或轮询帧时,这些帧也会传递到站点

driver_buffered_tids

驱动程序已缓冲数据的 TID 位图

txq_buffered_tids

mac80211 已缓冲 txq 数据的 TID 位图

assoc_at

上次关联的时钟启动时间(以纳秒为单位)

last_connected

站点连接的时间(以秒为单位)

last_seq_ctrl

来自此 STA 的上次接收的 seq/frag 编号(每个 TID 加一表示非 QoS 帧)

tid_seq

用于发送到此 STA 的每个 TID 的序列号

airtime

每个 AC 的 struct airtime_info,描述此站点的空口时间统计信息

airtime_weight

用于空口时间公平性计算目的的站点权重

ampdu_mlme

A-MPDU 状态机状态

debugfs_dir

调试文件系统目录 dentry

reserved_tid

保留的 TID(如果有,否则为 IEEE80211_TID_UNRESERVED)

amsdu_mesh_control

跟踪对等方使用的网状网络 A-MSDU 格式

  • -1:未知

  • 0:非网状网络 A-MSDU 长度字段

  • 1:大端网状网络 A-MSDU 长度字段

  • 2:小端网状网络 A-MSDU 长度字段

tdls_chandef

TDLS 对等方可以具有与 BSS 兼容的更宽的 chandef。

frags

片段缓存

cur

用于聚合数据的存储 struct ieee80211_sta 指向此处或 deflink.agg。

deflink

这是默认的链接 STA 信息,对于非 MLO STA,所有链接特定的 STA 信息都通过 deflink 或通过指向 deflink 地址的 link[0] 访问。对于 MLO 链接 STA,第一个添加的链接 STA 将指向 deflink。

link

对 Link Sta 条目的引用。对于 Non MLO STA,除了第一个链接(即 link[0])之外,所有链接默认都将被分配为 NULL,并且将通过 deflink 或 link[0] 访问链接信息。对于 MLO STA,正在添加的第一个链接 STA 将其链接指针指向 deflink 地址,其余链接将被分配,并且该地址将被分配给 link[link_id],其中 link_id 是由 AP 分配的 ID。

sta

我们与驱动程序共享的站点信息

描述

此结构收集有关 mac80211 正在与其通信的站点的信息。

STA 信息生存期规则

STA 信息结构 (struct sta_info) 在哈希表中管理,以便更快地查找,并在列表中管理,以便进行迭代。它们使用 RCU 进行管理,即对列表和哈希表的访问受到 RCU 的保护。

在通过 sta_info_alloc() 分配 STA 信息结构时,调用者拥有该结构。然后,它必须使用 sta_info_insert() 或 sta_info_insert_rcu() 将其插入到哈希表中;只有在后一种情况下(这会获取 rcu 读取节,但不得从中调用),指针在调用后仍然有效。请注意,调用者在插入之前可能无法对 STA 信息执行太多操作;特别是,它可能不会启动任何网状网络对等方链接管理或添加加密密钥。

当插入失败时 (sta_info_insert()) 返回非零值),该结构将已被 sta_info_insert() 释放!

当您与对等方建立链接时,mac80211 会添加站点条目。这意味着对于我们支持的不同类型的接口,意义有所不同。对于常规站点,这意味着我们在收到来自 AP 的关联响应时添加 AP sta。对于 IBSS,这发生在了解同一 IBSS 上的对等方时。对于 WDS,我们在设备打开时立即添加对等方的 sta。当使用 AP 模式时,我们在用户空间通过 nl80211 请求后,为每个站点添加站点。

为了删除 STA 信息结构,可以使用各种 sta_info_destroy_*() 调用。

STA 条目没有所有权的概念;每个结构都由全局哈希表/列表拥有,直到它被删除。结构的所有用户都需要受到 RCU 保护,以便在他们完成使用该结构之前不会释放该结构。

聚合函数

struct tid_ampdu_tx

TID 聚合信息 (Tx)。

定义:

struct tid_ampdu_tx {
    struct rcu_head rcu_head;
    struct timer_list session_timer;
    struct timer_list addba_resp_timer;
    struct sk_buff_head pending;
    struct sta_info *sta;
    unsigned long state;
    unsigned long last_tx;
    u16 timeout;
    u8 dialog_token;
    u8 stop_initiator;
    bool tx_stop;
    u16 buf_size;
    u16 ssn;
    u16 failed_bar_ssn;
    bool bar_pending;
    bool amsdu;
    u8 tid;
};

成员

rcu_head

用于释放结构的 rcu 头

session_timer

检查我们是否保持在 TID 上 Tx-ing(按超时值)

addba_resp_timer

用于对等方对 addba 请求的响应的计时器

pending

挂起的帧队列 -- 使用 sta 的自旋锁进行保护

sta

station we are attached to

state

session state (see above)

last_tx

jiffies of last tx activity

timeout

session timeout value to be filled in ADDBA requests

dialog_token

dialog token for aggregation session

stop_initiator

initiator of a session stop

tx_stop

TX DelBA frame when stopping

buf_size

reorder buffer size at receiver

ssn

starting sequence number of the session

failed_bar_ssn

ssn of the last failed BAR tx attempt

bar_pending

BAR needs to be re-sent

amsdu

support A-MSDU within A-MDPU

tid

TID number

描述

This structure’s lifetime is managed by RCU, assignments to the array holding it must hold the aggregation mutex.

The TX path can access it under RCU lock-free if, and only if, the state has the flag HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path must also acquire the spinlock and re-check the state, see comments in the tx code touching it.

struct tid_ampdu_rx

TID aggregation information (Rx).

定义:

struct tid_ampdu_rx {
    struct rcu_head rcu_head;
    spinlock_t reorder_lock;
    u64 reorder_buf_filtered;
    struct sk_buff_head *reorder_buf;
    unsigned long *reorder_time;
    struct sta_info *sta;
    struct timer_list session_timer;
    struct timer_list reorder_timer;
    unsigned long last_rx;
    u16 head_seq_num;
    u16 stored_mpdu_num;
    u16 ssn;
    u16 buf_size;
    u16 timeout;
    u8 tid;
    u8 auto_seq:1,removed:1, started:1;
};

成员

rcu_head

RCU head used for freeing this struct

reorder_lock

serializes access to reorder buffer, see below.

reorder_buf_filtered

bitmap indicating where there are filtered frames in the reorder buffer that should be ignored when releasing frames

reorder_buf

buffer to reorder incoming aggregated MPDUs. An MPDU may be an A-MSDU with individually reported subframes.

reorder_time

jiffies when skb was added

sta

station we are attached to

session_timer

check if peer keeps Tx-ing on the TID (by timeout value)

reorder_timer

releases expired frames from the reorder buffer.

last_rx

jiffies of last rx activity

head_seq_num

head sequence number in reordering buffer.

stored_mpdu_num

number of MPDUs in reordering buffer

ssn

Starting Sequence Number expected to be aggregated.

buf_size

buffer size for incoming A-MPDUs

timeout

reset timer value (in TUs).

tid

TID number

auto_seq

used for offloaded BA sessions to automatically pick head_seq_and and ssn.

removed

this session is removed (but might have been found due to RCU)

started

this session has started (head ssn or higher was received)

描述

This structure’s lifetime is managed by RCU, assignments to the array holding it must hold the aggregation mutex.

The reorder_lock is used to protect the members of this struct, except for timeout, buf_size and dialog_token, which are constant across the lifetime of the struct (the dialog token being used only for debugging).

struct sta_ampdu_mlme

STA aggregation information.

定义:

struct sta_ampdu_mlme {
    struct tid_ampdu_rx __rcu *tid_rx[IEEE80211_NUM_TIDS];
    u8 tid_rx_token[IEEE80211_NUM_TIDS];
    unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
    unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
    unsigned long tid_rx_manage_offl[BITS_TO_LONGS(2 * IEEE80211_NUM_TIDS)];
    unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
    unsigned long unexpected_agg[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
    struct wiphy_work work;
    struct tid_ampdu_tx __rcu *tid_tx[IEEE80211_NUM_TIDS];
    struct tid_ampdu_tx *tid_start_tx[IEEE80211_NUM_TIDS];
    unsigned long last_addba_req_time[IEEE80211_NUM_TIDS];
    u8 addba_req_num[IEEE80211_NUM_TIDS];
    u8 dialog_token_allocator;
};

成员

tid_rx

aggregation info for Rx per TID -- RCU protected

tid_rx_token

dialog tokens for valid aggregation sessions

tid_rx_timer_expired

bitmap indicating on which TIDs the RX timer expired until the work for it runs

tid_rx_stop_requested

bitmap indicating which BA sessions per TID the driver requested to close until the work for it runs

tid_rx_manage_offl

bitmap indicating which BA sessions were requested to be treated as started/stopped due to offloading

agg_session_valid

bitmap indicating which TID has a rx BA session open on

unexpected_agg

bitmap indicating which TID already sent a delBA due to unexpected aggregation related frames outside a session

work

work struct for starting/stopping aggregation

tid_tx

aggregation info for Tx per TID

tid_start_tx

sessions where start was requested, not just protected by wiphy mutex but also sta->lock

last_addba_req_time

timestamp of the last addBA request.

addba_req_num

number of times addBA request has been sent.

dialog_token_allocator

dialog token enumerator for each new session;

Synchronisation Functions

待定

Locking, lots of RCU