mac80211 子系统(基础)

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

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

基本硬件处理

待定

本章将包含有关获取 hw 结构并将其注册到 mac80211 的信息。

由于需要在注册 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(分贝差,以一毫瓦为基准)给出信号值。这是首选方法,因为它在不同的设备之间是标准化的。不需要设置 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。预计用户空间会根据需要创建 vif(因此可以根据需要命名它们)。

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

该设备严格在 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 skb 的有效负载或尾部空间。

IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS

HW 支持在一个命令中扫描所有频段,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 队列和快速传输支持。当不使用 minstrel/minstrel_ht 速率控制时,驱动程序必须通过在 struct ieee80211_sta 中设置 max_rc_amsdu_len 来限制最大 A-MSDU 大小,具体取决于当前 tx 速率。

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 BW (dot11VHTExtendedNSSBWCapable)。如果所选的速率控制算法设置了 RATE_CTRL_CAPA_VHT_EXT_NSS_BW,则将设置此标志,但如果速率控制是内置的,则必须由驱动程序设置。另请参阅该标志的文档。

IEEE80211_HW_STA_MMPDU_TXQ

将额外的每个站点的非 TID TXQ 用于站点接口上的所有 MMPDU。当然,这需要驱动程序首先使用 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 帧。如果支持此功能,则驱动程序必须将用于实际使用的 802.3 帧和设置了 RX_FLAG_ONLY_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 的驱动程序设置,因此当一个链路切换时,可以在其他链路上继续操作。

IEEE80211_HW_STRICT

严格执行规范规定的某些内容,否则会为了互操作性而被忽略/解决。这是一个 HW 标志,因此驱动程序可以根据自己的控制选择加入,例如在测试中。

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

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

max_report_rates

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

max_rate_tries

每个阶段的最大尝试次数

max_rx_aggregation_subframes

要用于 A-MPDU 块 ack 接收器聚合的最大缓冲区大小(子帧数)。这仅在设备对子帧数有限制时才相关,如果它依赖 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 硬件支持的功率级别列表。功率级别可以指定为整数或分数。索引 0 处的功率级别应为最大正功率级别。

max_txpwr_levels_idx

“tx_power_levels”列表的最大有效索引。

描述

此结构包含 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, unsigned int link_id, 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

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

stop

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

suspend

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

resume

如果配置了 WoWLAN,则表示 mac80211 现在正在恢复其操作,在此之后,设备必须再次完全正常运行。如果此函数返回错误,则唯一的出路也是注销该设备。如果它返回 1,则 mac80211 还将在恢复时进行常规的完整重新启动。

set_wakeup

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

add_interface

在连接到硬件的 netdevice 启用时调用。由于不会为监控模式设备调用此函数,因此必须实现 startstop。驱动程序应执行设备启用之前所需的任何初始化。conf 参数中给出了接口的初始配置。回调可以通过返回负错误代码(这将在用户空间中看到)来拒绝添加接口。必须实现并且可以休眠。

change_interface

在 netdevice 更改类型时调用。此回调是可选的,但仅当支持此回调时,才能在接口启动时切换接口类型。回调可以休眠。请注意,在切换接口时,接口迭代回调将找不到它。

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而“暂停”时(由通过bss_info_changed禁/启用信标指示),不会调用此函数(和stop_ap)。

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

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

hw_scan

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

cancel_hw_scan

要求底层取消活动的硬件扫描。驱动程序应要求硬件取消扫描(如果可能),但仅在驱动程序调用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/网格对等方等。此回调可以休眠。

sta_remove

通知底层驱动程序有关删除关联的站点、AP、IBSS/WDS/网格对等方等。请注意,在回调返回后,使用该指针是不安全的,即使是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/网格对等方等的电源状态转换。对于在AP模式下运行的VIF,设置IEEE80211_HW_AP_LINK_PS标志后,不会调用此回调。必须是原子的。

sta_set_txpwr

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

sta_state

通知底层驱动程序有关站点(可以是AP、客户端、IBSS/WDS/网格对等方等)的状态转换。此回调与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  

  • TX:        18 

  • 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节中的规定,为给定的覆盖范围类别设置时隙时间,并相应地修改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

准备设备以允许给定数量的帧发送到给定站点。在此调用之后,mac80211将通过通常的TX路径发送帧。已释放帧的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位。如果more_data参数为true,那么当然必须始终设置more-data位。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中定义的模式,将大量vif从一个chanctx切换到另一个,如传递给驱动程序的ieee80211_vif_chanctx_switch列表中所指定的。此回调可以休眠。

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集群,或创建一个新的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

配置可用于某些硬件上的雷达/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_add/sta_state,其中sta->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_changedlink_info_changed,则会调用此回调。

未实现。

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 释放已分配的资源并从网络子系统注销网络设备。

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;
    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

信标后内容(实际上是 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 目录项,驱动程序可以使用它来创建自己的每个接口的调试文件。 请注意,对于虚拟监视器接口(如果已请求),它将为 NULL。

probe_req_reg

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

rx_mcast_action_reg

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

drv_priv

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

描述

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

接收和传输处理

此处应包含哪些内容

待定

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

帧格式

作为一般规则,当帧在 mac80211 和驱动程序之间传递时,它们以 IEEE 802.11 标头开头,并包含通过无线方式发送的相同八位字节,但 FCS 应由硬件计算。

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

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

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

数据包对齐

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

此外,如果可能,它们应以保证包含的 IP 标头与四字节边界对齐的方式对齐有效负载数据。 对于常规帧,这仅仅意味着将有效负载与四字节边界对齐(因为要么直接包含 IP 标头,要么在其前面有长度可被四整除的 IV/RFC1042 标头)。 如果有效负载数据未正确对齐,并且该架构不支持有效的未对齐操作,则 mac80211 将对齐数据。

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

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

从中断调用到 mac80211

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

注意:如果驱动程序选择使用 _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 的帧,没有任何错误(如特定于驱动程序/HW 的问题)。 对于未使用 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 在控制信息中包含这些结构的数组,它将由速率控制算法根据应发送的内容填充。 例如,如果此数组包含以下信息,格式为 { , }:

{ 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

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

{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

排队时间 (for iTXQs)

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(802.11 标头之前)中包含 radiotap TLV。如果使用,则 SKB 的 mac_header 指针必须设置为指向 TLV 之后的 802.11 标头,并且驱动程序必须清除添加到 TLV 数据之后以对齐到 4 的任何填充,并将 TLV 放入 skb 中。

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

确认 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_ni() 的调用不得混合用于单个硬件。不得与 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(),但可以在进程上下文中调用(内部禁用 bottom halves)。

对该函数 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_ni() 的调用不得混合用于单个硬件。不得与 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-to-self 帧生成函数

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

const void *frame

指向将受 CTS-to-self 保护的帧的指针。

size_t frame_len

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

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

struct ieee80211_cts *cts

存储 CTS-to-self 帧的缓冲区。

描述

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

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

获取 CTS-to-self 帧的持续时间字段

参数

struct ieee80211_hw *hw

ieee80211_alloc_hw() 获取的指针。

struct ieee80211_vif *vif

来自 add_interface 回调的 struct ieee80211_vif 指针。

size_t frame_len

将受 CTS-to-self 保护的帧的长度。

const struct ieee80211_tx_info *frame_txctl

帧的 struct ieee80211_tx_info

描述

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

返回

持续时间。

__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)。

描述

计算某个通用帧的持续时间字段,给定其长度和传输速率(单位为 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 工作队列中。