mac80211 子系统(基础)

在实现 mac80211 驱动程序时,您应该阅读并理解本书本部分中包含的信息。在某些章节中,会注明高级用法,如果不需要,可以跳过这些用法。

本书的这一部分仅涵盖站点和监视器模式功能,实现其他模式所需的其他信息将在本书的第二部分中介绍。

基本硬件处理

待定

本章应包含有关获取已分配并向 mac80211 注册的 hw 结构的信息。

由于需要在注册 hw 结构之前分配速率/模式,因此本章还应包含有关设置速率/模式结构的信息。

此外,这里应该讨论一下回调和通用编程模型,包括对 ieee80211_ops 的定义,后面会经常引用该定义。

最后,应该讨论一下硬件功能,并参考本书的其他部分。

enum ieee80211_hw_flags

硬件标志

常量

IEEE80211_HW_HAS_RATE_CONTROL

硬件或固件包含速率控制,并且无法由堆栈控制。因此,不应实例化速率控制算法,并且报告给用户空间的 TX 速率将从 TX 状态而不是速率控制算法中获取。请注意,这要求驱动程序实现许多回调,以便它具有正确的信息,它需要具有 set_rts_threshold 回调,并且必须查看 BSS 配置 use_cts_prot 用于 G/N 保护,use_short_slot 用于 2.4 GHz 中的时隙定时,以及 use_short_preamble 用于 CCK 帧的前导码。

IEEE80211_HW_RX_INCLUDES_FCS

表示传递给堆栈的接收帧在末尾包含 FCS。

IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING

一些无线 LAN 芯片组在硬件/固件中为省电站点缓冲广播/多播帧,而另一些则依赖于主机系统进行此类缓冲。此选项用于配置 IEEE 802.11 上层,以便在存在省电站点时缓冲广播和多播帧,以便驱动程序可以使用 ieee80211_get_buffered_bc() 获取它们。

IEEE80211_HW_SIGNAL_UNSPEC

硬件可以提供信号值,但我们不知道它的单位。我们期望的值介于 0 和 max_signal 之间。如果可能,请提供 dB 或 dBm。

IEEE80211_HW_SIGNAL_DBM

硬件以 dBm 为单位提供信号值,即与 1 毫瓦的分贝差。这是首选方法,因为它在不同设备之间是标准化的。无需设置 max_signal

IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC

此设备需要在关联之前从信标获取数据(即 dtim_period)。

IEEE80211_HW_SPECTRUM_MGMT

硬件支持 802.11h 中定义的频谱管理:测量、信道切换、静默、TPC

IEEE80211_HW_AMPDU_AGGREGATION

硬件支持 11n A-MPDU 聚合。

IEEE80211_HW_SUPPORTS_PS

硬件具有省电支持(即可以进入睡眠状态)。

IEEE80211_HW_PS_NULLFUNC_STACK

硬件需要在堆栈中进行 nullfunc 帧处理,这意味着堆栈支持动态 PS。

IEEE80211_HW_SUPPORTS_DYNAMIC_PS

硬件支持动态 PS。

IEEE80211_HW_MFP_CAPABLE

硬件支持管理帧保护(MFP,IEEE 802.11w)。

IEEE80211_HW_WANT_MONITOR_VIF

当监视器接口是唯一活动的接口时,驱动程序希望收到有关虚拟监视器接口的通知。

IEEE80211_HW_NO_VIRTUAL_MONITOR

驱动程序希望收到有关任何监视器接口及其配置的信道的通知。这对于在不同信道上支持多个监视器接口非常有用。

IEEE80211_HW_NO_AUTO_VIF

驱动程序不希望创建 wlanX。预计用户空间将根据需要创建 vifs(因此可以根据需要命名它们)。

IEEE80211_HW_SW_CRYPTO_CONTROL

驱动程序想要控制哪些加密算法可以在软件中完成 - 因此,如果硬件加密失败,请不要自动尝试回退到软件加密,而是仅在驱动程序返回 1 时才这样做。这还会强制驱动程序公布其支持的密码套件。

IEEE80211_HW_SUPPORT_FAST_XMIT

驱动程序/硬件支持快速传输,这目前只需要计算帧的持续时间的能力。

IEEE80211_HW_REPORTS_TX_ACK_STATUS

硬件可以向堆栈提供 Tx 帧的 ack 状态报告。

IEEE80211_HW_CONNECTION_MONITOR

硬件执行其自己的连接监视,包括定期向 AP 发送保持活动消息,并在信标丢失时探测 AP。

IEEE80211_HW_QUEUE_CONTROL

驱动程序想要控制每个接口的队列映射,以便为不同的虚拟接口使用不同的队列(不仅仅是每个 AC 一个队列)。有关更多详细信息,请参阅有关 HW 队列控制的文档部分。

IEEE80211_HW_SUPPORTS_PER_STA_GTK

设备的加密引擎支持 IBSS RSN 或快速转换期间使用的每个站点的 GTK。如果设备不支持每个站点的 GTK,但可以要求不解密组寻址的帧,那么仍然可以支持 IBSS RSN,但将使用软件加密。仅在这种情况下才公布 wiphy 标志。

IEEE80211_HW_AP_LINK_PS

在 AP 模式下运行时,设备自主管理已连接站点的 PS 状态。设置此标志后,mac80211 将不会根据传入帧的 PM 位触发已连接站点的 PS 模式。使用 ieee80211_start_ps()/ieee8021_end_ps() 手动配置已连接站点的 PS 模式。

IEEE80211_HW_TX_AMPDU_SETUP_IN_HW

设备严格在硬件中处理 TX A-MPDU 会话设置。mac80211 不应尝试在软件中执行此操作。

IEEE80211_HW_SUPPORTS_RC_TABLE

驱动程序支持使用速率控制算法提供的速率选择表。

IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF

对任何 P2P 接口使用 P2P 设备地址。即使支持多个接口,也会遵守此规则。

IEEE80211_HW_TIMING_BEACON_ONLY

仅使用来自信标帧的同步定时,以便获取 DTIM 信标的 TBTT。

IEEE80211_HW_SUPPORTS_HT_CCK_RATES

硬件支持混合 HT/CCK 速率,并且可以处理聚合会话中的 CCK 速率(例如,通过不将聚合用于此类帧)。

IEEE80211_HW_CHANCTX_STA_CSA

在使用信道上下文时,为单个活动信道支持基于 802.11h 的信道切换 (CSA)。如果未启用支持,则默认操作是在获取 CSA 帧时断开连接。

IEEE80211_HW_SUPPORTS_CLONED_SKBS

驱动程序永远不会在不先复制的情况下修改 TX skbs 的有效负载或尾部空间。

IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS

硬件支持在一条命令中扫描所有频段,mac80211 不需要为每个频段单独运行扫描。

IEEE80211_HW_TDLS_WIDER_BW

设备/驱动程序支持 TDLS 链路在基础信道上使用比 BSS 带宽更宽的带宽。

IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU

驱动程序支持接收 A-MPDU 内的 A-MSDU。

IEEE80211_HW_BEACON_TX_STATUS

设备/驱动程序为发送的信标提供 TX 状态。

IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR

硬件(或驱动程序)要求每个站点都有一个唯一的地址,即每个站点条目只能通过其 MAC 地址来识别;例如,这可以防止同一站点同时连接到两个虚拟 AP 接口。

IEEE80211_HW_SUPPORTS_REORDERING_BUFFER

硬件(或驱动程序)在内部管理重新排序缓冲区,保证 mac80211 按顺序接收帧,并且不需要管理自己的重新排序缓冲区或 BA 会话超时。

IEEE80211_HW_USES_RSS

设备使用 RSS,因此需要并行 RX,这意味着使用每个 CPU 的站点统计信息。

IEEE80211_HW_TX_AMSDU

硬件(或驱动程序)支持软件聚合的 A-MSDU 帧。需要软件 tx 队列和 fast-xmit 支持。当不使用 minstrel/minstrel_ht 速率控制时,驱动程序必须根据当前 tx 速率,通过在 struct ieee80211_sta 中设置 max_rc_amsdu_len 来限制最大 A-MSDU 大小。

IEEE80211_HW_TX_FRAG_LIST

硬件(或驱动程序)支持发送 frag_list skb,这是零拷贝软件 A-MSDU 所必需的。

IEEE80211_HW_REPORTS_LOW_ACK

驱动程序(或固件)基于其自己的算法,通过 ieee80211_report_low_ack() 报告低 ack 事件。对于此类驱动程序,mac80211 数据包丢失机制将不会被触发,并且驱动程序完全依赖固件事件来踢出站点。

IEEE80211_HW_SUPPORTS_TX_FRAG

硬件本身执行分片。协议栈将不做分片。还应该设置 set_frag_threshold 的回调。

IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA

硬件支持在 TDLS 链路上缓冲 STA。

IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP

驱动程序(或固件)不支持 AP 探测的 QoS NDP - 这很可能是驱动程序错误。

IEEE80211_HW_BUFF_MMPDU_TXQ

使用 TXQ 来缓冲可缓冲的 MMPDU,这当然要求驱动程序首先使用 TXQ。

IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW

(硬件)速率控制支持 VHT 扩展 NSS 带宽 (dot11VHTExtendedNSSBWCapable)。如果选择的速率控制算法设置了 RATE_CTRL_CAPA_VHT_EXT_NSS_BW,则将设置此标志,但如果速率控制是内置的,则必须由驱动程序设置。另请参阅该标志的文档。

IEEE80211_HW_STA_MMPDU_TXQ

在站点接口上对所有 MMPDU 使用每个站点的额外非 TID TXQ。这当然要求驱动程序首先使用 TXQ。

IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN

驱动程序在 tx 状态信息中不报告准确的 A-MPDU 长度

IEEE80211_HW_SUPPORTS_MULTI_BSSID

硬件支持多 BSSID

IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID

硬件仅对 HE AP 支持多 BSSID。如果设置了 IEEE80211_HW_SUPPORTS_MULTI_BSSID,则适用。

IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT

卡和驱动程序仅聚合具有相同 keyid 的 MPDU,允许 mac80211 在使用扩展密钥 ID 重新密钥时保持 Tx A-MPDU 会话处于活动状态。

IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD

硬件支持 tx 封装卸载

IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD

硬件支持 rx 解封装卸载

IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP

硬件支持并发的 rx 解封装卸载和传递原始 802.11 帧用于 monitor iface。如果支持此功能,则驱动程序必须将实际使用的 802.3 帧和设置了 RX_FLAG_ONLY_MONITOR 的 monitor 的 802.11 帧都传递到协议栈。

IEEE80211_HW_DETECTS_COLOR_COLLISION

HW/驱动程序支持 BSS 颜色冲突检测,并且不需要在软件中进行检测。

IEEE80211_HW_MLO_MCAST_MULTI_LINK_TX

硬件/驱动程序处理在所有链路上发送多播帧,mac80211 不应这样做。

IEEE80211_HW_DISALLOW_PUNCTURING

HW 要求禁用 EHT 中的穿刺,并以较低的带宽连接

IEEE80211_HW_DISALLOW_PUNCTURING_5GHZ

HW 要求禁用 5 GHz 中 EHT 的穿刺,并以较低的带宽连接

IEEE80211_HW_HANDLES_QUIET_CSA

HW/驱动程序处理 CSA 的静默,因此无需停止队列。这实际上应该由实现 MLO 的驱动程序设置,以便当一个链路切换时,操作可以在其他链路上继续。

NUM_IEEE80211_HW_FLAGS

硬件标志的数量,用于调整数组大小

描述

这些标志用于向协议栈指示硬件功能。通常,此处的标志应以最简单的硬件不需要设置任何特定标志的方式来完成其含义。但是,此规则也有一些例外,因此建议您仔细查看这些标志。

struct ieee80211_hw

硬件信息和状态

定义:

struct ieee80211_hw {
    struct ieee80211_conf conf;
    struct wiphy *wiphy;
    const char *rate_control_algorithm;
    void *priv;
    unsigned long flags[BITS_TO_LONGS(NUM_IEEE80211_HW_FLAGS)];
    unsigned int extra_tx_headroom;
    unsigned int extra_beacon_tailroom;
    int vif_data_size;
    int sta_data_size;
    int chanctx_data_size;
    int txq_data_size;
    u16 queues;
    u16 max_listen_interval;
    s8 max_signal;
    u8 max_rates;
    u8 max_report_rates;
    u8 max_rate_tries;
    u16 max_rx_aggregation_subframes;
    u16 max_tx_aggregation_subframes;
    u8 max_tx_fragments;
    u8 offchannel_tx_hw_queue;
    u8 radiotap_mcs_details;
    u16 radiotap_vht_details;
    struct {
        int units_pos;
        s16 accuracy;
    } radiotap_timestamp;
    netdev_features_t netdev_features;
    u8 uapsd_queues;
    u8 uapsd_max_sp_len;
    u8 max_nan_de_entries;
    u8 tx_sk_pacing_shift;
    u8 weight_multiplier;
    u32 max_mtu;
    const s8 *tx_power_levels;
    u8 max_txpwr_levels_idx;
};

成员

conf

struct ieee80211_conf,设备配置,请勿使用。

wiphy

这指向为此 802.11 PHY 分配的 struct wiphy。您必须使用 SET_IEEE80211_DEV()SET_IEEE80211_PERM_ADDR() 填写此结构的 perm_addrdev 成员。此外,此处注册了所有支持的频段(带有信道、比特率)。

rate_control_algorithm

此硬件的速率控制算法。如果未设置 (NULL),则将使用默认算法。必须在调用 ieee80211_register_hw() 之前设置。

priv

指向与此结构一起为驱动程序使用而分配的私有区域的指针。

flags

硬件标志,请参阅 enum ieee80211_hw_flags

extra_tx_headroom

在每个传输 skb 中保留的头部空间,供驱动程序使用(例如,用于传输标头)。

extra_beacon_tailroom

在每个信标 tx skb 中保留的尾部空间。驱动程序可以使用它来添加额外的 IE。

vif_data_size

struct ieee80211_vif 内 drv_priv 数据区域的大小(以字节为单位)。

sta_data_size

struct ieee80211_sta 内 drv_priv 数据区域的大小(以字节为单位)。

chanctx_data_size

struct ieee80211_chanctx_conf 内 drv_priv 数据区域的大小(以字节为单位)。

txq_data_size

struct ieee80211_txq 内 drv_priv 数据区域的大小(以字节为单位)。

queues

可用于数据包的硬件传输队列的数量。WMM/QoS 至少需要四个,这些队列需要具有可配置的访问参数。

max_listen_interval

HW 支持的最大监听间隔,以信标间隔为单位

max_signal

RX 信息中信号(rssi)的最大值,仅当 IEEE80211_HW_SIGNAL_UNSPECIEEE80211_HW_SIGNAL_DB 时使用

max_rates

硬件可以处理的最大备用速率重试阶段数。

max_report_rates

硬件可以报告的最大备用速率重试阶段数。

max_rate_tries

每个阶段的最大尝试次数

max_rx_aggregation_subframes

用于 A-MPDU 块确认接收器聚合的最大缓冲区大小(子帧数)。这仅当设备对子帧数量有限制时才相关,如果它依赖 mac80211 来进行重新排序,则不应设置此值。

max_tx_aggregation_subframes

HT/HE 设备将传输的聚合中的最大子帧数。在 HT AddBA 中,我们将通告常量值 64,因为如果窗口大小较小,一些较旧的 AP 会崩溃(例如带有 FW v1.0.07 build 002 Jun 18 2012 的 LinkSys WRT120N)。对于 AddBA 到支持 HE 的对等方,将使用此值。

max_tx_fragments

每个(A)-MSDU 的最大 tx 缓冲区数,对于 frag_list 中的每个 skb,都是 1 + skb_shinfo(skb)->nr_frags 的总和。

offchannel_tx_hw_queue

用于关闭通道 TX 的 HW 队列 ID(如果设置了 IEEE80211_HW_QUEUE_CONTROL

radiotap_mcs_details

列出 HW 可以报告的 MCS 信息,默认设置为 _MCS、_GI 和 _BW,但不包括 _FMT。使用 IEEE80211_RADIOTAP_MCS_HAVE_* 值,目前仅支持添加 _BW。

radiotap_vht_details

列出 HW 报告的 VHT MCS 信息,默认为 _GI | _BANDWIDTH。使用 IEEE80211_RADIOTAP_VHT_KNOWN_* 值。

radiotap_timestamp

radiotap 时间戳字段的信息;如果 units_pos 成员设置为非负值,则将添加时间戳字段并从 struct ieee80211_rx_status device_timestamp 填充。

radiotap_timestamp.units_pos

必须设置为 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* 和 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_* 值的组合。

radiotap_timestamp.accuracy

如果为非负数,则会在 radiotap 字段中填充精度,并且将设置精度已知标志。

netdev_features

在从此 HW 创建的每个 netdev 中设置的 netdev 功能。请注意,并非所有功能都可与 mac80211 一起使用,其他功能将在 HW 注册期间被拒绝。

uapsd_queues

此位图包含在(重新)关联帧中,以指示每个访问类别是否启用 uAPSD 触发和交付。使用 IEEE80211_WMM_IE_STA_QOSINFO_AC_* 来设置此位图。每个位对应不同的 AC。特定位中的值“1”表示相应的 AC 既启用触发又启用交付。“0”表示均未启用。

uapsd_max_sp_len

WMM AP 在由 WMM STA 触发的任何服务期间可以向 WMM STA 交付的总缓冲帧的最大数量。使用 IEEE80211_WMM_IE_STA_QOSINFO_SP_* 获取正确的值。

max_nan_de_entries

设备支持的最大 NAN DE 函数数。

tx_sk_pacing_shift

当遇到来自 TCP 套接字的帧时,在这些套接字上设置的步调偏移。除非驱动程序有充分的理由需要更多缓冲区,否则通常不应更改默认值。

weight_multiplier

在重新填充每个 TXQ 的不足时使用的驱动程序特定的空闲时间权重乘数。

max_mtu

可以设置最大 mtu。

tx_power_levels

wifi 硬件支持的功率级别列表。功率级别可以指定为整数或分数。idx 0 处的功率级别应为最大正功率级别。

max_txpwr_levels_idx

“tx_power_levels”列表的最大有效 idx。

描述

此结构包含 802.11 PHY 的配置和硬件信息。

void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev)

为 802.11 硬件设置设备

参数

struct ieee80211_hw *hw

要设置设备的 struct ieee80211_hw

struct device *dev

此 802.11 设备的 struct device

void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, const u8 *addr)

为 802.11 硬件设置永久 MAC 地址

参数

struct ieee80211_hw *hw

要设置 MAC 地址的 struct ieee80211_hw

const u8 *addr

要设置的地址

struct ieee80211_ops

从 mac80211 到驱动程序的回调

定义:

struct ieee80211_ops {
    void (*tx)(struct ieee80211_hw *hw,struct ieee80211_tx_control *control, struct sk_buff *skb);
    int (*start)(struct ieee80211_hw *hw);
    void (*stop)(struct ieee80211_hw *hw, bool suspend);
#ifdef CONFIG_PM;
    int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
    int (*resume)(struct ieee80211_hw *hw);
    void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled);
#endif;
    int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*change_interface)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, enum nl80211_iftype new_type, bool p2p);
    void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*config)(struct ieee80211_hw *hw, u32 changed);
    void (*bss_info_changed)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *info, u64 changed);
    void (*vif_cfg_changed)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, u64 changed);
    void (*link_info_changed)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *info, u64 changed);
    int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
    void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
    u64 (*prepare_multicast)(struct ieee80211_hw *hw, struct netdev_hw_addr_list *mc_list);
    void (*configure_filter)(struct ieee80211_hw *hw,unsigned int changed_flags,unsigned int *total_flags, u64 multicast);
    void (*config_iface_filter)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,unsigned int filter_flags, unsigned int changed_flags);
    int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set);
    int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key);
    void (*update_tkip_key)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_key_conf *conf,struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
    void (*set_rekey_data)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data);
    void (*set_default_unicast_key)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int idx);
    int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req);
    void (*cancel_hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*sched_scan_start)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct cfg80211_sched_scan_request *req, struct ieee80211_scan_ies *ies);
    int (*sched_scan_stop)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    void (*sw_scan_start)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, const u8 *mac_addr);
    void (*sw_scan_complete)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*get_stats)(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats);
    void (*get_key_seq)(struct ieee80211_hw *hw,struct ieee80211_key_conf *key, struct ieee80211_key_seq *seq);
    int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
    int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
    int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
#ifdef CONFIG_MAC80211_DEBUGFS;
    void (*vif_add_debugfs)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    void (*link_add_debugfs)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *link_conf, struct dentry *dir);
    void (*sta_add_debugfs)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta, struct dentry *dir);
    void (*link_sta_add_debugfs)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_link_sta *link_sta, struct dentry *dir);
#endif;
    void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta);
    int (*sta_set_txpwr)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,struct ieee80211_sta *sta,enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state);
    void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    void (*link_sta_rc_update)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_link_sta *link_sta, u32 changed);
    void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    void (*sta_statistics)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta, struct station_info *sinfo);
    int (*conf_tx)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,unsigned int link_id, u16 ac, const struct ieee80211_tx_queue_params *params);
    u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf);
    void (*offset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, s64 offset);
    void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*tx_last_beacon)(struct ieee80211_hw *hw);
    int (*ampdu_action)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params);
    int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey);
    void (*rfkill_poll)(struct ieee80211_hw *hw);
    void (*set_coverage_class)(struct ieee80211_hw *hw, s16 coverage_class);
#ifdef CONFIG_NL80211_TESTMODE;
    int (*testmode_cmd)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len);
    int (*testmode_dump)(struct ieee80211_hw *hw, struct sk_buff *skb,struct netlink_callback *cb, void *data, int len);
#endif;
    void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop);
    void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    void (*channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch);
    int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
    int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
    int (*remain_on_channel)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_channel *chan,int duration, enum ieee80211_roc_type type);
    int (*cancel_remain_on_channel)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
    void (*get_ringparam)(struct ieee80211_hw *hw, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
    bool (*tx_frames_pending)(struct ieee80211_hw *hw);
    int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask);
    void (*event_callback)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, const struct ieee80211_event *event);
    void (*allow_buffered_frames)(struct ieee80211_hw *hw,struct ieee80211_sta *sta,u16 tids, int num_frames,enum ieee80211_frame_release_type reason, bool more_data);
    void (*release_buffered_frames)(struct ieee80211_hw *hw,struct ieee80211_sta *sta,u16 tids, int num_frames,enum ieee80211_frame_release_type reason, bool more_data);
    int (*get_et_sset_count)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset);
    void (*get_et_stats)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ethtool_stats *stats, u64 *data);
    void (*get_et_strings)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, u32 sset, u8 *data);
    void (*mgd_prepare_tx)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info);
    void (*mgd_complete_tx)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info);
    void (*mgd_protect_tdls_discover)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, unsigned int link_id);
    int (*add_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx);
    void (*remove_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx);
    void (*change_chanctx)(struct ieee80211_hw *hw,struct ieee80211_chanctx_conf *ctx, u32 changed);
    int (*assign_vif_chanctx)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx);
    void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx);
    int (*switch_vif_chanctx)(struct ieee80211_hw *hw,struct ieee80211_vif_chanctx_switch *vifs,int n_vifs, enum ieee80211_chanctx_switch_mode mode);
    void (*reconfig_complete)(struct ieee80211_hw *hw, enum ieee80211_reconfig_type reconfig_type);
#if IS_ENABLED(CONFIG_IPV6);
    void (*ipv6_addr_change)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct inet6_dev *idev);
#endif;
    void (*channel_switch_beacon)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef);
    int (*pre_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch);
    int (*post_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
    void (*abort_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf);
    void (*channel_switch_rx_beacon)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch);
    int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    u32 (*get_expected_throughput)(struct ieee80211_hw *hw, struct ieee80211_sta *sta);
    int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm);
    int (*tdls_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta, u8 oper_class,struct cfg80211_chan_def *chandef, struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
    void (*tdls_cancel_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta);
    void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_tdls_ch_sw_params *params);
    void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
    void (*sync_rx_queues)(struct ieee80211_hw *hw);
    int (*start_nan)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_nan_conf *conf);
    int (*stop_nan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    int (*nan_change_conf)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_nan_conf *conf, u32 changes);
    int (*add_nan_func)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, const struct cfg80211_nan_func *nan_func);
    void (*del_nan_func)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, u8 instance_id);
    bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw,struct sk_buff *head, struct sk_buff *skb);
    int (*get_ftm_responder_stats)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_ftm_responder_stats *ftm_stats);
    int (*start_pmsr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *request);
    void (*abort_pmsr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *request);
    int (*set_tid_config)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta, struct cfg80211_tid_config *tid_conf);
    int (*reset_tid_config)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta, u8 tids);
    void (*update_vif_offload)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
    void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enabled);
    int (*set_sar_specs)(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar);
    void (*sta_set_decap_offload)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enabled);
    void (*add_twt_setup)(struct ieee80211_hw *hw,struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt);
    void (*twt_teardown_request)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 flowid);
    int (*set_radar_background)(struct ieee80211_hw *hw, struct cfg80211_chan_def *chandef);
    int (*net_fill_forward_path)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta,struct net_device_path_ctx *ctx, struct net_device_path *path);
    bool (*can_activate_links)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, u16 active_links);
    int (*change_vif_links)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,u16 old_links, u16 new_links, struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]);
    int (*change_sta_links)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_sta *sta, u16 old_links, u16 new_links);
    int (*set_hw_timestamp)(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_set_hw_timestamp *hwts);
    int (*net_setup_tc)(struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct net_device *dev,enum tc_setup_type type, void *type_data);
    enum ieee80211_neg_ttlm_res(*can_neg_ttlm)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_neg_ttlm *ttlm);
    void (*prep_add_interface)(struct ieee80211_hw *hw, enum nl80211_iftype type);
};

成员

tx

802.11 模块为每个传输的帧调用的处理程序。skb 包含从 IEEE 802.11 标头开始的缓冲区。底层驱动程序应根据 TX 控制数据中的配置发送帧。此处理程序最好永远不要失败并适当地停止队列。必须是原子的。

start

在附加到硬件的第一个网络设备启用之前调用。这应打开硬件,并且必须打开帧接收(对于可能已启用的监视器接口)。返回负错误代码,这些错误代码可能在用户空间中看到,或者返回零。当设备启动时,它不应具有 MAC 地址,以避免在添加非监视器设备之前确认帧。必须实现并且可以休眠。

stop

在附加到硬件的最后一个网络设备禁用后调用。这应关闭硬件(至少必须关闭帧接收)。如果该接口拒绝接口,则可以在 add_interface 之后立即调用。如果在 mac80211 工作队列上添加了任何工作,则应确保在此回调中取消它。必须实现并且可以休眠。

suspend

挂起设备;mac80211 本身将在之前静止并停止传输和执行任何其他配置,然后要求设备挂起。仅当配置了 WoWLAN 时才会调用此操作,否则设备将被完全取消配置并在恢复时重新配置。如果驱动程序仅在设备关联时才支持 WoWLAN,则它还可以施加特殊条件,在这些条件下,它希望使用“正常”挂起(取消配置)。在这种情况下,它必须从此函数返回 1。

resume

如果配置了 WoWLAN,则表示 mac80211 现在正在恢复其操作,之后设备必须再次完全正常运行。如果返回错误,则唯一的解决方法是也取消注册设备。如果返回 1,则 mac80211 也将在恢复时进行常规的完整重新启动。

set_wakeup

当修改 WoWLAN 配置时启用或禁用唤醒。原因是 device_set_wakeup_enable() 应该在配置更改时调用,而不仅仅是在 suspend() 中调用。

add_interface

当附加到硬件的网络设备启用时调用。因为它不为监视器模式设备调用,所以必须实现 **start** 和 **stop**。驱动程序应执行设备启用之前所需的任何初始化。接口的初始配置在 conf 参数中给出。回调可以通过返回负错误代码来拒绝添加接口(这将在用户空间中看到)。必须实现并且可以休眠。

change_interface

当网络设备更改类型时调用。此回调是可选的,但仅当支持此回调时,才可以在接口处于 UP 状态时切换接口类型。回调可以休眠。请注意,在切换接口时,接口迭代回调将找不到该接口。

remove_interface

通知驱动程序接口正在关闭。如果它是最后一个接口并且不存在监视器接口,则在此之后调用 **stop** 回调。删除所有接口后,必须清除硬件中的 MAC 地址,以便设备不再确认数据包,conf 结构的 mac_addr 成员设置为正在消失的设备的 MAC 地址。因此,必须实现此回调。它可以休眠。

config

配置请求的处理程序。IEEE 802.11 代码调用此函数来更改硬件配置,例如,通道。此函数不应失败,但如果失败,则返回负错误代码。回调可以休眠。

bss_info_changed

用于处理与 BSS 参数相关的配置请求的处理程序,这些参数可能在 BSS 的生命周期中变化,并且可能会影响低级驱动程序(例如,关联/取消关联状态、erp 参数)。如果未设置 BSS,则不应使用此函数,除非用于关联指示。当进行调用时,**changed** 参数指示哪个 bss 参数已更改。回调可以休眠。

vif_cfg_changed

用于处理与接口 (MLD) 参数相关的配置请求的处理程序,这些参数来自 struct ieee80211_vif_cfg,并且在接口的生命周期内变化(例如,关联状态、IP 地址等)。**changed** 参数指示哪个值已更改。回调可以休眠。

link_info_changed

用于处理与来自 struct ieee80211_bss_conf 的链路参数相关的配置请求的处理程序,这些参数与单个链路相关。例如,传统/HT/VHT/...速率信息。**changed** 参数指示哪个值已更改,**link_id** 参数指示链路 ID。请注意,对于非 MLO 连接,**link_id** 将为 0。回调可以休眠。

start_ap

在 AP 接口上启动操作,这是在设置 bss_conf 中的所有信息并可以检索信标后调用的。在此调用之前绑定通道上下文。请注意,如果驱动程序使用软件扫描或 ROC,则当 AP 仅因扫描/ROC 而“暂停”时,不会调用此操作(和 **stop_ap**),这通过通过 **bss_info_changed** 禁用/启用信标来指示。

stop_ap

停止 AP 接口上的操作。

prepare_multicast

准备多播筛选器配置。此回调是可选的,其返回值将传递给 configure_filter()。此回调必须是原子的。

configure_filter

配置设备的 RX 筛选器。有关更多信息,请参见“帧筛选”部分。必须实现此回调并且可以休眠。

config_iface_filter

配置接口的 RX 筛选器。此回调是可选的,用于配置应将哪些帧传递给 mac80211。filter_flags 是 FIF_* 标志的组合。changed_flags 是一个位掩码,指示哪些标志已更改。此回调可以休眠。

set_tim

设置 TIM 位。当必须为给定的 STA 设置或清除 TIM 位时,mac80211 会调用此函数。必须是原子的。

set_key

请参阅“硬件加密加速”部分。此回调仅在 add_interface 和 remove_interface 调用之间调用,即在给定的虚拟接口启用时调用。如果无法添加密钥,则返回负错误代码。回调可以休眠。

update_tkip_key

请参阅“硬件加密加速”部分。将在 Rx 的上下文中调用此回调。为设置 IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY 的驱动程序调用。回调必须是原子的。

set_rekey_data

如果设备支持 GTK 重新密钥,例如在主机挂起时,它可以分配此回调以检索执行 GTK 重新密钥所需的数据,即 KEK、KCK 和重放计数器。完成重新密钥后,它应(例如在恢复期间)使用 ieee80211_gtk_rekey_notify() 通知用户空间新的重放计数器。

set_default_unicast_key

设置默认(单播)密钥索引,当设备自主发送数据包时(例如,对于 ARP 卸载),对于 WEP 非常有用。索引可以是 0-3,或者 -1 表示取消设置。

hw_scan

要求硬件为扫描请求提供服务,无需在堆栈中启动扫描状态机。扫描必须遵循监管代理在 wiphy 的注册频段中完成的通道配置。硬件(或驱动程序)需要确保禁用节能。mac80211 会重写 **req** ie/ie_len 成员以包含 SSID 之后的整个 IE,以便驱动程序无需查看这些,只需在 SSID 之后发送它们即可 -- mac80211 包括(扩展的)支持速率和 HT 信息(如果适用)。当扫描完成时,必须调用 ieee80211_scan_completed();请注意,当由于任何错误而无法完成扫描时,也必须调用它,除非此回调返回负错误代码。此回调也允许返回特殊返回值 1,这表示现在不希望进行硬件扫描,而应改为进行软件扫描。希望使用此功能的驱动程序必须确保其(硬件)扫描功能未宣传为比 mac80211 的软件扫描功能更强大。回调可以休眠。

cancel_hw_scan

要求底层 tp 取消活动硬件扫描。驱动程序应要求硬件取消扫描(如果可能),但仅在驱动程序调用 ieee80211_scan_completed() 后,扫描才会完成。此回调是为 wowlan 所需,以防止在底层驱动程序已挂起后入队新的 scan_work。回调可以休眠。

sched_scan_start

要求硬件以特定间隔开始重复扫描。驱动程序必须在找到结果时调用 ieee80211_sched_scan_results() 函数。此过程将继续进行,直到调用 sched_scan_stop。

sched_scan_stop

告知硬件停止正在进行的计划扫描。在这种情况下,不得调用 ieee80211_sched_scan_stopped()。

sw_scan_start

扫描开始前调用的通知函数。如果驱动程序不需要此通知,则可以为 NULL。mac_addr 参数允许支持 NL80211_SCAN_FLAG_RANDOM_ADDR,如果驱动程序可以使用此参数,则可以设置 NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR 标志。该回调可以休眠。

sw_scan_complete

软件扫描完成后调用的通知函数。如果驱动程序不需要此通知,则可以为 NULL。该回调可以休眠。

get_stats

返回底层统计信息。如果统计信息可用,则返回零。该回调可以休眠。

get_key_seq

如果您的设备在硬件中实现加密并执行 IV/PN 分配,则应提供此回调,以便从硬件读取给定密钥的 IV/PN。该回调必须是原子的。

set_frag_threshold

配置分片阈值。如果设备自行进行分片,则分配此值。请注意,为了防止堆栈进行分片,还应设置 IEEE80211_HW_SUPPORTS_TX_FRAG。该回调可以休眠。

set_rts_threshold

配置 RTS 阈值(如果设备需要)。该回调可以休眠。

sta_add

通知底层驱动程序有关添加关联站点、AP、IBSS/WDS/mesh 对等节点等的信息。此回调可以休眠。

sta_remove

通知底层驱动程序有关删除关联站点、AP、IBSS/WDS/mesh 对等节点等的信息。请注意,在回调返回后,使用指针是不安全的,即使是 RCU 保护的指针也不安全;不保证在返回此处和释放站点之间有 RCU 宽限期。如果需要,请参阅 sta_pre_rcu_remove。此回调可以休眠。

vif_add_debugfs

驱动程序可以使用此回调添加包含其文件的 debugfs vif 目录。此回调应在 CONFIG_MAC80211_DEBUGFS 条件内。此回调可以休眠。

link_add_debugfs

当将链路添加到 mac80211 vif 时,驱动程序可以使用此回调添加 debugfs 文件。此回调应在 CONFIG_MAC80211_DEBUGFS 条件内。此回调可以休眠。对于非 MLO,该回调将为默认 bss_conf 调用一次,使用 vif 的目录而不是单独的子目录。

sta_add_debugfs

当将站点添加到 mac80211 的站点列表时,驱动程序可以使用此回调添加 debugfs 文件。此回调应在 CONFIG_MAC80211_DEBUGFS 条件内。此回调可以休眠。

link_sta_add_debugfs

当将链路添加到 mac80211 站点时,驱动程序可以使用此回调添加 debugfs 文件。此回调应在 CONFIG_MAC80211_DEBUGFS 条件内。此回调可以休眠。对于非 MLO,该回调将为 deflink 调用一次,使用站点的目录而不是单独的子目录。

sta_notify

通知底层驱动程序有关关联站点、AP、IBSS/WDS/mesh 对等节点等的电源状态转换。对于在 AP 模式下运行的 VIF,设置 IEEE80211_HW_AP_LINK_PS 标志时,不会调用此回调。必须是原子的。

sta_set_txpwr

配置站点发射功率。此回调设置站点的发射功率。此回调可以休眠。

sta_state

通知底层驱动程序有关站点(可以是 AP、客户端、IBSS/WDS/mesh 对等节点等)的状态转换。此回调与 sta_add/sta_remove 互斥。对于向下转换,它不能失败,但对于向上转换,可能会失败。另请注意,在回调返回后,使用指针是不安全的,即使是 RCU 保护的指针也不安全 - 不保证在返回此处和释放站点之间有 RCU 宽限期。如果需要,请参阅 sta_pre_rcu_remove。该回调可以休眠。

sta_pre_rcu_remove

在 RCU 同步之前通知驱动程序有关站点移除的信息。如果驱动程序需要使用 RCU 保护站点指针,则此操作很有用,然后可以使用此调用来清除指针,而无需等待 sta_state 中的 RCU 宽限期结束。该回调可以休眠。

link_sta_rc_update

通知驱动程序可以用来向站点发送数据的比特率的变化。这些变化通过 enum ieee80211_rate_control_changed 中的位进行通告,并且这些值反映在站点数据中。仅当驱动程序使用硬件速率控制 (IEEE80211_HW_HAS_RATE_CONTROL) 时才应使用此回调,否则会直接通知速率控制算法。必须是原子的。

sta_rate_tbl_update

通知驱动程序速率表已更改。这仅在配置的速率控制算法实际使用新的速率表 API 时使用,因此是可选的。必须是原子的。

sta_statistics

获取此站点的统计信息。例如,使用信标过滤时,mac80211 保留的统计信息可能不准确,因此让驱动程序预先填充统计信息。驱动程序可以填充大多数值(通过设置填充位图指示填充哪些值),但并非所有值都有意义 - 有关哪些值是可能的,请参阅源代码。驱动程序未填充的统计信息将由 mac80211 填充。该回调可以休眠。

conf_tx

配置硬件 TX 队列的 TX 队列参数(EDCF (aifs、cw_min、cw_max)、突发)。如果失败,则返回负错误代码。该回调可以休眠。

get_tsf

从固件/硬件获取当前 TSF 计时器值。目前,这仅用于 IBSS 模式 BSSID 合并和调试。不是必需的函数。该回调可以休眠。

set_tsf

将 TSF 计时器设置为固件/硬件中指定的值。目前,这仅用于 IBSS 模式调试。不是必需的函数。该回调可以休眠。

offset_tsf

在固件/硬件中将 TSF 计时器偏移指定的值。首选 set_tsf,因为它避免了调用 set_tsf() 和硬件被编程之间的时间延迟,这将显示为 TSF 延迟。不是必需的函数。该回调可以休眠。

reset_tsf

重置 TSF 计时器并允许固件/硬件与 IBSS 中的其他 STA 同步。这仅在 IBSS 模式下使用。如果固件/硬件完全负责 TSF 同步,则此函数是可选的。该回调可以休眠。

tx_last_beacon

确定最后一个 IBSS 信标是否由我们发送。这仅在 IBSS 模式下需要,此函数的结果用于确定是否回复探测请求。如果此设备发送了最后一个信标,则返回非零值。该回调可以休眠。

ampdu_action

执行特定的 A-MPDU 操作。RA/TID 组合确定我们要为其执行 ampdu 操作的目标和 TID。该操作通过 ieee80211_ampdu_mlme_action 定义。当操作设置为 IEEE80211_AMPDU_TX_OPERATIONAL 时,驱动程序既不能发送包含比 buf_size 更多子帧的聚合,也不能以丢失帧会超出缓冲区大小的方式发送聚合。如果只是限制聚合大小,则可以使用 buf_size 为 8 的值来实现

  • TX: 1.....7

  • RX:  2....7 (丢失帧 #1)

  • TX:        8..1...

这是无效的,因为 #1 现在已在超出 8 的缓冲区大小的情况下重新传输。重新传输 #1 的正确方法是

  • TX:        1   or

  • TX:        18  or

  • TX:        81

即使 189 也是错误的,因为 1 可能会再次丢失。

如果失败,则返回负错误代码。如果会话可以立即开始,则驱动程序可以为 IEEE80211_AMPDU_TX_START 返回 IEEE80211_AMPDU_TX_START_IMMEDIATE

该回调可以休眠。

get_survey

返回每个信道的调查信息

rfkill_poll

轮询 rfkill 硬件状态。如果您需要此功能,还需要在注册之前将 wiphy->rfkill_poll 设置为 true,并且需要在回调中调用 wiphy_rfkill_set_hw_state()。该回调可以休眠。

set_coverage_class

按照 IEEE 802.11-2007 第 17.3.8.6 节中的规定,设置给定覆盖范围等级的 slot time 并相应地修改 ACK 超时;覆盖范围等级等于 -1,表示启用 ACK 超时估计算法 (dynack)。要禁用 dynack,请设置有效的覆盖范围等级值。此回调不是必需的,并且可能会休眠。

testmode_cmd

实现 cfg80211 测试模式命令。传递的 vif 可能为 NULL。该回调可以休眠。

testmode_dump

实现 cfg80211 测试模式转储。该回调可以休眠。

flush

从硬件队列刷新所有挂起的帧,确保硬件队列为空。queues 参数是要刷新的队列的位图,如果不同的虚拟接口使用不同的硬件队列,则此参数很有用;它也可能指示所有队列。如果参数 drop 设置为 true,则可能会丢弃挂起的帧。请注意,vif 可以为 NULL。该回调可以休眠。

flush_sta

刷新或丢弃给定站点的硬件队列中所有挂起的帧,因为它即将被删除。该回调可以休眠。

channel_switch

对于从 AP 收到的 CSA,需要(或想要)卸载信道切换操作的驱动程序可以实现此回调。然后,他们必须调用 ieee80211_chswitch_done() 来指示信道切换完成。

set_antenna

在设备上设置天线配置(tx_ant、rx_ant)。参数是用于 TX/RX 的允许天线的位图。驱动程序可能会拒绝它们不支持的 TX/RX 掩码组合,方法是返回 -EINVAL(另请参阅 nl80211.h NL80211_ATTR_WIPHY_ANTENNA_TX)。

get_antenna

从设备获取当前天线配置(tx_ant、rx_ant)。

remain_on_channel

在给定信道上启动一个非信道期,当在该信道上时必须回调 ieee80211_ready_on_channel()。请注意,正常的信道流量不会停止,因为这是为硬件卸载设计的。在非信道信道上发送的帧会正常发送,但带有 IEEE80211_TX_CTL_TX_OFFCHAN 标志除外。当持续时间(始终为非零)到期时,驱动程序必须调用 ieee80211_remain_on_channel_expired()。请注意,此回调可能会在设备处于 IDLE 状态时调用,并且在这种情况下必须接受。此回调可能会休眠。

cancel_remain_on_channel

请求在正在进行的非信道期到期之前中止。此回调可能会休眠。

set_ringparam

设置 tx 和 rx 环形缓冲区大小。

get_ringparam

获取 tx 和 rx 环形缓冲区的当前和最大大小。

tx_frames_pending

检查在进入省电模式之前硬件队列中是否有任何挂起的帧。

set_bitrate_mask

设置一个速率掩码,用于在发送帧时进行速率控制选择。目前仅处理旧版速率。此回调可以休眠。

event_callback

通知驱动程序有关 mac80211 中的任何事件。有关不同类型,请参阅 enum ieee80211_event_type。此回调必须是原子的。

allow_buffered_frames

准备设备以允许给定数量的帧发送到给定站点。在此调用之后,帧将通过正常的 TX 路径由 mac80211 发送。已释放帧的 TX 信息还将设置 IEEE80211_TX_CTL_NO_PS_BUFFER 标志,最后一个帧还将设置 IEEE80211_TX_STATUS_EOSP。如果从多个 TID 释放帧,并且驱动程序可能会在 TID 之间重新排序它们,则必须在最后一个帧上设置 IEEE80211_TX_STATUS_EOSP 标志,并清除所有其他帧上的该标志,并且还必须正确处理 QoS 标头中的 EOSP 位。或者,它也可以调用 ieee80211_sta_eosp() 函数。tids 参数是一个位图,告诉驱动程序帧将在哪个 TID 上;它最多设置两个位。此回调必须是原子的。

release_buffered_frames

根据给定的参数释放缓冲的帧。如果驱动程序为休眠站点缓冲了一些帧,则 mac80211 将使用此回调来告知驱动程序释放一些帧,以用于 PS-poll 或 uAPSD。请注意,如果 more_data 参数为 false,则驱动程序必须检查给定 TID 上是否有更多帧,如果帧的数量多于正在释放的帧,则仍必须在帧中设置更多数据位。如果 more_data 参数为 true,则当然必须始终设置更多数据位。tids 参数告诉驱动程序要从哪个 TID 释放帧,对于 PS-poll,它将始终仅设置一位。如果用于 PS-poll 发起的释放,则 num_frames 参数将始终为 1,因此可以共享代码。在这种情况下,驱动程序还必须在 TX 状态上设置 IEEE80211_TX_STATUS_EOSP 标志(并且必须报告 TX 状态),以便正确结束 PS-poll 周期。这用于避免为重试的 PS-poll 帧发送多个响应。如果用于 uAPSD,则 num_frames 参数可能大于 1,但驱动程序可以发送较少的帧(但必须至少发送一个)。在这种情况下,它还负责在帧的 QoS 标头中设置 EOSP 标志。此外,当服务周期结束时,驱动程序必须在 SP 中的最后一个帧上设置 IEEE80211_TX_STATUS_EOSP。或者,它可以调用函数 ieee80211_sta_eosp() 以通知 mac80211 SP 的结束。此回调必须是原子的。

get_et_sset_count

Ethtool API 用于获取字符串集计数。请注意,此回调不持有 wiphy 互斥锁,因为它应该返回静态值。

get_et_stats

Ethtool API 用于获取一组 u64 统计信息。

get_et_strings

Ethtool API 用于获取一组字符串来描述统计信息,以及其他可能支持的 ethtool 数据集类型。请注意,此回调不持有 wiphy 互斥锁,因为它应该返回静态值。

mgd_prepare_tx

准备发送关联前的管理帧。在多信道场景中,虚拟接口在关联之前绑定到信道,但由于尚未关联,因此不一定需要提供空闲时间,特别是由于任何到 P2P GO 的传输都需要与 GO 的省电状态同步。mac80211 将在发送管理帧之前调用此函数,以允许驱动程序为传输提供信道时间,获取响应并能够与 GO 同步。该回调将在每次传输之前调用,并且在返回时,mac80211 将立即发送帧。附加信息在 struct ieee80211_prep_tx_info 数据中传递。如果此处的持续时间大于零,则 mac80211 会向驱动程序提示请求操作的持续时间。此回调是可选的,并且可以(应该!)休眠。

mgd_complete_tx

通知驱动程序,先前使用 mgd_prepare_tx 通告的已发送帧的响应帧已收到,数据填充方式与 mgd_prepare_tx 类似,但未使用持续时间。

mgd_protect_tdls_discover

保护 TDLS 发现会话。在发送 TDLS 发现请求后,我们希望在 AP 的信道上收到回复。我们必须保持在信道上(无 PSM、扫描等),因为 TDLS 设置响应是 AP 未缓冲的直接数据包。mac80211 将在传输 TDLS 发现请求之前调用此函数。建议的保护周期至少为 2 *(DTIM 周期)。此回调是可选的,可以休眠。

add_chanctx

通知设备驱动程序有关新信道上下文创建的信息。此回调可能会休眠。

remove_chanctx

通知设备驱动程序有关信道上下文销毁的信息。此回调可能会休眠。

change_chanctx

通知设备驱动程序有关在同一信道上下文上组合具有不同设置的不同虚拟接口时可能发生的信道上下文更改。此回调可能会休眠。

assign_vif_chanctx

通知设备驱动程序有关信道上下文绑定到 vif 的信息。可能的用途是用于硬件队列重映射。此回调可能会休眠。

unassign_vif_chanctx

通知设备驱动程序有关从 vif 解除绑定的信道上下文的信息。此回调可能会休眠。

switch_vif_chanctx

根据 ieee80211_chanctx_switch_mode 中定义的模式,将传递给驱动程序的 ieee80211_vif_chanctx_switch 列表中指定的一些 vif 从一个 chanctx 切换到另一个 chanctx。此回调可能会休眠。

reconfig_complete

在调用 ieee80211_restart_hw() 之后以及恢复期间,当重新配置完成时调用。这可以帮助驱动程序实现重新配置步骤(并指示 mac80211 已准备好接收帧)。此回调可能会休眠。

ipv6_addr_change

给定接口上的 IPv6 地址分配已更改。目前,这仅针对托管或 P2P 客户端接口调用。此回调是可选的;它不得休眠。

channel_switch_beacon

启动到新信道的信道切换。在调用此函数之前,会修改信标以包含 CSA 或 ECSA IE。这些 IE 中的相应计数字段必须递减,当它们达到 1 时,驱动程序必须调用 ieee80211_csa_finish()。使用 ieee80211_beacon_get() 的驱动程序会使 mac80211 递减 csa 计数器,但必须在使用 ieee80211_beacon_counter_is_complete() 发送信标后检查其是否为 1,然后调用 ieee80211_csa_finish()。如果 CSA 计数开始为零或 1,则不会调用此函数,因为无论如何,在切换之前没有任何时间发送信标。

pre_channel_switch

这是一个可选的回调,在启动信道切换过程之前调用(即,当 STA 获得 CSA 或用户空间发起的信道切换时),允许驱动程序为信道切换做准备。

post_channel_switch

这是一个可选的回调,在信道切换过程完成后调用,允许驱动程序返回正常配置。

abort_channel_switch

这是一个可选的回调,在信道切换过程中止时调用,允许驱动程序返回正常配置。

channel_switch_rx_beacon

这是一个可选的回调,在信道切换过程正在进行且收到带有 CSA IE 的其他信标时调用,允许驱动程序跟踪计数中的更改。

join_ibss

加入 IBSS(在 IBSS 接口上);这在设置完 bss_conf 中的所有信息并且可以检索信标后调用。在调用此函数之前,会绑定信道上下文。

leave_ibss

再次离开 IBSS。

get_expected_throughput

提取到指定站点的预期吞吐量。返回的值以 Kbps 表示。如果 RC 算法没有提供适当的数据,则返回 0。

get_txpower

根据配置和硬件限制,获取当前最大发射功率(以 dBm 为单位)。

tdls_channel_switch

使用 TDLS 对等方开始信道切换。驱动程序负责不断启动信道切换操作并返回基本信道以与 AP 通信。驱动程序会收到信道切换请求模板以及模板中切换时序 IE 的位置作为调用的组成部分。该模板仅在调用中有效,驱动程序可以选择复制 skb 以便进一步重用。

tdls_cancel_channel_switch

停止与 TDLS 对等方进行信道切换。调用完成时,两个对等方都必须位于基本信道上。

tdls_recv_channel_switch

已从远程对等方收到与 TDLS 通道切换相关的帧(请求或响应)。驱动程序会解析传入帧中的参数,并可以使用这些参数来继续正在进行的通道切换操作。此外,还提供了通道切换响应模板,以及模板中切换定时 IE 的位置。skb 只能在函数调用中使用。

wake_tx_queue

当新数据包已添加到队列时调用。

sync_rx_queues

处理 RSS 队列中的所有待处理帧。这是一种同步操作,当驱动程序的 RSS 队列中有在当前采取的控制路径操作(例如,取消关联)之前接收但尚未处理的待处理帧时,需要进行同步。

start_nan

加入现有的 NAN 集群,或创建一个新的集群。

stop_nan

离开 NAN 集群。

nan_change_conf

更改 NAN 配置。cfg80211_nan_conf 中的数据包含完整的新的配置,并且更改指定了相对于上次 NAN 配置更改的参数。驱动程序会获取完整的配置和已更改的参数,因为某些设备可能需要完整的配置,而其他设备可能只需要已更改的参数。

add_nan_func

添加一个 NAN 函数。成功时返回 0。cfg80211_nan_func 中的数据不得在此调用的范围之外引用。

del_nan_func

删除一个 NAN 函数。驱动程序必须在删除时使用 NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST 原因代码调用 ieee80211_nan_func_terminated()。

can_aggregate_in_amsdu

调用以确定硬件是否支持在同一个 A-MSDU 中聚合两个特定的帧。skb 之间的关系应该是对称的和可传递的。请注意,虽然 skb 始终是一个真实的帧,但 head 可能是一个 A-MSDU,也可能不是。

get_ftm_responder_stats

检索 FTM 响应器统计信息(如果可用)。统计信息应该是累积的,目前没有提供重置方法。

start_pmsr

启动对等测量(例如 FTM)(此调用可以休眠)

abort_pmsr

中止对等测量(此调用可以休眠)

set_tid_config

应用特定于 TID 的配置。此回调可能会休眠。

reset_tid_config

重置对等体的特定于 TID 的配置。此回调可能会休眠。

update_vif_offload

更新虚拟接口卸载标志。此回调可能会休眠。

sta_set_4addr

当站点开始/停止使用 4 地址模式时,调用以通知驱动程序

set_sar_specs

更新 SAR(TX 功率)设置。

sta_set_decap_offload

当允许站点使用 rx 解封装卸载时,调用以通知驱动程序

add_twt_setup

使用从对等体接收的 TWT 协商参数更新硬件。此回调允许硬件检查是否支持请求的参数以及是否有足够空间进行新的协商。硬件应在 twt 结构的 req_type 字段中设置协商结果。

twt_teardown_request

使用从对等体接收的 TWT 拆除请求更新硬件。

set_radar_background

在某些硬件上配置专用的 offchannel 链,用于雷达/CAC 检测。此链不能用于发送或接收帧,并且绑定到正在运行的 wdev。后台雷达/CAC 检测允许避免在所选雷达通道上进行 CAC 检测时切换到不同通道而造成的 CAC 停机时间。调用者应将 chandef 指针设置为 NULL 以禁用后台 CAC/雷达检测。

net_fill_forward_path

从 .ndo_fill_forward_path 调用,以解析硬件流卸载的路径

can_activate_links

检查驱动程序是否支持特定的 active_links 位图。

change_vif_links

更改接口上的有效链接,请注意,在删除时旧的链接信息仍然有效(link_conf 指针),但可能会在函数返回后立即消失。如果从/到非 MLO 情况,旧的或新的链接位图可能为 0。**old** 数组包含指向已删除的旧 bss_conf 结构的指针,以防需要它们。此回调可以休眠。

change_sta_links

更改站点的有效链接,类似于 **change_vif_links**。此回调可以休眠。请注意,也可以插入或删除具有有效链接的 sta,即使用 sta->valid_links 不为零传递给 **sta_add**/**sta_state**。事实上,不能从具有 valid_links 变为没有 valid_links 的状态。

set_hw_timestamp

启用/禁用 TM/FTM 帧的硬件时间戳。mac80211 不会在硬件重置时恢复此设置,因此驱动程序需要处理此问题。

net_setup_tc

从 .ndo_setup_tc 调用,以便为源自 vif 的流准备硬件流卸载。请注意,驱动程序此时不得假设 vif driver_data 有效,因为该回调可以在 netdev 拆卸期间调用。

can_neg_ttlm

对于托管接口,请求驱动程序确定是否可以接受请求的 TID 到链接的映射。如果未接受,驱动程序可能会建议首选的映射,并使用建议的 TID 到链接的映射修改 **ttlm** 参数。

prep_add_interface

为添加接口做准备。驱动程序可以使用此方法来准备添加新接口,例如,分配所需的资源等。此回调不保证将添加具有指定类型的接口,因此实现此回调的驱动程序需要处理这种情况。该类型是完整的 enum nl80211_iftype

描述

此结构包含驱动程序可以处理或在某些情况下必须处理的各种回调,例如,将硬件配置为新通道或发送帧。

注意

如果未实现 **vif_cfg_changed** 或 **link_info_changed**,则会调用此回调。

are not implemented.

struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops)

分配新的硬件设备

参数

size_t priv_data_len

私有数据的长度

const struct ieee80211_ops *ops

此设备的回调

描述

对于每个硬件设备,必须调用此函数一次。调用其他函数时,必须使用返回的指针来引用此设备。mac80211 为驱动程序分配一个私有数据区域,该区域由 struct ieee80211_hw 中的 **priv** 指向,此区域的大小由 **priv_data_len** 给定。

返回

指向新硬件设备的指针,如果出错,则返回 NULL

int ieee80211_register_hw(struct ieee80211_hw *hw)

注册硬件设备

参数

struct ieee80211_hw *hw

要注册的设备,由 ieee80211_alloc_hw() 返回

描述

在 mac80211 中调用任何其他函数之前,必须调用此函数。请注意,在注册硬件之前,您需要填写所包含的 wiphy 的信息。

返回

成功时返回 0。否则返回错误代码。

void ieee80211_unregister_hw(struct ieee80211_hw *hw)

注销硬件设备

参数

struct ieee80211_hw *hw

要注销的硬件

描述

此函数指示 mac80211 释放已分配的资源并从网络子系统中注销 netdevice。

void ieee80211_free_hw(struct ieee80211_hw *hw)

释放硬件描述符

参数

struct ieee80211_hw *hw

要释放的硬件

描述

此函数释放已分配的所有内容,包括驱动程序的私有数据。在调用此函数之前,必须调用 ieee80211_unregister_hw()

PHY 配置

待定

本章应描述 PHY 处理,包括启动/停止回调和使用的各种结构。

enum ieee80211_conf_flags

配置标志

常量

IEEE80211_CONF_MONITOR

存在监视器接口 -- 使用此标志来确定是否计算数据包的时间戳等,不要使用它来代替筛选标志!

IEEE80211_CONF_PS

启用 802.11 省电模式(仅限托管模式)。这是 IEEE 802.11-2007 第 11.2 节定义的省电模式,这意味着硬件仍然会唤醒以接收信标,能够发送帧并接收可能的确认帧。不要与硬件特定的唤醒/睡眠状态混淆,驱动程序负责处理这些状态。有关更多信息,请参见“省电支持”部分。

IEEE80211_CONF_IDLE

设备正在运行,但处于空闲状态;如果设置了该标志,则驱动程序应准备好处理配置请求,但可以将设备尽可能地关闭。通常,当接口设置为 UP 但未关联或扫描时,将设置此标志,但在监视器接口处于活动状态时,也可以取消设置此标志。

IEEE80211_CONF_OFFCHANNEL

设备当前不在其主要操作通道上。

描述

用于定义 PHY 配置选项的标志

struct ieee80211_conf

设备配置

定义:

struct ieee80211_conf {
    u32 flags;
    int power_level, dynamic_ps_timeout;
    u16 listen_interval;
    u8 ps_dtim_period;
    u8 long_frame_max_tx_count, short_frame_max_tx_count;
    struct cfg80211_chan_def chandef;
    bool radar_enabled;
    enum ieee80211_smps_mode smps_mode;
};

成员

flags

上面定义的配置标志

power_level

请求的发送功率(以 dBm 为单位),仅限向后兼容值,设置为所有接口的最小值

dynamic_ps_timeout

动态省电超时(以毫秒为单位),请参见下面的省电文档。此变量仅在设置了 CONF_PS 标志时有效。

listen_interval

以信标间隔为单位的侦听间隔

ps_dtim_period

我们连接的 AP 的 DTIM 周期,用于省电。在收到信标并且已知 DTIM 周期之前,不会启用省电功能。

long_frame_max_tx_count

“长”帧(非 RTS 保护的帧)的最大传输次数,在 802.11 中称为 “dot11LongRetryLimit”,但实际上是指传输次数而非重试次数

short_frame_max_tx_count

“短”帧的最大传输次数,在 802.11 中称为 “dot11ShortRetryLimit”,但实际上是指传输次数而非重试次数

chandef

要调谐到的信道定义

radar_enabled

是否启用雷达检测

smps_mode

空间复用省电模式;请注意,当设备未配置为 HT 信道时,会使用 IEEE80211_SMPS_STATIC。请注意,这仅在不使用信道上下文时有效,否则每个信道上下文都会列出链的数量。

描述

此结构指示驱动程序应如何配置硬件。

虚拟接口

待定

本章应描述与驱动程序相关的虚拟接口基础知识(VLAN、MGMT 等不包括在内)。它应解释 add_iface/remove_iface 回调以及接口配置回调的用法。

与 AP 模式相关的内容应在此处讨论。

与支持多个接口相关的内容应在相应的章节中讨论,但此处应有一个大大的提示,并建议首先只允许在 STA 模式下使用单个接口!

struct ieee80211_vif

每个接口的数据

定义:

struct ieee80211_vif {
    enum nl80211_iftype type;
    struct ieee80211_vif_cfg cfg;
    struct ieee80211_bss_conf bss_conf;
    struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
    u16 valid_links, active_links, dormant_links, suspended_links;
    struct ieee80211_neg_ttlm neg_ttlm;
    u8 addr[ETH_ALEN] ;
    bool addr_valid;
    bool p2p;
    u8 cab_queue;
    u8 hw_queue[IEEE80211_NUM_ACS];
    struct ieee80211_txq *txq;
    netdev_features_t netdev_features;
    u32 driver_flags;
    u32 offload_flags;
#ifdef CONFIG_MAC80211_DEBUGFS;
    struct dentry *debugfs_dir;
#endif;
    bool probe_req_reg;
    bool rx_mcast_action_reg;
    struct ieee80211_vif *mbssid_tx_vif;
    u8 drv_priv[] ;
};

成员

type

此虚拟接口的类型

cfg

vif 配置,请参阅 struct ieee80211_vif_cfg

bss_conf

此接口的 BSS 配置,我们自己的配置或我们关联到的 BSS

link_conf

如果是 MLD,则为每个链路的 BSS 配置,按链路 ID 索引

valid_links

有效链路的位图,对于非 MLO 为 0。

active_links

活动链路的位图,对于非 MLO 为 0。驱动程序不应直接更改此项,而应使用为此目的而设计的 API 调用。

dormant_links

有效链路的子集,由于通告或协商的 TTLM 而被禁用/暂停。对于非 MLO 为 0。

suspended_links

dormant_links 的子集,表示由于协商的 TTLM 而被暂停的链路,并且将来可以通过取消 TTLM 协商来激活。对于非 MLO 为 0。

neg_ttlm

协商的 TID 到链路映射信息。请参阅 struct ieee80211_neg_ttlm

addr

此接口的地址

addr_valid

指示该地址是否正在使用。对于被动监视器接口设置为 false,在所有其他情况下设置为 true。

p2p

指示此 AP 或 STA 接口是否为 p2p 接口,即分别为 GO 或 p2p-sta

cab_queue

beacon 后内容(实际上是 DTIM 信标)队列,仅限 AP 模式

hw_queue

每个 AC 的硬件队列

txq

多播数据 TX 队列

netdev_features

此 vif 的硬件支持的 tx netdev 功能。mac80211 将此初始化为 hw->netdev_features,驱动程序可以屏蔽特定的 tx 功能。mac80211 将处理屏蔽的卸载(GSO、CSUM)的软件修复

driver_flags

驱动程序为此接口提供的标志/功能,这些需要在添加接口时或(如果驱动程序支持)在运行时更改接口类型时设置(或清除),mac80211 永远不会触及此字段

offload_flags

802.3 -> 802.11 封装卸载标志,请参阅 enum ieee80211_offload_flags

debugfs_dir

debugfs dentry,驱动程序可以使用它来创建自己的每个接口的调试文件。请注意,对于虚拟监视器接口(如果请求),它将为 NULL。

probe_req_reg

应向 mac80211 报告此接口的探测请求。

rx_mcast_action_reg

应向 mac80211 报告此接口的多播操作帧。

mbssid_tx_vif

如果启用了 MBSSID,则指向传输接口的指针。

drv_priv

供驱动程序使用的数据区域,始终与 sizeof(void *) 对齐。

描述

此结构中的数据在虚拟接口的生命周期内持续存在,供驱动程序使用。

接收和传输处理

这里应该有什么

待定

这应该描述 mac80211/驱动程序中的接收和传输路径以及传输状态处理。

帧格式

通常,当帧在 mac80211 和驱动程序之间传递时,它们以 IEEE 802.11 标头开始,并包括通过无线发送的相同八位字节,但 FCS 除外,FCS 应由硬件计算。

但是,对于高级功能,此规则有各种例外情况

第一个例外是硬件加密和解密卸载,其中 IV/ICV 可能在硬件中生成,也可能不在硬件中生成。

其次,当硬件处理分片时,从 mac80211 传递给驱动程序的帧是 MSDU,而不是 MPDU。

数据包对齐

驱动程序始终需要将与双字节边界对齐的数据包传递到堆栈。

此外,如果可能,它们应以保证包含的 IP 标头与四字节边界对齐的方式对齐有效载荷数据。在常规帧的情况下,这只需将有效载荷对齐到四字节边界(因为 IP 标头直接包含在内,或者在它前面有长度可被四整除的 IV/RFC1042 标头)。如果有效载荷数据未正确对齐并且架构不支持高效的未对齐操作,mac80211 将对齐数据。

但是,对于 A-MSDU 帧,有效载荷数据地址必须产生 2 模 4,因为 A-MSDU 帧中有 14 字节的 802.3 标头,它们将 IP 标头进一步推回四的倍数。值得庆幸的是,这次规范足够明智,要求将每个 A-MSDU 子帧填充到四的倍数的长度。

不支持 Atheros 硬件添加的 802.11 标头和有效载荷之间的填充;在这种情况下,驱动程序需要移动 802.11 标头,使其直接位于有效载荷前面。

从中断调用到 mac80211

只有 ieee80211_tx_status_irqsafe()ieee80211_rx_irqsafe() 可以在硬件中断上下文中调用。底层驱动程序不得在硬件中断上下文中调用任何其他函数。如果需要此类调用,则底层驱动程序应首先确认中断,然后在此之后执行 IEEE 802.11 代码调用,例如,从计划的工作队列甚至 tasklet 函数。

注意:如果驱动程序选择使用 _irqsafe() 函数,则它也可能不

使用非 IRQ 安全函数!

函数/定义

enum mac80211_tx_info_flags

描述传输信息/状态的标志

常量

IEEE80211_TX_CTL_REQ_TX_STATUS

需要此帧的 TX 状态回调。

IEEE80211_TX_CTL_ASSIGN_SEQ

驱动程序必须为此帧分配一个序列号,注意不要覆盖分段号,并且仅当设置 IEEE80211_TX_CTL_FIRST_FRAGMENT 标志时才增加序列号。mac80211 将为 QoS 数据帧正确分配序列号,但不能为非 QoS 数据帧和管理帧正确分配序列号,因为信标也需要来自该计数器的序列号,并且 mac80211 不能保证正确的排序。如果设置此标志,驱动程序应指示硬件为帧分配序列号或自己分配一个序列号。参见 IEEE 802.11-2007 7.1.3.4.1 第 3 段。此标志将始终为信标设置,并且对于没有序列号字段的帧始终清除。

IEEE80211_TX_CTL_NO_ACK

告诉底层不要等待确认

IEEE80211_TX_CTL_CLEAR_PS_FILT

清除目标站的省电过滤器

IEEE80211_TX_CTL_FIRST_FRAGMENT

这是帧的第一个片段

IEEE80211_TX_CTL_SEND_AFTER_DTIM

在 DTIM 信标之后发送此帧

IEEE80211_TX_CTL_AMPDU

此帧应作为 A-MPDU 的一部分发送

IEEE80211_TX_CTL_INJECTED

帧已注入,mac80211 内部。

IEEE80211_TX_STAT_TX_FILTERED

该帧未传输,因为目标 STA 处于省电模式。请注意,为避免竞争条件,过滤器必须由硬件或固件在收到指示该站进入睡眠状态的帧时设置(必须在设备上完成,以过滤队列中已有的帧),并且只能在 mac80211 通过设置 IEEE80211_TX_CTL_CLEAR_PS_FILT(见上文)给出 OK 后才能取消设置,因为只有这样才能保证硬件队列中没有更多帧。

IEEE80211_TX_STAT_ACK

帧已确认

IEEE80211_TX_STAT_AMPDU

帧已聚合,因此状态适用于整个聚合。

IEEE80211_TX_STAT_AMPDU_NO_BACK

未返回块确认,因此请考虑使用块确认请求 (BAR)。

IEEE80211_TX_CTL_RATE_CTRL_PROBE

mac80211 内部,可由速率控制算法设置以指示探测速率,将清除分片帧(最后一个片段除外)

IEEE80211_TX_INTFL_OFFCHAN_TX_OK

mac80211 内部。用于指示当队列因异频信道操作而停止时,可以传输帧。

IEEE80211_TX_CTL_HW_80211_ENCAP

此帧使用硬件封装(标头转换)

IEEE80211_TX_INTFL_RETRIED

完全是 mac80211 内部,用于指示由于 PS 而已重试过帧

IEEE80211_TX_INTFL_DONT_ENCRYPT

完全是 mac80211 内部,用于指示不应加密帧

IEEE80211_TX_CTL_NO_PS_BUFFER

此帧是对轮询帧(PS-Poll 或 uAPSD)或不可缓冲的 MMPDU 的响应,即使该站处于省电模式也必须发送。

IEEE80211_TX_CTL_MORE_FRAMES

当前帧之后,将向传输函数传递更多帧,驱动程序可以使用此功能仅在取消设置时或队列已满时才启动 DMA 队列。

IEEE80211_TX_INTFL_RETRANSMISSION

此帧在 TX 状态之后正在重新传输,因为目标处于休眠状态,因此不得再次修改(无 seqno 分配、加密等)

IEEE80211_TX_INTFL_MLME_CONN_TX

此帧由 MLME 代码传输,用于建立连接,这表示其状态应启动 MLME 状态机。

IEEE80211_TX_INTFL_NL80211_FRAME_TX

通过 nl80211 MLME 命令请求的帧(mac80211 内部,用于确定是否将 TX 状态发送到用户空间)

IEEE80211_TX_CTL_LDPC

告诉驱动程序为此帧使用 LDPC

IEEE80211_TX_CTL_STBC

为该帧启用空时分组码 (STBC),并选择它可使用的最大流数。

IEEE80211_TX_CTL_TX_OFFCHAN

当在硬件中完成保持在信道上的卸载时,将此数据包标记为在异频信道上传输 - 正常数据包仍然流动,并期望设备正确处理。

IEEE80211_TX_INTFL_TKIP_MIC_FAILURE

将此数据包标记为用于 TKIP 测试。它将使用不正确的 Michael MIC 密钥发送出去,以允许测试 TKIP 对策。

IEEE80211_TX_CTL_NO_CCK_RATE

此帧将以非 CCK 速率发送。此标志实际上用于管理帧,特别是用于在 2GHz 频段中不以 CCK 速率发送的 P2P 帧。

IEEE80211_TX_STATUS_EOSP

此数据包标志着服务周期的结束,当其状态被报告时,服务周期结束。对于 mac80211 发送的 SP 中的帧,此标志已设置;对于驱动程序帧,驱动程序可以设置此标志。它也用于对 PS-Poll 响应执行相同的操作。

IEEE80211_TX_CTL_USE_MINRATE

此帧将以最低速率发送。当 nullfunc 用于连接监控目的时,此标志用于以最低速率发送 nullfunc 帧。

IEEE80211_TX_CTL_DONTFRAG

即使此数据包会因大小而被分片,也不要对其进行分片(这是可选的,仅用于监控注入)。

IEEE80211_TX_STAT_NOACK_TRANSMITTED

标记为 IEEE80211_TX_CTL_NO_ACK 的帧已成功发送,没有任何错误(例如特定于驱动程序/硬件的问题)。对于未使用 IEEE80211_TX_CTL_NO_ACK 请求无确认行为的帧,不得设置此标志。

描述

这些标志与 ieee80211_tx_infoflags 成员一起使用。

注意

如果必须向枚举添加新标志,请不要

忘记在必要时更新 IEEE80211_TX_TEMPORARY_FLAGS

enum mac80211_tx_control_flags

用于描述发送控制的标志

常量

IEEE80211_TX_CTRL_PORT_CTRL_PROTO

此帧是端口控制协议帧(例如,EAP)

IEEE80211_TX_CTRL_PS_RESPONSE

此帧是对轮询帧(PS-Poll 或 uAPSD)的响应。

IEEE80211_TX_CTRL_RATE_INJECT

此帧注入了速率信息

IEEE80211_TX_CTRL_AMSDU

此帧是 A-MSDU 帧

IEEE80211_TX_CTRL_FAST_XMIT

此帧正在通过 fast_xmit 路径

IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP

此帧跳过网状路径查找

IEEE80211_TX_INTCFL_NEED_TXPROCESSING

完全在 mac80211 内部使用,用于指示挂起的帧在发送之前需要 TX 处理。

IEEE80211_TX_CTRL_NO_SEQNO

不要覆盖已分配给此帧的序列号。

IEEE80211_TX_CTRL_DONT_REORDER

此帧不应相对于其他设置了此标志的帧重新排序,而与其 QoS TID 或其他优先级字段值无关。

IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX

第一个 MLO TX,主要在内部用于序列号分配

IEEE80211_TX_CTRL_DONT_USE_RATE_MASK

不要为此帧使用速率掩码,此帧由于扫描或异频 TX 而传输,而不是接口上的正常操作。

IEEE80211_TX_CTRL_MLO_LINK

如果不是 IEEE80211_LINK_UNSPECIFIED,则应在特定链路上发送此帧。这实际上只与不存在数据的帧相关,并且不用于 802.3 格式的帧。请注意,即使帧位于特定链路上,如果它旨在用于 MLD,则地址转换仍然可能适用。

描述

这些标志在 tx_info->control.flags 中使用。

enum mac80211_rate_control_flags

速率控制算法设置的每速率标志。

常量

IEEE80211_TX_RC_USE_RTS_CTS

对此速率使用 RTS/CTS 交换。

IEEE80211_TX_RC_USE_CTS_PROTECT

需要 CTS 自保护。如果当前 BSS 需要 ERP 保护,则会设置此标志。

IEEE80211_TX_RC_USE_SHORT_PREAMBLE

使用短前导码。

IEEE80211_TX_RC_MCS

HT 速率。

IEEE80211_TX_RC_GREEN_FIELD

指示此速率是否应在 Greenfield 模式下使用。

IEEE80211_TX_RC_40_MHZ_WIDTH

指示信道宽度是否应为 40 MHz。

IEEE80211_TX_RC_DUP_DATA

如果当前信道类型是 NL80211_CHAN_HT40MINUS 或 NL80211_CHAN_HT40PLUS,则帧应在相邻的两个 20 MHz 信道上发送。

IEEE80211_TX_RC_SHORT_GI

此速率应使用短保护间隔。

IEEE80211_TX_RC_VHT_MCS

VHT MCS 速率,在这种情况下,idx 字段分为较高的 4 位(Nss)和较低的 4 位(MCS 编号)

IEEE80211_TX_RC_80_MHZ_WIDTH

指示 80 MHz 传输

IEEE80211_TX_RC_160_MHZ_WIDTH

指示 160 MHz 传输(尚不支持 80+80)

描述

这些标志由速率控制算法在 tx 期间为每个速率设置,位于 struct ieee80211_tx_rateflags 成员中。

struct ieee80211_tx_rate

速率选择/状态

定义:

struct ieee80211_tx_rate {
    s8 idx;
    u16 count:5, flags:11;
};

成员

idx

尝试发送的速率索引

count

在此速率下尝试的次数,然后再转到下一个速率

flags

速率控制标志(enum mac80211_rate_control_flags

描述

idx 的值 -1 表示无效速率,如果用于重试速率数组中,则表示不应再尝试更多速率。

当用于传输状态报告时,驱动程序应始终报告速率及其使用的标志。

struct ieee80211_tx_info 在控制信息中包含这些结构体的数组,它将由速率控制算法根据应发送的内容进行填充。例如,如果此数组以 { <idx>, <count> } 的格式包含信息

{ 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }

那么这意味着该帧应以速率 3 最多传输两次,以速率 2 最多传输两次,如果未收到确认,则以速率 1 最多传输四次。假设它在第五次尝试后被对等方确认,则状态信息应包含

{ 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...

因为它以速率 3 传输了两次,以速率 2 传输了两次,然后以速率 1 传输了一次,之后我们收到了确认。

struct ieee80211_tx_info

skb 传输信息

定义:

struct ieee80211_tx_info {
    u32 flags;
    u32 band:3,status_data_idr:1,status_data:13,hw_queue:4, tx_time_est:10;
    union {
        struct {
            union {
                struct {
                    struct ieee80211_tx_rate rates[ IEEE80211_TX_MAX_RATES];
                    s8 rts_cts_rate_idx;
                    u8 use_rts:1;
                    u8 use_cts_prot:1;
                    u8 short_preamble:1;
                    u8 skip_table:1;
                    u8 antennas:2;
                };
                unsigned long jiffies;
            };
            struct ieee80211_vif *vif;
            struct ieee80211_key_conf *hw_key;
            u32 flags;
            codel_time_t enqueue_time;
        } control;
        struct {
            u64 cookie;
        } ack;
        struct {
            struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
            s32 ack_signal;
            u8 ampdu_ack_len;
            u8 ampdu_len;
            u8 antenna;
            u8 pad;
            u16 tx_time;
            u8 flags;
            u8 pad2;
            void *status_driver_data[16 / sizeof(void *)];
        } status;
        struct {
            struct ieee80211_tx_rate driver_rates[ IEEE80211_TX_MAX_RATES];
            u8 pad[4];
            void *rate_driver_data[ IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
        };
        void *driver_data[ IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)];
    };
};

成员

flags

传输信息标志,如上定义

band

要在其上发送的频段(例如,用于检查竞争),如果接口是 MLD,则无效,因为我们不知道该帧将在哪个链路上发送

status_data_idr

指示状态数据是为 ack 帧分配的 IDR ID

status_data

用于 TX 状态处理的内部数据,私下分配,另请参见 enum ieee80211_status_data 以获取内部文档

hw_queue

将帧放置到的 HW 队列,skb_get_queue_mapping() 提供 AC

tx_time_est

以 4us 为单位的 TX 时间估计值,在内部使用

{unnamed_union}

anonymous

control

控制数据的联合部分

{unnamed_union}

anonymous

{unnamed_struct}

anonymous

control.rates

要尝试的 TX 速率数组

control.rts_cts_rate_idx

RTS 或 CTS 的速率

control.use_rts

使用 RTS

control.use_cts_prot

使用 RTS/CTS

control.short_preamble

使用短前导码(仅限 CCK)

control.skip_table

跳过外部配置的速率表

control.jiffies

用于节能客户端过期的时间戳

control.vif

虚拟接口(可能为 NULL)

control.hw_key

用于加密的密钥(可能为 NULL)

control.flags

控制标志,请参见 enum mac80211_tx_control_flags

control.enqueue_time

入队时间(对于 iTXQ)

ack

用于纯 ACK 数据的联合部分

ack.cookie

ACK 的 cookie

status

用于状态数据的联合部分

status.rates

尝试的速率

status.ack_signal

ACK 信号

status.ampdu_ack_len

AMPDU ack 长度

status.ampdu_len

AMPDU 长度

status.antenna

(旧版,仅用于 iwlegacy)

status.tx_time

传输消耗的空闲时间;请注意,这仅用于 WMM AC,而不用于空闲时间公平性

status.flags

状态标志,请参见 enum mac80211_tx_status_flags

status.status_driver_data

驱动程序使用区域

{unnamed_struct}

anonymous

driver_rates

control.rates 的别名,用于保留空间

pad

填充

rate_driver_data

如果驱动程序需要 control.rates,则驱动程序使用区域

driver_data

driver_data 指针数组

描述

此结构体放置在 skb->cb 中,用于三个用途
  1. mac80211 TX 控制 - mac80211 告诉驱动程序要执行的操作

  2. 驱动程序内部使用(如果适用)

  3. TX 状态信息 - 驱动程序告诉 mac80211 发生了什么

void ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)

清除 TX 状态

参数

struct ieee80211_tx_info *info

要清除的 struct ieee80211_tx_info

描述

当驱动程序将 skb 返回到 mac80211 时,它必须在 TX 状态中报告许多内容。此函数清除 TX 状态中的所有内容,但速率控制信息(它会清除计数,因为您无论如何都需要填写该计数)。

注意

虽然速率数组保持不变,但这会擦除 info 中的所有

driver_data 字段,因此驱动程序需要在调用此帮助程序后恢复其需要的任何字段。

enum mac80211_rx_flags

接收标志

常量

RX_FLAG_MMIC_ERROR

在此帧上报告了 Michael MIC 错误。与 RX_FLAG_MMIC_STRIPPED 一起使用。

RX_FLAG_DECRYPTED

此帧已在硬件中解密。

RX_FLAG_ONLY_MONITOR

仅向监视接口报告帧,而不以任何常规方式处理它。如果驱动程序卸载某些帧但仍希望报告它们以进行嗅探,这将非常有用。

RX_FLAG_MMIC_STRIPPED

Michael MIC 已从此帧中删除,硬件已完成验证。

RX_FLAG_IV_STRIPPED

IV 和 ICV 已从此帧中删除。如果设置此标志,则堆栈无法进行任何重放检测,因此驱动程序或硬件必须执行此操作。

RX_FLAG_FAILED_FCS_CRC

如果帧上的 FCS 校验失败,则设置此标志。

RX_FLAG_FAILED_PLCP_CRC

如果帧上的 PCLP 校验失败,则设置此标志。

RX_FLAG_MACTIME_IS_RTAP_TS64

RX状态中的 mactime 时间戳仅用于 radiotap 时间戳头部,不是一个有效的 mactime 值。请注意,这是一个单独的标志,因此我们仍然看到 RX_FLAG_MACTIME 未设置。另请注意,在这种情况下,时间戳报告为 64 位宽,而不仅仅是 32 位。

RX_FLAG_NO_SIGNAL_VAL

信号强度值不存在。仅对数据帧(主要是 A-MPDU)有效

RX_FLAG_AMPDU_DETAILS

A-MPDU 详细信息已知,特别是参考编号 (ampdu_reference) 必须填充,并且对于每个 A-MPDU 都是不同的数字

RX_FLAG_PN_VALIDATED

目前仅对 CCMP/GCMP 帧有效,此标志表示 PN 已验证以进行重放保护。请注意,此标志目前仅在帧也被解密时才支持(即必须设置 RX_FLAG_DECRYPTED

RX_FLAG_DUP_VALIDATED

如果驱动程序本身进行了去重,则应设置此标志。

RX_FLAG_AMPDU_LAST_KNOWN

已知最后一个子帧,应在单个 A-MPDU 的所有子帧上设置

RX_FLAG_AMPDU_IS_LAST

此子帧是 A-MPDU 的最后一个子帧

RX_FLAG_AMPDU_DELIM_CRC_ERROR

在此子帧上检测到分隔符 CRC 错误

RX_FLAG_MACTIME

如果此字段为非零值,则 RX 状态(mactime 字段)中传递的时间戳有效,并且采样时间戳的位置取决于该值。

RX_FLAG_MACTIME_PLCP_START

RX 状态(mactime 字段)中传递的时间戳有效,并且包含收到 SYNC 前导码的时间。

RX_FLAG_MACTIME_START

RX 状态(mactime 字段)中传递的时间戳有效,并且包含收到 MPDU 的第一个符号的时间。这在监视模式和正确的 IBSS 合并中很有用。

RX_FLAG_MACTIME_END

RX 状态(mactime 字段)中传递的时间戳有效,并且包含收到 MPDU 的最后一个符号(包括 FCS)的时间。

RX_FLAG_SKIP_MONITOR

处理帧并将其报告给所有接口,但监视器接口除外。如果驱动程序卸载一些帧,但仍然希望为了嗅探目的而报告它们,则此功能很有用。

RX_FLAG_AMSDU_MORE

出于性能原因,某些驱动程序可能更喜欢报告单独的 A-MSDU 子帧,而不是一个巨大的帧。来自 A-MSDU 的所有 MSDU,但最后一个 MSDU 除外,都应设置此标志。例如,如果 A-MSDU 有 3 个帧,则前 2 个必须设置该标志,而第 3 个(最后一个)则不能设置该标志。该标志用于正确处理重传/重复恢复,因为 A-MSDU 子帧共享相同的序列号。报告的子帧可以是常规 MSDU 或单个 A-MSDU。子帧不得与其他帧交错。

RX_FLAG_RADIOTAP_TLV_AT_END

此帧在 skb->data 中包含 radiotap TLV(在 802.11 标头之前)。如果使用,则 SKB 的 mac_header 指针必须设置为指向 TLV 之后的 802.11 标头,并且驱动程序在 skb 中放置 TLV 后添加到 4 对齐的任何填充都必须被清除。

RX_FLAG_MIC_STRIPPED

此数据包的 mic 已被剥离。解密由硬件完成

RX_FLAG_ALLOW_SAME_PN

允许与之前的相同数据包使用相同的 PN。这用于 AMSDU 子帧,它们可以与第一个子帧具有相同的 PN。

RX_FLAG_ICV_STRIPPED

此帧已剥离 ICV。CRC 校验必须在硬件中完成。

RX_FLAG_AMPDU_EOF_BIT

此帧的 A-MPDU 分隔符中的 EOF 位的值

RX_FLAG_AMPDU_EOF_BIT_KNOWN

EOF 值已知

RX_FLAG_RADIOTAP_HE

存在 HE radiotap 数据 (struct ieee80211_radiotap_he, mac80211 将会填写)

  • DATA3_DATA_MCS

  • DATA3_DATA_DCM

  • DATA3_CODING

  • DATA5_GI

  • DATA5_DATA_BW_RU_ALLOC

  • DATA6_NSTS

  • DATA3_STBC

来自 RX 信息数据,因此在构建此数据时将这些数据归零)

RX_FLAG_RADIOTAP_HE_MU

存在 HE MU radiotap 数据 (struct ieee80211_radiotap_he_mu)

RX_FLAG_RADIOTAP_LSIG

存在 L-SIG radiotap 数据

RX_FLAG_NO_PSDU

仅将该帧用于 radiotap 报告,其中包含 “0 长度 PSDU” 字段。它的值位于 struct ieee80211_rx_status 中。请注意,如果此值未知,则不应报告该帧。

RX_FLAG_8023

该帧具有 802.3 标头(由硬件或驱动程序执行的解封装卸载)

描述

这些标志与 struct ieee80211_rx_statusflag 成员一起使用。

enum mac80211_rx_encoding_flags

MCS & 带宽标志

常量

RX_ENC_FLAG_SHORTPRE

此帧使用了短前导码

RX_ENC_FLAG_SHORT_GI

使用了短保护间隔

RX_ENC_FLAG_HT_GF

如果驱动程序填充此值,则此帧在 HT-greenfield 传输中接收,它应将 IEEE80211_RADIOTAP_MCS_HAVE_FMT 添加到 hw.radiotap_mcs_details 中,以声明该事实。

RX_ENC_FLAG_STBC_MASK

STBC 2 位位掩码。1 - Nss=1, 2 - Nss=2, 3 - Nss=3

RX_ENC_FLAG_LDPC

使用了 LDPC

RX_ENC_FLAG_BF

数据包已波束成形

struct ieee80211_rx_status

接收状态

定义:

struct ieee80211_rx_status {
    u64 mactime;
    union {
        u64 boottime_ns;
        ktime_t ack_tx_hwtstamp;
    };
    u32 device_timestamp;
    u32 ampdu_reference;
    u32 flag;
    u16 freq: 13, freq_offset: 1;
    u8 enc_flags;
    u8 encoding:3, bw:4;
    union {
        struct {
            u8 he_ru:3;
            u8 he_gi:2;
            u8 he_dcm:1;
        };
        struct {
            u8 ru:4;
            u8 gi:2;
        } eht;
    };
    u8 rate_idx;
    u8 nss;
    u8 rx_flags;
    u8 band;
    u8 antenna;
    s8 signal;
    u8 chains;
    s8 chain_signal[IEEE80211_MAX_CHAINS];
    u8 zero_length_psdu_type;
    u8 link_valid:1, link_id:4;
};

成员

mactime

当第一个数据符号 (MPDU) 到达硬件时,64 位时间同步函数 (TSF) 计时器的微秒值。

{unnamed_union}

anonymous

boottime_ns

接收帧时的 CLOCK_BOOTTIME 时间戳,这仅对于更新扫描缓存的信标和探测响应是必需的。

ack_tx_hwtstamp

ack TX 的硬件时间戳(以纳秒为单位)。仅对于计时测量和精细计时测量操作帧是必需的。仅由启用了时间戳的设备报告。

device_timestamp

设备的任意时间戳,mac80211 不使用它,但可以存储它并将其传递回驱动程序以进行同步

ampdu_reference

A-MPDU 参考编号,每个 A-MPDU 必须是一个不同的值,但对于一个 A-MPDU 中的每个子帧,该值必须相同

flag

RX_FLAG_*

freq

无线电接收此帧时调谐到的频率,以 MHz 为单位。必须为管理帧设置此字段,但对于数据(其他)帧不是严格必需的 - 对于这些帧,它仅影响 radiotap 报告。

freq_offset

freq 的正偏移量为 500Khz。

enc_flags

使用来自 enum mac80211_rx_encoding_flags 的位

encoding

enum mac80211_rx_encoding

bw

enum rate_info_bw

{unnamed_union}

anonymous

{unnamed_struct}

anonymous

he_ru

HE RU,来自 enum nl80211_he_ru_alloc

he_gi

HE GI,来自 enum nl80211_he_gi

he_dcm

HE DCM 值

eht

EHT 特定速率信息

eht.ru

EHT RU,来自 enum nl80211_eht_ru_alloc

eht.gi

EHT GI,来自 enum nl80211_eht_gi

rate_idx

数据速率在频段的支持速率中的索引,如果使用 HT 或 VHT,则为 MCS 索引 (RX_FLAG_HT/RX_FLAG_VHT)

nss

流的数量(仅限 VHT、HE 和 EHT)

rx_flags

mac80211 的内部 RX 标志

band

接收此帧时活动的频段

antenna

使用的天线

signal

接收此帧时的信号强度,以 dBm 为单位、以 dB 为单位或未指定,具体取决于硬件功能标志 IEEE80211_HW_SIGNAL_*

chains

为其填充了单独的信号强度值的接收链的位掩码。

chain_signal

每个链的信号强度,以 dBm 为单位(与 signal 不同,不支持 dB 或未指定的单位)

zero_length_psdu_type

0 长度 PSDU 的 radiotap 类型

link_valid

如果由 link_id 标识的链路有效。此标志仅在连接为 MLO 时设置。

link_id

用于接收数据包的链路的 ID。这与 link_valid 一起使用。

描述

低级驱动程序应使用每个接收到的帧,在 skb 的控制缓冲区 (cb) 中向 802.11 代码提供此信息(硬件支持的子集)。

void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)

接收帧

参数

struct ieee80211_hw *hw

此帧传入的硬件

struct sk_buff *skb

接收缓冲区,在此调用后归 mac80211 所有

描述

使用此函数将接收到的帧传递给 mac80211。skb 中的接收缓冲区必须以 IEEE 802.11 标头开头。在使用分页的 skb 的情况下,建议驱动程序将帧的 ieee80211 标头放在 skb 的线性部分,以避免堆栈的内存分配和/或 memcpy。

此函数不得在 IRQ 上下文调用。对单个硬件调用此函数必须彼此同步。对于单个硬件,此函数、ieee80211_rx_ni()ieee80211_rx_irqsafe() 的调用不得混合使用。不得与 ieee80211_tx_status_skb()ieee80211_tx_status_ni() 同时运行。

在进程上下文中,请改用 ieee80211_rx_ni()

void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)

接收帧

参数

struct ieee80211_hw *hw

此帧传入的硬件

struct sk_buff *skb

接收缓冲区,在此调用后归 mac80211 所有

描述

类似于 ieee80211_rx(),但可以在 IRQ 上下文中调用(内部会延迟到 tasklet)。

对于单个硬件,此函数、ieee80211_rx()ieee80211_rx_ni() 的调用不得混合使用。不得与 ieee80211_tx_status_skb()ieee80211_tx_status_ni() 同时运行。

void ieee80211_rx_ni(struct ieee80211_hw *hw, struct sk_buff *skb)

接收帧(在进程上下文中)。

参数

struct ieee80211_hw *hw

此帧传入的硬件

struct sk_buff *skb

接收缓冲区,在此调用后归 mac80211 所有

描述

类似于 ieee80211_rx(),但可以在进程上下文中调用(内部会禁用底部半部)。

对于单个硬件,此函数、ieee80211_rx()ieee80211_rx_irqsafe() 的调用不得混合使用。不得与 ieee80211_tx_status_skb()ieee80211_tx_status_ni() 同时运行。

void ieee80211_tx_status_skb(struct ieee80211_hw *hw, struct sk_buff *skb)

发送状态回调。

参数

struct ieee80211_hw *hw

发送帧的硬件。

struct sk_buff *skb

发送的帧,在此调用后由 mac80211 拥有。

描述

在发送完所有发送的帧后调用此函数。允许不对多播帧调用此函数,但这会影响统计信息。

此函数不得在 IRQ 上下文调用。对单个硬件调用此函数必须彼此同步。对于单个硬件,此函数、ieee80211_tx_status_ni()ieee80211_tx_status_irqsafe() 的调用不得混合使用。不得与 ieee80211_rx()ieee80211_rx_ni() 同时运行。

void ieee80211_tx_status_ni(struct ieee80211_hw *hw, struct sk_buff *skb)

发送状态回调(在进程上下文中)。

参数

struct ieee80211_hw *hw

发送帧的硬件。

struct sk_buff *skb

发送的帧,在此调用后由 mac80211 拥有。

描述

类似于 ieee80211_tx_status_skb(),但可以在进程上下文中调用。

对于单个硬件,此函数、ieee80211_tx_status_skb()ieee80211_tx_status_irqsafe() 的调用不得混合使用。

void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)

IRQ 安全的发送状态回调。

参数

struct ieee80211_hw *hw

发送帧的硬件。

struct sk_buff *skb

发送的帧,在此调用后由 mac80211 拥有。

描述

类似于 ieee80211_tx_status_skb(),但可以在 IRQ 上下文中调用(内部会延迟到 tasklet)。

对于单个硬件,此函数、ieee80211_tx_status_skb()ieee80211_tx_status_ni() 的调用不得混合使用。

void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_info *frame_txctl, struct ieee80211_rts *rts)

RTS 帧生成函数。

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

const void *frame

指向将由 RTS 保护的帧的指针。

size_t frame_len

帧长度(以字节为单位)。

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

struct ieee80211_rts *rts

用于存储 RTS 帧的缓冲区。

描述

如果 RTS 帧由主机系统生成(即,不是在硬件/固件中生成),则底层驱动程序使用此函数从 802.11 代码接收下一个 RTS 帧。底层驱动程序负责在需要 RTS 帧之前调用此函数。

__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, size_t frame_len, const struct ieee80211_tx_info *frame_txctl)

获取 RTS 帧的持续时间字段

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

size_t frame_len

将要被 RTS 保护的帧的长度。

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

描述

如果 RTS 在固件中生成,但主机系统必须提供持续时间字段,则底层驱动程序使用此函数以小端字节序接收持续时间字段值。

返回

持续时间。

void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_info *frame_txctl, struct ieee80211_cts *cts)

自发 CTS 帧生成函数

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

const void *frame

指向将要被自发 CTS 保护的帧的指针。

size_t frame_len

帧长度(以字节为单位)。

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

struct ieee80211_cts *cts

存储自发 CTS 帧的缓冲区。

描述

如果自发 CTS 帧由主机系统生成(即,不是在硬件/固件中生成),则底层驱动程序使用此函数从 802.11 代码接收下一个自发 CTS 帧。底层驱动程序负责在需要自发 CTS 帧之前调用此函数。

__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, size_t frame_len, const struct ieee80211_tx_info *frame_txctl)

获取自发 CTS 帧的持续时间字段

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

size_t frame_len

将要被自发 CTS 保护的帧的长度。

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

描述

如果自发 CTS 在固件中生成,但主机系统必须提供持续时间字段,则底层驱动程序使用此函数以小端字节序接收持续时间字段值。

返回

持续时间。

__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_band band, size_t frame_len, struct ieee80211_rate *rate)

计算帧的持续时间字段

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

enum nl80211_band band

用于计算帧持续时间的频段

size_t frame_len

帧的长度。

struct ieee80211_rate *rate

帧将要传输的速率。

描述

计算给定长度和传输速率(以 100kbps 为单位)的某个通用帧的持续时间字段。

返回

持续时间。

void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)

唤醒特定的队列

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

int queue

队列号(从零开始计数)。

描述

驱动程序必须使用此函数而不是 netif_wake_queue。

void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)

停止特定的队列

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

int queue

队列号(从零开始计数)。

描述

驱动程序必须使用此函数而不是 netif_stop_queue。

int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)

测试队列的状态

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

int queue

队列号(从零开始计数)。

描述

驱动程序必须使用此函数而不是 netif_queue_stopped。

返回

如果队列已停止,则为 true。否则为 false

void ieee80211_stop_queues(struct ieee80211_hw *hw)

停止所有队列

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

描述

驱动程序必须使用此函数而不是 netif_tx_stop_all_queues。

void ieee80211_wake_queues(struct ieee80211_hw *hw)

唤醒所有队列

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

描述

驱动程序必须使用此函数而不是 netif_tx_wake_all_queues。

帧过滤

mac80211 需要看到许多管理帧才能正常运行,并且当处于监视模式时,用户可能希望看到更多帧。但是,为了获得最佳的 CPU 使用率和功耗,最好让尽可能少的帧通过堆栈。因此,硬件应尽可能多地进行过滤。

为了实现这一点,mac80211 使用过滤器标志(见下文)来告知驱动程序的 configure_filter() 函数哪些帧应传递给 mac80211,哪些帧应过滤掉。

在调用 configure_filter() 之前,将使用参数 mc_countmc_list 为所有虚拟接口的组合多播地址列表调用 prepare_multicast() 回调。它的使用是可选的,它返回一个 u64,该 u64 会传递给 configure_filter()。此外,configure_filter() 还有 changed_flags 参数,用于指示哪些标志被更改,以及 total_flags 参数,用于指示新的标志状态。

如果您的设备没有多播地址过滤器,您的驱动程序将需要检查 FIF_ALLMULTI 标志和 mc_count 参数,以确定是否应该接受或丢弃多播帧。

total_flags 中所有不支持的标志都必须清除。如果硬件无法将帧 _传递_ 到堆栈,则表示该硬件不支持该标志。否则,驱动程序必须忽略该标志,但不能清除它。只有当您无法将数据包类型传递到堆栈时(即硬件始终会过滤该数据包),您才必须_清除_该标志(向 mac80211 声明不支持该标志)。例如,如果您的硬件始终过滤控制帧,则应清除 FIF_CONTROL。如果您的硬件始终将控制帧传递到内核并且无法过滤它们,则您_不_清除 FIF_CONTROL 标志。此规则也适用于所有其他 FIF 标志。

enum ieee80211_filter_flags

硬件过滤标志

常量

FIF_ALLMULTI

传递所有多播帧,如果用户请求或硬件无法按多播地址过滤时,则使用此标志。

FIF_FCSFAIL

传递 FCS 失败的帧(但您需要为它们设置 RX_FLAG_FAILED_FCS_CRC

FIF_PLCPFAIL

传递 PLCP CRC 失败的帧(但您需要为它们设置 RX_FLAG_FAILED_PLCP_CRC

FIF_BCN_PRBRESP_PROMISC

此标志在扫描期间设置,以指示硬件不应按 BSSID 过滤信标或探测响应。过滤它们可以大大减少 mac80211 需要执行的处理量和 CPU 唤醒次数,因此如果可能,您应该遵守此标志。

FIF_CONTROL

传递寻址到此站点的控制帧(PS Poll 除外)

FIF_OTHER_BSS

传递目标为其他 BSS 的帧

FIF_PSPOLL

传递 PS Poll 帧

FIF_PROBE_REQ

传递探测请求帧

FIF_MCAST_ACTION

传递多播 Action 帧

描述

这些标志确定硬件中的过滤器应被编程为允许哪些帧通过,以及哪些帧不应传递到堆栈。传递比请求的更多的帧始终是安全的,但这会对功耗产生负面影响。

mac80211 工作队列

mac80211 为驱动程序和内部 mac80211 使用提供了自己的工作队列。该工作队列是单线程工作队列,并且只能通过助手进行访问以进行健全性检查。驱动程序必须确保添加到 mac80211 工作队列的所有工作都应在驱动程序的 stop() 回调中取消。

mac80211 将在接口移除和挂起期间刷新工作队列。

在 mac80211 工作队列上执行的所有工作都不得获取 RTNL 锁。

void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)

将工作添加到 mac80211 工作队列

参数

struct ieee80211_hw *hw

我们要添加工作的接口的硬件结构

struct work_struct *work

我们想要添加到 mac80211 工作队列的工作

描述

驱动程序和 mac80211 使用它来将工作添加到 mac80211 工作队列。此助手可确保驱动程序不会在不应该排队工作时排队工作。

void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, struct delayed_work *dwork, unsigned long delay)

将工作添加到 mac80211 工作队列

参数

struct ieee80211_hw *hw

我们要添加工作的接口的硬件结构

struct delayed_work *dwork

要排队到 mac80211 工作队列的可延迟工作

unsigned long delay

在排队之前等待的 jiffies 数量

描述

驱动程序和 mac80211 使用它来将延迟工作排队到 mac80211 工作队列。