STRUCT IEEE80211_OPS(9)
π struct ieee80211_ops
okay so bestie, buckle up β this one's straight out of the Kernel API Manual, section 9 (yes, section 9, the kernel-interfaces girlies, iykyk β¨). It's a big one, so we're doing it in parts and you're gonna understand it, fr fr.
β¨ NAME β¨
struct ieee80211_ops β the callback squad that mac80211 rings up when it needs your driver to do something π
like, think of it as the contact list mac80211 keeps on speed dial. when mac80211 (the kernel's 802.11 wireless stack) has stuff to hand off, it doesn't just barge into your driver β it calls the callbacks you registered in this struct. mac80211 β driver, that's the direction, no cap π«Ά
callbacks from mac80211 to the driver β that's the whole vibe check right there.
part 1 done, bestie β more coming, don't go anywhere π
β¨ SYNOPSIS β¨
okay bestie, here's the whole struct ieee80211_ops in all its main-character glory π«Ά every single function pointer, every #ifdef, every lil parameter β no skips, fr fr. it's giving "phone book but make it wifi" π
we'll unpack what each one actually does later, but first the vibe check:
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, int radio_idx, 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, int radio_idx,
u32 value);
int (*set_rts_threshold)(struct ieee80211_hw *hw, int radio_idx, 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);
void (*link_sta_statistics)(struct ieee80211_hw *hw, struct
ieee80211_vif *vif, struct ieee80211_link_sta *link_sta, struct
link_station_info *link_sinfo);
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, int radio_idx,
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, int radio_idx, u32
tx_ant, u32 rx_ant);
int (*get_antenna)(struct ieee80211_hw *hw, int radio_idx, 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);
int (*nan_peer_sched_changed)(struct ieee80211_hw *hw, struct
ieee80211_sta *sta);
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);
int (*set_eml_op_mode)(struct ieee80211_hw *hw, struct ieee80211_vif
*vif, struct ieee80211_sta *sta, struct ieee80211_eml_params
*eml_params);
};
π MEMBERS π
okay bestie, this is the part where we go through the whole roster, one callback at a time. grab a snack π
π«Ά tx
Handler that 802.11 module calls for each transmitted frame. skb contains the buffer starting from the IEEE 802.11 header. The low-level driver should send the frame out based on configuration in the TX control data. This handler should, preferably, never fail and stop queues appropriately. Must be atomic.
no cap β this one's on the hot path. it's giving "don't block, don't sleep, just yeet."
π± start
Called before the first netdevice attached to the hardware is enabled. This should turn on the hardware and must turn on frame reception (for possibly enabled monitor interfaces.) Returns negative error codes β these may be seen in userspace β or zero. When the device is started it should not have a MAC address, to avoid acknowledging frames before a non-monitor device is added. Must be implemented and can sleep.
π stop
Called after the last netdevice attached to the hardware is disabled. This should turn off the hardware (at least it must turn off frame reception.) May be called right after add_interface if that rejects an interface. If you added any work onto the mac80211 workqueue you should ensure to cancel it on this callback. Must be implemented and can sleep.
π΄ suspend
Suspend the device; mac80211 itself will quiesce before and stop transmitting and doing any other configuration, and then ask the device to suspend. This is only invoked when WoWLAN is configured β otherwise the device is deconfigured completely and reconfigured at resume time. The driver may also impose special conditions under which it wants to use the "normal" suspend (deconfigure), say if it only supports WoWLAN when the device is associated. In this case, it must return 1 from this function.
π
resume
If WoWLAN was configured, this indicates that mac80211 is now resuming its operation, and after this the device must be fully functional again. If this returns an error, the only way out is to also unregister the device. If it returns 1, then mac80211 will also go through the regular complete restart on resume.
β° set_wakeup
Enable or disable wakeup when WoWLAN configuration is modified. The reason is that device_set_wakeup_enable is supposed to be called when the configuration changes, not only in suspend.
π§ add_interface
Called when a netdevice attached to the hardware is enabled. Because it is not called for monitor mode devices, start and stop must be implemented. The driver should perform any initialization it needs before the device can be enabled. The initial configuration for the interface is given in the conf parameter. The callback may refuse to add an interface by returning a negative error code (which will be seen in userspace.) Must be implemented and can sleep.
π¦ change_interface
Called when a netdevice changes type. This callback is optional β but only if it is supported can interface types be switched while the interface is UP. The callback can sleep. Note that while an interface is being switched, it will not be found by the interface iteration callbacks.
π
remove_interface
Notifies a driver that an interface is going down. The stop callback is called after this if it is the last interface and no monitor interfaces are present. When all interfaces are removed, the MAC address in the hardware must be cleared so the device no longer acknowledges packets β the mac_addr member of the conf structure is, however, set to the MAC address of the device going away. Hence, this callback must be implemented. It can sleep.
βοΈ config
Handler for configuration requests. IEEE 802.11 code calls this function to change hardware configuration, e.g., channel. This function should never fail but returns a negative error code if it does. The callback can sleep.
πΈ bss_info_changed
Handler for configuration requests related to BSS parameters that may vary during a BSS's lifespan, and may affect the low level driver (e.g. assoc/disassoc status, erp parameters). This function should not be used if no BSS has been set, unless for association indication. The changed parameter indicates which of the BSS parameters has changed when a call is made. The callback can sleep.
π vif_cfg_changed
Handler for configuration requests related to interface (MLD) parameters from struct ieee80211_vif_cfg that vary during the lifetime of the interface (e.g. assoc status, IP addresses, etc.) The changed parameter indicates which value changed. The callback can sleep.
π link_info_changed
Handler for configuration requests related to link parameters from struct ieee80211_bss_conf that are related to an individual link, e.g. legacy/HT/VHT/... rate information. The changed parameter indicates which value changed, and the link_id parameter indicates the link ID. Note that link_id will be 0 for non-MLO connections. The callback can sleep.
π start_ap
Start operation on the AP interface β this is called after all the information in bss_conf is set and beacon can be retrieved. A channel context is bound before this is called. Note that if the driver uses software scan or ROC, this (and stop_ap) isn't called when the AP is just "paused" for scanning/ROC, which is indicated by the beacon being disabled/enabled via bss_info_changed.
πͺ stop_ap
Stop operation on the AP interface.
π prepare_multicast
Prepare for multicast filter configuration. This callback is optional, and its return value is passed to configure_filter. This callback must be atomic.
π configure_filter
Configure the device's RX filter. See the section "Frame filtering" for more information. This callback must be implemented and can sleep.
π§Ό config_iface_filter
Configure the interface's RX filter. This callback is optional and is used to configure which frames should be passed to mac80211. The filter_flags is the combination of FIF_* flags. The changed_flags is a bit mask that indicates which flags are changed. This callback can sleep.
set_timβ sets the TIM bit β¨ mac80211 hits this up whenever a TIM bit needs to be set or cleared for a given STA. Must be atomic.set_keyβ go read the "Hardware crypto acceleration" section, bestie, that's where the lore lives π this callback only ever gets called betweenadd_interfaceandremove_interfacecalls, i.e. while the given virtual interface is enabled. Returns a negative error code if the key can't be added. The callback can sleep. π΄update_tkip_keyβ again, see "Hardware crypto acceleration" π this one gets called in the context of Rx. It's for drivers which setIEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. The callback must be atomic.set_rekey_dataβ if the device supports GTK rekeying (say, while the host is suspended π΄), it can assign this callback to retrieve the data necessary to do GTK rekeying β that's the KEK, KCK and replay counter, the whole trio π after rekeying was done it should (for example during resume) notify userspace of the new replay counter usingieee80211_gtk_rekey_notify.set_default_unicast_keyβ sets the default (unicast) key index, which is useful for WEP when the device sends data packets autonomously, e.g. for ARP offloading. The index can be0-3, or-1for unsetting it πhw_scanβ asks the hardware to service the scan request, no need to start the scan state machine in stack π the scan must honour the channel configuration done by the regulatory agent in the wiphy's registered bands. The hardware (or the driver) needs to make sure that power save is disabled. Thereqie/ie_lenmembers are rewritten by mac80211 to contain the entire IEs after the SSID, so that drivers need not look at these at all but just send them after the SSID β mac80211 includes the (extended) supported rates and HT information (where applicable). When the scan finishes,ieee80211_scan_completedmust be called; note that it also must be called when the scan cannot finish due to any error unless this callback returned a negative error code. This callback is also allowed to return the special return value1, which indicates that hardware scan isn't desirable right now and a software scan should be done instead π a driver wishing to use this capability must ensure its (hardware) scan capabilities aren't advertised as more capable than mac80211's software scan is. The callback can sleep.cancel_hw_scanβ asks the low-level tp cancel the active hw scan (yes,tp, that's literally what it says, we don't edit the source around here π). The driver should ask the hardware to cancel the scan (if possible), but the scan will be completed only after the driver will callieee80211_scan_completed. This callback is needed for wowlan, to prevent enqueueing a newscan_workafter the low-level driver was already suspended. The callback can sleep.sched_scan_startβ asks the hardware to start scanning repeatedly at specific intervals β° the driver must call theieee80211_sched_scan_resultsfunction whenever it finds results. This process will continue untilsched_scan_stopis called.sched_scan_stopβ tells the hardware to stop an ongoing scheduled scan π in this case,ieee80211_sched_scan_stoppedmust not be called.sw_scan_startβ notifier function that's called just before a software scan is started. Can beNULL, if the driver doesn't need this notification. Themac_addrparameter allows supportingNL80211_SCAN_FLAG_RANDOM_ADDR, and the driver may set theNL80211_FEATURE_SCAN_RANDOM_MAC_ADDRflag if it can use this parameter. The callback can sleep. π¦sw_scan_completeβ notifier function that's called just after a software scan finished. Can beNULL, if the driver doesn't need this notification. The callback can sleep.get_statsβ returns low-level statistics π returns zero if statistics are available. The callback can sleep.get_key_seqβ if your device implements encryption in hardware and does IV/PN assignment then this callback should be provided to read the IV/PN for the given key from hardware π The callback must be atomic.set_frag_thresholdβ configuration of fragmentation threshold. Assign this if the device does fragmentation by itself. Note that to prevent the stack from doing fragmentation,IEEE80211_HW_SUPPORTS_TX_FRAGshould be set as well. The callback can sleep.set_rts_thresholdβ configuration of RTS threshold (if device needs it). The callback can sleep.sta_addβ notifies the low level driver about the addition of an associated station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.sta_removeβ notifies the low level driver about the removal of an associated station, AP, IBSS/WDS/mesh peer etc. β οΈ note that after the callback returns it isn't safe to use the pointer, not even RCU protected; no RCU grace period is guaranteed between returning here and freeing the station. Seesta_pre_rcu_removeif needed. This callback can sleep.vif_add_debugfsβ drivers can use this callback to add a debugfs vif directory with its files ποΈ this callback should be within aCONFIG_MAC80211_DEBUGFSconditional. This callback can sleep.link_add_debugfsβ drivers can use this callback to add debugfs files when a link is added to a mac80211 vif. This callback should be within aCONFIG_MAC80211_DEBUGFSconditional. This callback can sleep. For non-MLO the callback will be called once for the defaultbss_confwith the vif's directory rather than a separate subdirectory.sta_add_debugfsβ drivers can use this callback to add debugfs files when a station is added to mac80211's station list. This callback should be within aCONFIG_MAC80211_DEBUGFSconditional. This callback can sleep.link_sta_add_debugfsβ drivers can use this callback to add debugfs files when a link is added to a mac80211 station. This callback should be within aCONFIG_MAC80211_DEBUGFSconditional. This callback can sleep. For non-MLO the callback will be called once for thedeflinkwith the station's directory rather than a separate subdirectory.sta_notifyβ notifies the low level driver about a power state transition of an associated station, AP, IBSS/WDS/mesh peer etc. β‘ for a VIF operating in AP mode, this callback will not be called when the flagIEEE80211_HW_AP_LINK_PSis set. Must be atomic.sta_set_txpwrβ configure the station tx power. This callback set the tx power for the station. This callback can sleep.sta_stateβ notifies the low level driver about a state transition of a station (which can be the AP, a client, IBSS/WDS/mesh peer etc.) π this callback is mutually exclusive withsta_add/sta_remove. It must not fail for down transitions but may fail for transitions up the list of states. Also note that after the callback returns it isn't safe to use the pointer, not even RCU protected β no RCU grace period is guaranteed between returning here and freeing the station. Seesta_pre_rcu_removeif needed. The callback can sleep.sta_pre_rcu_removeβ notify the driver about station removal before RCU synchronisation. This is useful if a driver needs to have station pointers protected using RCU β it can then use this call to clear the pointers instead of waiting for an RCU grace period to elapse insta_stateπΈ The callback can sleep.link_sta_rc_updateβ notifies the driver of changes to the bitrates that can be used to transmit to the station. The changes are advertised with bits fromenum ieee80211_rate_control_changedand the values are reflected in the station data. This callback should only be used when the driver uses hardware rate control (IEEE80211_HW_HAS_RATE_CONTROL) since otherwise the rate control algorithm is notified directly. Must be atomic.sta_rate_tbl_updateβ notifies the driver that the rate table changed π this is only used if the configured rate control algorithm actually uses the new rate table API, and is therefore optional. Must be atomic.sta_statisticsβ get statistics for this station. For example with beacon filtering, the statistics kept by mac80211 might not be accurate, so let the driver pre-fill the statistics. The driver can fill most of the values (indicating which by setting thefilledbitmap), but not all of them make sense β see the source for which ones are possible π statistics that the driver doesn't fill will be filled by mac80211. The callback can sleep.conf_txβ configure TX queue parameters (EDCF (aifs,cw_min,cw_max), bursting) for a hardware TX queue. Returns a negative error code on failure. The callback can sleep.get_tsfβ get the current TSF timer value from firmware/hardware β±οΈ currently, this is only used for IBSS mode BSSID merging and debugging. Is not a required function. The callback can sleep.set_tsfβ set the TSF timer to the specified value in the firmware/hardware. Currently, this is only used for IBSS mode debugging. Is not a required function. The callback can sleep.offset_tsfβ offset the TSF timer by the specified value in the firmware/hardware. Preferred toset_tsfas it avoids delay between callingset_tsfand hardware getting programmed, which will show up as TSF delay β¨ is not a required function. The callback can sleep.reset_tsfβ Reset the TSF timer and let the firmware/hardware re-sync with the other STAs in the IBSS. IBSS mode only, bestie π . This one's optional if your firmware/hardware is a total main character and handles TSF synchronization all by itself. The callback can sleep π΄.tx_last_beaconβ Basically asking "was that last IBSS beacon mine?" π Only needed for IBSS mode, and the result gets used to decide whether to reply to Probe Requests. Returns non-zero if this device sent the last beacon. The callback can sleep.link_sta_statisticsβ Get link statistics for this station β¨. Like, with beacon filtering, the stats mac80211 keeps might not be accurate, so let the driver pre-fill them. The driver can fill most of the values (and it signals which ones by setting the filled bitmap), but not all of them even make sense β see the source for which ones are possible, iykyk. Whatever the driver doesn't fill, mac80211 fills in for you π«Ά. The callback can sleep.ampdu_actionβ Perform a certain A-MPDU action π₯. The RA/TID combo is what decides the destination and the TID we want the ampdu action performed for. The action itself is defined throughieee80211_ampdu_mlme_action. When the action is set toIEEE80211_AMPDU_TX_OPERATIONAL, the driver may neither send aggregates containing more subframes thanbuf_sizenor send aggregates in a way that lost frames would exceed the buffer size. If you're just limiting the aggregate size, this would lowkey be possible with abuf_sizeof 8:
TX: 1.....7
RX: 2....7 (lost frame #1)
TX: 8..1...
which is invalid since #1 was now re-transmitted well past the buffer size of 8 π. Correct ways to retransmit #1 would be:
TX: 1 or
TX: 18 or
TX: 81
Even 189 would be wrong since 1 could be lost again π.
Returns a negative error code on failure. The driver may return IEEE80211_AMPDU_TX_START_IMMEDIATE for IEEE80211_AMPDU_TX_START if the session can start immediately β‘.
The callback can sleep.
get_surveyβ Return per-channel survey information πΈ.rfkill_pollβ Poll rfkill hardware state. If you need this one, you also need to setwiphy->rfkill_pollto true before registration, and you need to callwiphy_rfkill_set_hw_statein the callback π. The callback can sleep.set_coverage_classβ Set the slot time for a given coverage class as specified in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout accordingly; coverage class equals to-1to enable the ACK timeout estimation algorithm (dynack) β¨. To disable dynack, set a valid value for coverage class. This callback is not required and may sleep π΄.testmode_cmdβ Implement a cfg80211 test mode command. The passed vif may beNULL. The callback can sleep.testmode_dumpβ Implement a cfg80211 test mode dump. The callback can sleep.flushβ Flush all pending frames from the hardware queue, making sure the hardware queues are actually empty π§Ήβ¨. Thequeuesparameter is a bitmap of queues to flush, which is super useful if different virtual interfaces use different hardware queues; it may also indicate all queues. If the parameterdropis set to true, pending frames may be dropped π. Note thatvifcan beNULL. The callback can sleep.flush_staβ Flush or drop all pending frames from the hardware queue(s) for the given station, since it's about to be removed π«Ά. The callback can sleep.channel_switchβ Drivers that need (or want) to offload the channel switch operation for CSAs received from the AP may implement this callback π . They must then callieee80211_chswitch_doneto indicate completion of the channel switch, no cap.set_antennaβ Set the antenna configuration (tx_ant,rx_ant) on the device π‘. The parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may reject TX/RX mask combinations they cannot support by returning-EINVAL(also seenl80211.hNL80211_ATTR_WIPHY_ANTENNA_TX).get_antennaβ Get the current antenna configuration from the device (tx_ant,rx_ant) π.remain_on_channelβ Starts an off-channel period on the given channel, and you must call back toieee80211_ready_on_channelwhen you're actually on that channel β°. Note that normal channel traffic is not stopped, since this is intended for hw offload. Frames to transmit on the off-channel channel are transmitted normally, except for theIEEE80211_TX_CTL_TX_OFFCHANflag. When the duration (which will always be non-zero) expires, the driver must callieee80211_remain_on_channel_expiredπ. Note that this callback may be called while the device is in IDLE and must be accepted in this case, fr fr. This callback may sleep.cancel_remain_on_channelβ Requests that an ongoing off-channel period is aborted before it expires π. This callback may sleep.set_ringparamβ Set tx and rx ring sizes π§.get_ringparamβ Get tx and rx ring current and maximum sizes π.tx_frames_pendingβ Check if there's any pending frame in the hardware queues before entering power save π€.set_bitrate_maskβ Set a mask of rates to be used for rate control selection when transmitting a frame π. Currently only legacy rates are handled, ngl. The callback can sleep.event_callbackβ Notify the driver about any event in mac80211. Seeenum ieee80211_event_typefor the different types π. The callback must be atomic β‘.allow_buffered_framesβ Prepare the device to allow the given number of frames to go out to the given station π. The frames will be sent by mac80211 via the usual TX path after this call. The TX information for frames released will also have theIEEE80211_TX_CTL_NO_PS_BUFFERflag set, and the last one will also haveIEEE80211_TX_STATUS_EOSPset. In case frames from multiple TIDs are released and the driver might reorder them between the TIDs, it must set theIEEE80211_TX_STATUS_EOSPflag on the last frame and clear it on all others, and also handle the EOSP bit in the QoS header correctly π. Alternatively, it can also call theieee80211_sta_eospfunction. Thetidsparameter is a bitmap and tells the driver which TIDs the frames will be on; it will at most have two bits set. This callback must be atomic β‘.release_buffered_framesβ Release buffered frames according to the given parameters π. In the case where the driver buffers some frames for sleeping stations, mac80211 will use this callback to tell the driver to release some frames, either for PS-poll or uAPSD. Note that if themore_dataparameter is false, the driver must check if there are more frames on the given TIDs, and if there are more than the frames being released, then it must still set the more-data bit in the frame π. If themore_dataparameter is true, then of course the more-data bit must always be set. Thetidsparameter tells the driver which TIDs to release frames from; for PS-poll it will always have only a single bit set. In the case this is used for a PS-poll initiated release, thenum_framesparameter will always be1so code can be shared π€. In this case the driver must also set theIEEE80211_TX_STATUS_EOSPflag on the TX status (and must report TX status) so that the PS-poll period is properly ended β this is used to avoid sending multiple responses for a retried PS-poll frame. In the case this is used for uAPSD, thenum_framesparameter may be bigger than one, but the driver may send fewer frames (it must send at least one, however π€). In this case it is also responsible for setting the EOSP flag in the QoS header of the frames. Also, when the service period ends, the driver must setIEEE80211_TX_STATUS_EOSPon the last frame in the SP. Alternatively, it may call the functionieee80211_sta_eospto inform mac80211 of the end of the SP. This callback must be atomic β‘.get_et_sset_countβ Ethtool API to get string-set count π’. Note that the wiphy mutex is not held for this callback, since it's expected to return a static value.get_et_statsβ Ethtool API to get a set of u64 stats π.get_et_stringsβ Ethtool API to get a set of strings to describe stats and perhaps other supported types of ethtool data-sets π. Note that the wiphy mutex is not held for this callback, since it's expected to return a static value.mgd_prepare_txβ Prepare for transmitting a management frame for association before you're associated π«Ά. In multi-channel scenarios, a virtual interface is bound to a channel before it's associated, but since it isn't associated yet it need not necessarily be given airtime β especially since any transmission to a P2P GO needs to be synchronized against the GO's powersave state π΄. mac80211 will call this function before transmitting a management frame, prior to transmitting that frame, to allow the driver to give it channel time for the transmission, to get a response, and to be able to synchronize with the GO β¨. The callback will be called before each transmission, and upon return mac80211 will transmit the frame right away β‘. Additional information is passed in thestruct ieee80211_prep_tx_infodata. Ifdurationthere is greater than zero, mac80211 hints to the driver the duration for which the operation is requested. The callback is optional and can (should!) sleep π΄π.
mgd_complete_tx
Okay so this one's the "we heard back!!" callback π It tells the driver that the response frame for a frame it already sent β the one it announced with mgd_prepare_tx β actually arrived. The data gets filled in pretty much the same way as mgd_prepare_tx, except the duration isn't used here. One lil caveat though: this isn't always called for every single mgd_prepare_tx call β for example with SAE, the 'confirm' messages can be on the air in any order, so like, don't count on a perfect one-to-one match, bestie π«Ά
mgd_protect_tdls_discover
Protects a TDLS discovery session β¨ So after we send a TDLS discovery-request, we expect a reply to arrive on the AP's channel, right? Which means we have to stay on that channel β no PSM, no scan, no nothing β because a TDLS setup-response is a direct packet that isn't buffered by the AP. mac80211 will call this function just before the transmission of a TDLS discovery-request. The recommended protection period is at least 2 * (DTIM period). This callback is optional and it can sleep π΄
add_chanctx
Notifies the device driver that a new channel context got created π This callback may sleep.
remove_chanctx
Notifies the device driver that a channel context is being destroyed π«§ This callback may sleep.
change_chanctx
Notifies the device driver about channel context changes β the kind that can happen when you combine different virtual interfaces on the same channel context with different settings. This callback may sleep π€
assign_vif_chanctx
Notifies the device driver that a channel context is being bound to a vif. Possible use case? hw queue remapping π This callback may sleep.
unassign_vif_chanctx
Notifies the device driver that a channel context is being unbound from a vif. This callback may sleep.
switch_vif_chanctx
Switches a number of vifs from one chanctx to another, exactly as specified in the list of ieee80211_vif_chanctx_switch passed to the driver, according to the mode defined in ieee80211_chanctx_switch_mode π This callback may sleep.
reconfig_complete
Called after a call to ieee80211_restart_hw and during resume, when the reconfiguration has completed β¨ This can help the driver implement the reconfiguration step (and indicate that mac80211 is ready to receive frames). This callback may sleep.
ipv6_addr_change
The IPv6 address assignment on the given interface changed πΈ Currently this is only called for managed or P2P client interfaces. This callback is optional β and it must not sleep β οΈ
channel_switch_beacon
Starts a channel switch to a new channel π¦ Beacons get modified to include CSA or ECSA IEs before this function is called. The corresponding count fields in these IEs must be decremented, and when they reach 1 the driver must call ieee80211_csa_finish. Drivers which use ieee80211_beacon_get get the csa counter decremented by mac80211, but they must check if it is 1 using ieee80211_beacon_counter_is_complete after the beacon has been transmitted, and then call ieee80211_csa_finish. And if the CSA count starts as zero or 1? This function won't be called at all, since there won't be any time to beacon before the switch anyway π
pre_channel_switch
This is an optional callback that gets called before a channel switch procedure is started (ie. when a STA gets a CSA, or a userspace initiated channel-switch), so the driver can prepare for the channel switch π
post_channel_switch
Optional callback, called after a channel switch procedure is completed β lets the driver go back to a normal configuration π
abort_channel_switch
Optional callback, called when a channel switch procedure was aborted β lets the driver go back to a normal configuration. Love a clean exit π
channel_switch_rx_beacon
Optional callback, called when a channel switch procedure is in progress and an additional beacon with a CSA IE was received π¦ Lets the driver track changes in the count.
join_ibss
Join an IBSS (on an IBSS interface) π«Ά This is called after all the information in bss_conf is set up and the beacon can be retrieved. A channel context is bound before this is called.
leave_ibss
Leave the IBSS again. Bye bestie π
get_expected_throughput
Extracts the expected throughput towards the specified station. The returned value is expressed in Kbps. It returns 0 if the RC algorithm doesn't have proper data to provide π
get_txpower
Get the current maximum tx power (in dBm) based on configuration and hardware limits β‘
tdls_channel_switch
Start channel-switching with a TDLS peer π« The driver is responsible for continually initiating channel-switching operations and returning to the base channel for communication with the AP. The driver receives a channel-switch request template and the location of the switch-timing IE within the template as part of the invocation. Heads up: the template is valid only within the call, and the driver can optionally copy the skb for further re-use.
tdls_cancel_channel_switch
Stop channel-switching with a TDLS peer π Both peers must be on the base channel when the call completes.
tdls_recv_channel_switch
A TDLS channel-switch related frame (request or response) has been received from a remote peer β¨ The driver gets parameters parsed from the incoming frame and may use them to continue an ongoing channel-switch operation. In addition, a channel-switch response template is provided, together with the location of the switch-timing IE within the template. The skb can only be used within the function call. No holding onto it, bestie π
wake_tx_queue
Called when new packets have been added to the queue π¨
sync_rx_queues
Process all pending frames in RSS queues π This is a synchronization which is needed in case the driver has, in its RSS queues, pending frames that were received prior to the control path action currently taken (e.g. disassociation) but are not processed yet.
start_nan
Join an existing NAN cluster, or create a new one πΈ
stop_nan
Leave the NAN cluster π«§
nan_change_conf
Change NAN configuration β¨ The data in cfg80211_nan_conf contains the full new configuration, and changes specify which parameters are changed with respect to the last NAN config. The driver gets both the full configuration and the changed parameters, since some devices may need the full configuration while others need only the changed parameters.
add_nan_func
Add a NAN function. Returns 0 on success π The data in cfg80211_nan_func must not be referenced outside the scope of this call.
del_nan_func
Remove a NAN function. The driver must call ieee80211_nan_func_terminated with the NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal π
nan_peer_sched_changed
Notifies the driver that the peer NAN schedule has changed π« The new schedule is available via sta->nan_sched. Note that the channel_entry blob might not match the actual chandef, since the bandwidth of the chandef is the minimum of the local and peer bandwidth. And it's the driver's responsibility to remove the peer schedule when the NMI station is removed π«Ά
can_aggregate_in_amsdu
Called in order to determine if the HW supports aggregating two specific frames in the same A-MSDU. The relation between the skbs should be symmetric and transitive π§ Note that while skb is always a real frame, head may or may not be an A-MSDU π
get_ftm_responder_stats
Retrieve FTM responder statistics, if available π Statistics should be cumulative β currently no way to reset is provided.
start_pmsr
Start peer measurement (e.g. FTM) π (this call can sleep)
abort_pmsr
Abort peer measurement π (this call can sleep)
set_tid_config
Apply TID specific configurations. This callback may sleep π΄
reset_tid_config
Reset TID specific configuration for the peer. This callback may sleep.
update_vif_offload
Update virtual interface offload flags π¦ This callback may sleep.
sta_set_4addr
Called to notify the driver when a station starts/stops using 4-address mode β¨
set_sar_specs
Update the SAR (TX power) settings β‘
sta_set_decap_offload
Called to notify the driver when a station is allowed to use rx decapsulation offload π
add_twt_setup
Update the hw with TWT agreement parameters received from the peer π« This callback allows the hw to check if the requested parameters are supported and if there's enough room for a new agreement. The hw is expected to set the agreement result in the req_type field of the twt structure π
twt_teardown_request
Update the hw with the TWT teardown request received from the peer π«§
set_radar_background
Configure a dedicated offchannel chain available for radar/CAC detection on some hw π This chain can't be used to transmit or receive frames, and it is bounded to a running wdev. Background radar/CAC detection allows you to avoid the CAC downtime switching to a different channel during CAC detection on the selected radar channel. The caller is expected to set the chandef pointer to NULL in order to disable background CAC/radar detection β οΈ
net_fill_forward_path
Called from .ndo_fill_forward_path in order to resolve a path for hardware flow offloading π£οΈ
can_activate_links
Checks if a specific active_links bitmap is supported by the driver β
change_vif_links
okay so this one changes the valid links on an interface β¨ and there's a lil warning bestie β while you're removing the old link, the old info is still valid (that link_conf pointer is still pointing at something real, promise), but it may immediately disappear right after the function returns π so don't get attached. the old or new links bitmaps can totally be 0 if you're going from a non-MLO situation to a non-MLO situation (or vice versa, iykyk). the old array has pointers to the old bss_conf structures that were already removed, just in case you need them π«Ά. also note that removal of a link should always succeed, so the return value gets ignored in a removal-only case (not me ignoring a return value π). and yes, this callback can sleep π΄.
change_sta_links
changes the valid links of a station β basically the same vibe as change_vif_links above π―. this callback can sleep too π€. heads up though: a sta can also be inserted or removed with valid links, like being passed to sta_add/sta_state with sta->valid_links not zero. in fact, you cannot change from having valid_links to not having them β that's just not a thing π«. no cap.
set_hw_timestamp
enable/disable HW timestamping of TM/FTM frames β±οΈβ¨. lowkey important: this is not restored at HW reset by mac80211, so drivers gotta take care of that themselves, bestie β mac80211 is not your mom π .
net_setup_tc
called from .ndo_setup_tc in order to prepare hardware flow offloading for flows originating from the vif π. but listen β the driver must not assume that the vif driver_data is valid at this point, because the callback can be called during netdev teardown π¬. like, mid-teardown, things are messy, don't touch stuff and assume it's fine.
can_neg_ttlm
for a managed interface, this asks the driver to figure out whether the requested TID-To-Link mapping can be accepted or not π€. if it's not accepted, the driver may suggest a preferred mapping and modify the ttlm parameter with that suggested TID-To-Link mapping. so thoughtful of it π.
prep_add_interface
prepare for interface addition π¬. drivers can use this to get ready for a new interface showing up β like allocating the needed resources etc. etc. but!! this callback doesn't guarantee that an interface with the specified type would actually be added, so if you implement this you gotta handle those cases π. the type is the full enum nl80211_iftype, for the record.
set_eml_op_mode
configure eMLSR/eMLMR operation mode in the underlay driver, according to the parameter received in the EML Operating mode notification frame π‘π. that's it, that's the vibe.
π Description π
so what is this structure, you ask? bestie. it contains various callbacks that the driver may handle, or β in some cases β must handle π«‘. like, for example, to configure the hardware to a new channel, or to transmit a frame. that's the whole entire point, periodt.
π Note π
this callback is called ifvif_cfg_changedorlink_info_changedare not implemented π β so like, if you didn't implement those, this is your fallback bestie.
π«Ά SEE ALSO
okay bestie, this is the part where the page hits you with the entire extended cinematic universe. every struct, every enum, every helper that lives in the same header β all invited to the group chat. lowkey iconic, highkey a lot. we're doing it though, no skips, no shortcuts.
first up, the mothership itself β the kernel file ./include/net/mac80211.h β and the big-picture intro pages you should read before you touch anything: Introduction(9), Calling mac80211 from interrupts(9), Warning(9), Frame format(9), mac80211 workqueue(9), mac80211 software tx queueing(9), HW timestamping(9), enum ieee80211_max_queues(9), enum ieee80211_ac_numbers(9), struct ieee80211_tx_queue_params(9), enum ieee80211_chanctx_change(9), struct ieee80211_chan_req(9), struct ieee80211_chanctx_conf(9), enum ieee80211_chanctx_switch_mode(9), struct ieee80211_vif_chanctx_switch(9), enum ieee80211_bss_change(9), enum ieee80211_event_type(9), enum ieee80211_rssi_event_data(9), struct ieee80211_rssi_event(9), enum ieee80211_mlme_event_data(9), enum ieee80211_mlme_event_status(9), struct ieee80211_mlme_event(9), struct ieee80211_ba_event(9), struct ieee80211_event(9), struct ieee80211_mu_group_data(9), struct ieee80211_ftm_responder_params(9), struct ieee80211_fils_discovery(9), struct ieee80211_parsed_tpe(9), struct ieee80211_bss_npca_params(9), struct ieee80211_bss_conf(9).
still with me? π«Ά good, because it keeps going:
struct ieee80211_nan_channel(9), struct ieee80211_nan_peer_map(9), struct ieee80211_nan_peer_sched(9), enum mac80211_tx_info_flags(9), enum mac80211_tx_control_flags(9), enum mac80211_tx_status_flags(9), enum mac80211_rate_control_flags(9), struct ieee80211_tx_rate(9), struct ieee80211_tx_info(9), struct ieee80211_tx_status(9), struct ieee80211_scan_ies(9), ieee80211_tx_info_clear_status(9), enum mac80211_rx_flags(9), enum mac80211_rx_encoding_flags(9), struct ieee80211_rx_status(9), enum ieee80211_conf_flags(9), enum ieee80211_conf_changed(9), enum ieee80211_smps_mode(9), struct ieee80211_conf(9), struct ieee80211_channel_switch(9), enum ieee80211_vif_flags(9), enum ieee80211_offload_flags(9), struct ieee80211_eml_params(9), struct ieee80211_nan_sched_cfg(9), struct ieee80211_vif_cfg(9), struct ieee80211_neg_ttlm(9), enum ieee80211_neg_ttlm_res(9), struct ieee80211_vif(9).
the vif saga continues, and then we get into keys and stations (the drama):
ieee80211_vif_usable_links(9), ieee80211_vif_is_mld(9), ieee80211_vif_link_active(9), wdev_to_ieee80211_vif(9), ieee80211_vif_to_wdev(9), enum ieee80211_key_flags(9), struct ieee80211_key_conf(9), struct ieee80211_key_seq(9), enum set_key_cmd(9), enum ieee80211_sta_state(9), enum ieee80211_sta_rx_bandwidth(9), struct ieee80211_sta_rates(9), struct ieee80211_sta_txpwr(9), struct ieee80211_sta_aggregates(9), struct ieee80211_link_sta(9), struct ieee80211_sta(9), enum sta_notify_cmd(9), struct ieee80211_tx_control(9), struct ieee80211_txq(9), enum ieee80211_hw_flags(9), struct ieee80211_hw(9), struct ieee80211_scan_request(9), struct ieee80211_tdls_ch_sw_params(9), wiphy_to_ieee80211_hw(9), SET_IEEE80211_DEV(9), SET_IEEE80211_PERM_ADDR(9), ieee80211_free_txskb(9), ieee80211_purge_tx_queue(9).
then the β¨conceptβ¨ pages β yes they're actual page titles, capital letters and all, we do not abbreviate:
Hardware crypto acceleration(9), Powersave support(9), Beacon filter support(9), Spatial multiplexing power save(9), Frame filtering(9), AP support for powersaving clients(9), HW queue control(9), enum ieee80211_filter_flags(9), enum ieee80211_ampdu_mlme_action(9), struct ieee80211_ampdu_params(9), enum ieee80211_frame_release_type(9), enum ieee80211_rate_control_changed(9), enum ieee80211_roc_type(9), enum ieee80211_reconfig_type(9), struct ieee80211_prep_tx_info(9), ieee80211_alloc_hw_nm(9), ieee80211_alloc_hw(9), ieee80211_register_hw(9), struct ieee80211_tpt_blink(9), enum ieee80211_tpt_led_trigger_flags(9), ieee80211_get_tx_led_name(9), ieee80211_get_rx_led_name(9), ieee80211_get_assoc_led_name(9), ieee80211_get_radio_led_name(9), ieee80211_create_tpt_led_trigger(9), ieee80211_unregister_hw(9), ieee80211_free_hw(9), ieee80211_restart_hw(9).
rx/tx path besties, assemble π:
ieee80211_rx_list(9), ieee80211_rx_napi(9), ieee80211_rx(9), ieee80211_rx_irqsafe(9), ieee80211_rx_ni(9), ieee80211_sta_ps_transition(9), ieee80211_sta_ps_transition_ni(9), ieee80211_sta_pspoll(9), ieee80211_sta_uapsd_trigger(9), ieee80211_sta_set_buffered(9), ieee80211_get_tx_rates(9), ieee80211_tx_rate_update(9), ieee80211_tx_status_skb(9), ieee80211_tx_status_ext(9), ieee80211_tx_status_noskb(9), ieee80211_tx_status_ni(9), ieee80211_tx_status_irqsafe(9), ieee80211_report_low_ack(9), struct ieee80211_mutable_offsets(9), ieee80211_beacon_get_template(9), ieee80211_beacon_get_template_ema_index(9), struct ieee80211_ema_beacons(9), ieee80211_beacon_get_template_ema_list(9), ieee80211_beacon_free_ema_list(9), ieee80211_beacon_get_tim(9), ieee80211_beacon_get(9), ieee80211_beacon_update_cntdwn(9), ieee80211_beacon_set_cntdwn(9).
beacon era continues, then frames, then TKIP (throwback π), then keys again:
ieee80211_csa_finish(9), ieee80211_beacon_cntdwn_is_complete(9), ieee80211_color_change_finish(9), ieee80211_proberesp_get(9), ieee80211_pspoll_get(9), ieee80211_nullfunc_get(9), ieee80211_probereq_get(9), ieee80211_rts_get(9), ieee80211_rts_duration(9), ieee80211_ctstoself_get(9), ieee80211_ctstoself_duration(9), ieee80211_generic_frame_duration(9), ieee80211_get_buffered_bc(9), ieee80211_get_tkip_p1k_iv(9), ieee80211_get_tkip_p1k(9), ieee80211_get_tkip_rx_p1k(9), ieee80211_get_tkip_p2k(9), ieee80211_tkip_add_iv(9), ieee80211_get_key_rx_seq(9), ieee80211_set_key_rx_seq(9), ieee80211_gtk_rekey_add(9), ieee80211_gtk_rekey_notify(9), ieee80211_key_mic_failure(9), ieee80211_key_replay(9), ieee80211_wake_queue(9), ieee80211_stop_queue(9), ieee80211_queue_stopped(9), ieee80211_stop_queues(9), ieee80211_wake_queues(9), ieee80211_scan_completed(9), ieee80211_sched_scan_results(9), ieee80211_sched_scan_stopped(9).
iterators + aggregation, aka the "for_each" chapter of your life:
enum ieee80211_interface_iteration_flags(9), ieee80211_iterate_interfaces(9), ieee80211_iterate_active_interfaces(9), ieee80211_iterate_active_interfaces_atomic(9), for_each_interface(9), for_each_active_interface(9), ieee80211_iterate_active_interfaces_mtx(9), ieee80211_iterate_stations_atomic(9), for_each_station(9), ieee80211_iterate_stations_mtx(9), ieee80211_queue_work(9), ieee80211_queue_delayed_work(9), ieee80211_refresh_tx_agg_session_timer(9), ieee80211_start_tx_ba_session(9), ieee80211_start_tx_ba_cb_irqsafe(9), ieee80211_stop_tx_ba_session(9), ieee80211_stop_tx_ba_cb_irqsafe(9), ieee80211_find_sta(9), ieee80211_find_sta_by_ifaddr(9), ieee80211_find_sta_by_link_addrs(9), ieee80211_sta_block_awake(9), ieee80211_sta_eosp(9), ieee80211_send_eosp_nullfunc(9), ieee80211_sta_recalc_aggregates(9), ieee80211_sta_register_airtime(9), ieee80211_txq_airtime_check(9), ieee80211_txq_aql_pending(9).
the "something went wrong" section, which is honestly a vibe π:
ieee80211_iter_keys(9), ieee80211_iter_keys_rcu(9), ieee80211_iter_chan_contexts_atomic(9), ieee80211_iter_chan_contexts_mtx(9), ieee80211_ap_probereq_get(9), ieee80211_beacon_loss(9), ieee80211_connection_loss(9), ieee80211_disconnect(9), ieee80211_resume_disconnect(9), ieee80211_hw_restart_disconnect(9), ieee80211_cqm_rssi_notify(9), ieee80211_cqm_beacon_loss_notify(9), ieee80211_radar_detected(9), ieee80211_chswitch_done(9), ieee80211_channel_switch_disconnect(9), ieee80211_request_smps(9), ieee80211_ready_on_channel(9), ieee80211_remain_on_channel_expired(9), ieee80211_stop_rx_ba_session(9), ieee80211_mark_rx_ba_filtered_frames(9), ieee80211_send_bar(9), ieee80211_manage_rx_ba_offl(9), ieee80211_start_rx_ba_session_offl(9), ieee80211_stop_rx_ba_session_offl(9), ieee80211_rx_ba_timer_expired(9).
rate control, caps, airtime, woah:
struct ieee80211_tx_rate_control(9), enum rate_control_capabilities(9), rate_control_set_rates(9), ieee80211_get_he_iftype_cap_vif(9), ieee80211_get_he_6ghz_capa_vif(9), ieee80211_get_eht_iftype_cap_vif(9), ieee80211_get_uhr_iftype_cap_vif(9), ieee80211_update_mu_groups(9), ieee80211_ave_rssi(9), ieee80211_calculate_rx_timestamp(9), ieee80211_report_wowlan_wakeup(9), ieee80211_tx_prepare_skb(9), ieee80211_parse_tx_radiotap(9), struct ieee80211_noa_data(9), ieee80211_parse_p2p_noa(9), ieee80211_update_p2p_noa(9), ieee80211_tdls_oper_request(9), ieee80211_reserve_tid(9), ieee80211_unreserve_tid(9), ieee80211_tx_dequeue(9), ieee80211_tx_dequeue_ni(9), ieee80211_handle_wake_tx_queue(9), ieee80211_next_txq(9), ieee80211_txq_schedule_start(9), ieee80211_schedule_txq(9), ieee80211_return_txq(9), ieee80211_txq_may_transmit(9), ieee80211_txq_get_depth(9).
and the final stretch, the last few homies β NAN, airtime math, links, and the great encrypt:
ieee80211_nan_func_terminated(9), ieee80211_nan_func_match(9), ieee80211_nan_sched_update_done(9), ieee80211_nan_cluster_joined(9), ieee80211_nan_try_evacuate(9), ieee80211_calc_rx_airtime(9), ieee80211_calc_tx_airtime(9), ieee80211_get_fils_discovery_tmpl(9), ieee80211_get_unsol_bcast_probe_resp_tmpl(9), ieee80211_obss_color_collision_notify(9), ieee80211_is_tx_data(9), ieee80211_set_active_links(9), ieee80211_set_active_links_async(9), ieee80211_send_teardown_neg_ttlm(9), ieee80211_chan_width_to_rx_bw(9), ieee80211_prepare_rx_omi_bw(9), ieee80211_finalize_rx_omi_bw(9), ieee80211_vif_nan_started(9), ieee80211_encrypt_tx_skb(9).
that's the whole roster, fr fr β nothing dropped, nothing merged. if you need a specific one, man 9 it and go off. π
and that's a wrap on the whole page, bestie π this one lives in ./include/net, it's dated October 2026, and the whole thing is filed under struct ieee80211_ops(9) β go forth and slay your driver. β¨π¦
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms