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_addr 和 dev 成员。此外,此处注册了所有支持的频段(带有信道、比特率)。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_UNSPEC 或 IEEE80211_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_info
的 flags 成员一起使用。
注意
- 如果必须向枚举添加新标志,请不要
忘记在必要时更新
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_rate
的 flags 成员中。
-
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 中,用于三个用途
mac80211 TX 控制 - mac80211 告诉驱动程序要执行的操作
驱动程序内部使用(如果适用)
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_status
的 flag 成员一起使用。
-
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_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
描述
如果 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_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
描述
如果自发 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)¶
停止所有队列
-
void ieee80211_wake_queues(struct ieee80211_hw *hw)¶
唤醒所有队列
帧过滤¶
mac80211 需要看到许多管理帧才能正常运行,并且当处于监视模式时,用户可能希望看到更多帧。但是,为了获得最佳的 CPU 使用率和功耗,最好让尽可能少的帧通过堆栈。因此,硬件应尽可能多地进行过滤。
为了实现这一点,mac80211 使用过滤器标志(见下文)来告知驱动程序的 configure_filter() 函数哪些帧应传递给 mac80211,哪些帧应过滤掉。
在调用 configure_filter() 之前,将使用参数 mc_count 和 mc_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 工作队列。