aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorGravatar Jakub Kicinski <kuba@kernel.org> 2023-02-16 11:33:10 -0800
committerGravatar Jakub Kicinski <kuba@kernel.org> 2023-02-16 11:33:10 -0800
commitca0df43d211039dded5a8f8553356414c9a74731 (patch)
treed7196452d070c88831cf17dfa063a1b65d9ad913 /net
parentMerge branch 'seg6-add-psp-flavor-support-for-srv6-end-behavior' (diff)
parentwifi: brcmfmac: p2p: Introduce generic flexible array frame member (diff)
downloadlinux-ca0df43d211039dded5a8f8553356414c9a74731.tar.gz
linux-ca0df43d211039dded5a8f8553356414c9a74731.tar.bz2
linux-ca0df43d211039dded5a8f8553356414c9a74731.zip
Merge tag 'wireless-next-2023-03-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Johannes Berg says: ==================== Major stack changes: * EHT channel puncturing support (client & AP) * some support for AP MLD without mac80211 * fixes for A-MSDU on mesh connections Major driver changes: iwlwifi * EHT rate reporting * Bump FW API to 74 for AX devices * STEP equalizer support: transfer some STEP (connection to radio on platforms with integrated wifi) related parameters from the BIOS to the firmware mt76 * switch to using page pool allocator * mt7996 EHT (Wi-Fi 7) support * Wireless Ethernet Dispatch (WED) reset support libertas * WPS enrollee support brcmfmac * Rename Cypress 89459 to BCM4355 * BCM4355 and BCM4377 support mwifiex * SD8978 chipset support rtl8xxxu * LED support ath12k * new driver for Qualcomm Wi-Fi 7 devices ath11k * IPQ5018 support * Fine Timing Measurement (FTM) responder role support * channel 177 support ath10k * store WLAN firmware version in SMEM image table * tag 'wireless-next-2023-03-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (207 commits) wifi: brcmfmac: p2p: Introduce generic flexible array frame member wifi: mac80211: add documentation for amsdu_mesh_control wifi: cfg80211: remove gfp parameter from cfg80211_obss_color_collision_notify description wifi: mac80211: always initialize link_sta with sta wifi: mac80211: pass 'sta' to ieee80211_rx_data_set_sta() wifi: cfg80211: Set SSID if it is not already set wifi: rtw89: move H2C of del_pkt_offload before polling FW status ready wifi: rtw89: use readable return 0 in rtw89_mac_cfg_ppdu_status() wifi: rtw88: usb: drop now unnecessary URB size check wifi: rtw88: usb: send Zero length packets if necessary wifi: rtw88: usb: Set qsel correctly wifi: mac80211: fix off-by-one link setting wifi: mac80211: Fix for Rx fragmented action frames wifi: mac80211: avoid u32_encode_bits() warning wifi: mac80211: Don't translate MLD addresses for multicast wifi: cfg80211: call reg_notifier for self managed wiphy from driver hint wifi: cfg80211: get rid of gfp in cfg80211_bss_color_notify wifi: nl80211: Allow authentication frames and set keys on NAN interface wifi: mac80211: fix non-MLO station association wifi: mac80211: Allow NSS change only up to capability ... ==================== Link: https://lore.kernel.org/r/20230216105406.208416-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c50
-rw-r--r--net/mac80211/chan.c2
-rw-r--r--net/mac80211/debugfs_netdev.c3
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/link.c3
-rw-r--r--net/mac80211/mlme.c167
-rw-r--r--net/mac80211/rx.c401
-rw-r--r--net/mac80211/sta_info.c5
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/vht.c25
-rw-r--r--net/rfkill/core.c16
-rw-r--r--net/wireless/ap.c2
-rw-r--r--net/wireless/chan.c69
-rw-r--r--net/wireless/mlme.c5
-rw-r--r--net/wireless/nl80211.c156
-rw-r--r--net/wireless/nl80211.h2
-rw-r--r--net/wireless/reg.c3
-rw-r--r--net/wireless/sme.c48
-rw-r--r--net/wireless/trace.h309
-rw-r--r--net/wireless/util.c183
21 files changed, 1021 insertions, 439 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f5d43f42f6d8..8eb342300868 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1220,7 +1220,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_local *local = sdata->local;
struct beacon_data *old;
struct ieee80211_sub_if_data *vlan;
- u32 changed = BSS_CHANGED_BEACON_INT |
+ u64 changed = BSS_CHANGED_BEACON_INT |
BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_BEACON |
BSS_CHANGED_P2P_PS |
@@ -1296,6 +1296,11 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
}
+ if (params->eht_cap) {
+ link_conf->eht_puncturing = params->punct_bitmap;
+ changed |= BSS_CHANGED_EHT_PUNCTURING;
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_AP &&
params->mbssid_config.tx_wdev) {
err = ieee80211_set_ap_mbssid_options(sdata,
@@ -3546,6 +3551,12 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&local->mtx);
lockdep_assert_held(&local->chanctx_mtx);
+ if (sdata->vif.bss_conf.eht_puncturing != sdata->vif.bss_conf.csa_punct_bitmap) {
+ sdata->vif.bss_conf.eht_puncturing =
+ sdata->vif.bss_conf.csa_punct_bitmap;
+ changed |= BSS_CHANGED_EHT_PUNCTURING;
+ }
+
/*
* using reservation isn't immediate as it may be deferred until later
* with multi-vif. once reservation is complete it will re-schedule the
@@ -3587,7 +3598,8 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
if (err)
return err;
- cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0);
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0,
+ sdata->vif.bss_conf.eht_puncturing);
return 0;
}
@@ -3849,9 +3861,13 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
goto out;
}
+ if (params->punct_bitmap && !sdata->vif.bss_conf.eht_support)
+ goto out;
+
sdata->deflink.csa_chandef = params->chandef;
sdata->deflink.csa_block_tx = params->block_tx;
sdata->vif.bss_conf.csa_active = true;
+ sdata->vif.bss_conf.csa_punct_bitmap = params->punct_bitmap;
if (sdata->deflink.csa_block_tx)
ieee80211_stop_vif_queues(local, sdata,
@@ -3859,7 +3875,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
cfg80211_ch_switch_started_notify(sdata->dev,
&sdata->deflink.csa_chandef, 0,
- params->count, params->block_tx);
+ params->count, params->block_tx,
+ sdata->vif.bss_conf.csa_punct_bitmap);
if (changed) {
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
@@ -4171,7 +4188,7 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_link_data *link;
int ret;
- u32 changed = 0;
+ u64 changed = 0;
link = sdata_dereference(sdata->link[link_id], sdata);
@@ -4652,6 +4669,19 @@ unlock:
sdata_unlock(sdata);
}
+void ieee80211_color_collision_detection_work(struct work_struct *work)
+{
+ struct delayed_work *delayed_work = to_delayed_work(work);
+ struct ieee80211_link_data *link =
+ container_of(delayed_work, struct ieee80211_link_data,
+ color_collision_detect_work);
+ struct ieee80211_sub_if_data *sdata = link->sdata;
+
+ sdata_lock(sdata);
+ cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap);
+ sdata_unlock(sdata);
+}
+
void ieee80211_color_change_finish(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -4666,11 +4696,21 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
u64 color_bitmap, gfp_t gfp)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_link_data *link = &sdata->deflink;
if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active)
return;
- cfg80211_obss_color_collision_notify(sdata->dev, color_bitmap, gfp);
+ if (delayed_work_pending(&link->color_collision_detect_work))
+ return;
+
+ link->color_bitmap = color_bitmap;
+ /* queue the color collision detection event every 500 ms in order to
+ * avoid sending too much netlink messages to userspace.
+ */
+ ieee80211_queue_delayed_work(&sdata->local->hw,
+ &link->color_collision_detect_work,
+ msecs_to_jiffies(500));
}
EXPORT_SYMBOL_GPL(ieee80211_obss_color_collision_notify);
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index e72cf0749d49..dbc34fbe7c8f 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -1916,7 +1916,7 @@ int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
int ieee80211_link_change_bandwidth(struct ieee80211_link_data *link,
const struct cfg80211_chan_def *chandef,
- u32 *changed)
+ u64 *changed)
{
struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_bss_conf *link_conf = link->conf;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index c87e1137e5da..0bac9af3ca96 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -603,8 +603,6 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
-IEEE80211_IF_FILE(dropped_frames_congestion,
- u.mesh.mshstats.dropped_frames_congestion, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route,
u.mesh.mshstats.dropped_frames_no_route, DEC);
@@ -740,7 +738,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
MESHSTATS_ADD(fwded_frames);
MESHSTATS_ADD(dropped_frames_ttl);
MESHSTATS_ADD(dropped_frames_no_route);
- MESHSTATS_ADD(dropped_frames_congestion);
#undef MESHSTATS_ADD
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d16606e84e22..ecc232eb1ee8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -327,7 +327,6 @@ struct mesh_stats {
__u32 fwded_frames; /* Mesh total forwarded frames */
__u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
__u32 dropped_frames_no_route; /* Not transmitted, no route found */
- __u32 dropped_frames_congestion;/* Not forwarded due to congestion */
};
#define PREQ_Q_F_START 0x1
@@ -974,6 +973,8 @@ struct ieee80211_link_data {
struct cfg80211_chan_def csa_chandef;
struct work_struct color_change_finalize_work;
+ struct delayed_work color_collision_detect_work;
+ u64 color_bitmap;
/* context reservation -- protected with chanctx_mtx */
struct ieee80211_chanctx *reserved_chanctx;
@@ -1929,6 +1930,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
/* color change handling */
void ieee80211_color_change_finalize_work(struct work_struct *work);
+void ieee80211_color_collision_detection_work(struct work_struct *work);
/* interface handling */
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
@@ -2478,7 +2480,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link);
int __must_check
ieee80211_link_change_bandwidth(struct ieee80211_link_data *link,
const struct cfg80211_chan_def *chandef,
- u32 *changed);
+ u64 *changed);
void ieee80211_link_release_channel(struct ieee80211_link_data *link);
void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link);
void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index d1f5a9f7c647..8c8869cc1fb4 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -39,6 +39,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
ieee80211_csa_finalize_work);
INIT_WORK(&link->color_change_finalize_work,
ieee80211_color_change_finalize_work);
+ INIT_DELAYED_WORK(&link->color_collision_detect_work,
+ ieee80211_color_collision_detection_work);
INIT_LIST_HEAD(&link->assigned_chanctx_list);
INIT_LIST_HEAD(&link->reserved_chanctx_list);
INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
@@ -66,6 +68,7 @@ void ieee80211_link_stop(struct ieee80211_link_data *link)
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_mgd_stop_link(link);
+ cancel_delayed_work_sync(&link->color_collision_detect_work);
ieee80211_link_release_channel(link);
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0aee2392dd29..60792dfabc9d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -8,7 +8,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2022 Intel Corporation
+ * Copyright (C) 2018 - 2023 Intel Corporation
*/
#include <linux/delay.h>
@@ -89,6 +89,80 @@ MODULE_PARM_DESC(probe_wait_ms,
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
/*
+ * Extract from the given disabled subchannel bitmap (raw format
+ * from the EHT Operation Element) the bits for the subchannel
+ * we're using right now.
+ */
+static u16
+ieee80211_extract_dis_subch_bmap(const struct ieee80211_eht_operation *eht_oper,
+ struct cfg80211_chan_def *chandef, u16 bitmap)
+{
+ struct ieee80211_eht_operation_info *info = (void *)eht_oper->optional;
+ struct cfg80211_chan_def ap_chandef = *chandef;
+ u32 ap_center_freq, local_center_freq;
+ u32 ap_bw, local_bw;
+ int ap_start_freq, local_start_freq;
+ u16 shift, mask;
+
+ if (!(eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT) ||
+ !(eht_oper->params &
+ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT))
+ return 0;
+
+ /* set 160/320 supported to get the full AP definition */
+ ieee80211_chandef_eht_oper(eht_oper, true, true, &ap_chandef);
+ ap_center_freq = ap_chandef.center_freq1;
+ ap_bw = 20 * BIT(u8_get_bits(info->control,
+ IEEE80211_EHT_OPER_CHAN_WIDTH));
+ ap_start_freq = ap_center_freq - ap_bw / 2;
+ local_center_freq = chandef->center_freq1;
+ local_bw = 20 * BIT(ieee80211_chan_width_to_rx_bw(chandef->width));
+ local_start_freq = local_center_freq - local_bw / 2;
+ shift = (local_start_freq - ap_start_freq) / 20;
+ mask = BIT(local_bw / 20) - 1;
+
+ return (bitmap >> shift) & mask;
+}
+
+/*
+ * Handle the puncturing bitmap, possibly downgrading bandwidth to get a
+ * valid bitmap.
+ */
+static void
+ieee80211_handle_puncturing_bitmap(struct ieee80211_link_data *link,
+ const struct ieee80211_eht_operation *eht_oper,
+ u16 bitmap, u64 *changed)
+{
+ struct cfg80211_chan_def *chandef = &link->conf->chandef;
+ u16 extracted;
+ u64 _changed = 0;
+
+ if (!changed)
+ changed = &_changed;
+
+ while (chandef->width > NL80211_CHAN_WIDTH_40) {
+ extracted =
+ ieee80211_extract_dis_subch_bmap(eht_oper, chandef,
+ bitmap);
+
+ if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ chandef))
+ break;
+ link->u.mgd.conn_flags |=
+ ieee80211_chandef_downgrade(chandef);
+ *changed |= BSS_CHANGED_BANDWIDTH;
+ }
+
+ if (chandef->width <= NL80211_CHAN_WIDTH_40)
+ extracted = 0;
+
+ if (link->conf->eht_puncturing != extracted) {
+ link->conf->eht_puncturing = extracted;
+ *changed |= BSS_CHANGED_EHT_PUNCTURING;
+ }
+}
+
+/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
* reschedule it when it should fire _earlier_ than it was
@@ -413,7 +487,7 @@ static int ieee80211_config_bw(struct ieee80211_link_data *link,
const struct ieee80211_he_operation *he_oper,
const struct ieee80211_eht_operation *eht_oper,
const struct ieee80211_s1g_oper_ie *s1g_oper,
- const u8 *bssid, u32 *changed)
+ const u8 *bssid, u64 *changed)
{
struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
@@ -1704,7 +1778,7 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link)
return;
}
- cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0);
+ cfg80211_ch_switch_notify(sdata->dev, &link->reserved_chandef, 0, 0);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1914,7 +1988,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
mutex_unlock(&local->mtx);
cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
- csa_ie.count, csa_ie.mode);
+ csa_ie.count, csa_ie.mode, 0);
if (local->ops->channel_switch) {
/* use driver's channel switch callback */
@@ -4145,6 +4219,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
link_sta);
bss_conf->eht_support = link_sta->pub->eht_cap.has_eht;
+ *changed |= BSS_CHANGED_EHT_PUNCTURING;
} else {
bss_conf->eht_support = false;
}
@@ -5477,6 +5552,45 @@ static bool ieee80211_rx_our_beacon(const u8 *tx_bssid,
return ether_addr_equal(tx_bssid, bss->transmitted_bss->bssid);
}
+static bool ieee80211_config_puncturing(struct ieee80211_link_data *link,
+ const struct ieee80211_eht_operation *eht_oper,
+ u64 *changed)
+{
+ u16 bitmap = 0, extracted;
+
+ if ((eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT) &&
+ (eht_oper->params &
+ IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) {
+ const struct ieee80211_eht_operation_info *info =
+ (void *)eht_oper->optional;
+ const u8 *disable_subchannel_bitmap = info->optional;
+
+ bitmap = get_unaligned_le16(disable_subchannel_bitmap);
+ }
+
+ extracted = ieee80211_extract_dis_subch_bmap(eht_oper,
+ &link->conf->chandef,
+ bitmap);
+
+ /* accept if there are no changes */
+ if (!(*changed & BSS_CHANGED_BANDWIDTH) &&
+ extracted == link->conf->eht_puncturing)
+ return true;
+
+ if (!cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ &link->conf->chandef)) {
+ link_info(link,
+ "Got an invalid disable subchannel bitmap from AP %pM: bitmap = 0x%x, bw = 0x%x. disconnect\n",
+ link->u.mgd.bssid,
+ bitmap,
+ link->conf->chandef.width);
+ return false;
+ }
+
+ ieee80211_handle_puncturing_bitmap(link, eht_oper, bitmap, changed);
+ return true;
+}
+
static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
struct ieee80211_hdr *hdr, size_t len,
struct ieee80211_rx_status *rx_status)
@@ -5494,7 +5608,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
struct ieee80211_channel *chan;
struct link_sta_info *link_sta;
struct sta_info *sta;
- u32 changed = 0;
+ u64 changed = 0;
bool erp_valid;
u8 erp_value = 0;
u32 ncrc = 0;
@@ -5791,6 +5905,21 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
elems->pwr_constr_elem,
elems->cisco_dtpc_elem);
+ if (elems->eht_operation &&
+ !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) {
+ if (!ieee80211_config_puncturing(link, elems->eht_operation,
+ &changed)) {
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_DEAUTH_LEAVING,
+ true, deauth_buf);
+ ieee80211_report_disconnect(sdata, deauth_buf,
+ sizeof(deauth_buf), true,
+ WLAN_REASON_DEAUTH_LEAVING,
+ false);
+ goto free;
+ }
+ }
+
ieee80211_link_info_change_notify(sdata, link, changed);
free:
kfree(elems);
@@ -6892,9 +7021,12 @@ ieee80211_setup_assoc_link(struct ieee80211_sub_if_data *sdata,
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
}
+ link->conf->eht_puncturing = 0;
+
rcu_read_lock();
beacon_ies = rcu_dereference(cbss->beacon_ies);
if (beacon_ies) {
+ const struct ieee80211_eht_operation *eht_oper;
const struct element *elem;
u8 dtim_count = 0;
@@ -6923,6 +7055,31 @@ ieee80211_setup_assoc_link(struct ieee80211_sub_if_data *sdata,
link->conf->ema_ap = true;
else
link->conf->ema_ap = false;
+
+ elem = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION,
+ beacon_ies->data, beacon_ies->len);
+ eht_oper = (const void *)(elem->data + 1);
+
+ if (elem &&
+ ieee80211_eht_oper_size_ok((const void *)(elem->data + 1),
+ elem->datalen - 1) &&
+ (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT) &&
+ (eht_oper->params & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) {
+ const struct ieee80211_eht_operation_info *info =
+ (void *)eht_oper->optional;
+ const u8 *disable_subchannel_bitmap = info->optional;
+ u16 bitmap;
+
+ bitmap = get_unaligned_le16(disable_subchannel_bitmap);
+ if (cfg80211_valid_disable_subchannel_bitmap(&bitmap,
+ &link->conf->chandef))
+ ieee80211_handle_puncturing_bitmap(link,
+ eht_oper,
+ bitmap,
+ NULL);
+ else
+ conn_flags |= IEEE80211_CONN_DISABLE_EHT;
+ }
}
rcu_read_unlock();
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e284897ba5e9..f7fdfe710951 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2720,6 +2720,174 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
}
}
+static ieee80211_rx_result
+ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
+ struct sk_buff *skb)
+{
+#ifdef CONFIG_MAC80211_MESH
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
+ uint16_t fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
+ struct ieee80211_hdr hdr = {
+ .frame_control = cpu_to_le16(fc)
+ };
+ struct ieee80211_hdr *fwd_hdr;
+ struct ieee80211s_hdr *mesh_hdr;
+ struct ieee80211_tx_info *info;
+ struct sk_buff *fwd_skb;
+ struct ethhdr *eth;
+ bool multicast;
+ int tailroom = 0;
+ int hdrlen, mesh_hdrlen;
+ u8 *qos;
+
+ if (!ieee80211_vif_is_mesh(&sdata->vif))
+ return RX_CONTINUE;
+
+ if (!pskb_may_pull(skb, sizeof(*eth) + 6))
+ return RX_DROP_MONITOR;
+
+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(*eth));
+ mesh_hdrlen = ieee80211_get_mesh_hdrlen(mesh_hdr);
+
+ if (!pskb_may_pull(skb, sizeof(*eth) + mesh_hdrlen))
+ return RX_DROP_MONITOR;
+
+ eth = (struct ethhdr *)skb->data;
+ multicast = is_multicast_ether_addr(eth->h_dest);
+
+ mesh_hdr = (struct ieee80211s_hdr *)(eth + 1);
+ if (!mesh_hdr->ttl)
+ return RX_DROP_MONITOR;
+
+ /* frame is in RMC, don't forward */
+ if (is_multicast_ether_addr(eth->h_dest) &&
+ mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
+ return RX_DROP_MONITOR;
+
+ /* Frame has reached destination. Don't forward */
+ if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
+ goto rx_accept;
+
+ if (!ifmsh->mshcfg.dot11MeshForwarding) {
+ if (is_multicast_ether_addr(eth->h_dest))
+ goto rx_accept;
+
+ return RX_DROP_MONITOR;
+ }
+
+ /* forward packet */
+ if (sdata->crypto_tx_tailroom_needed_cnt)
+ tailroom = IEEE80211_ENCRYPT_TAILROOM;
+
+ if (!--mesh_hdr->ttl) {
+ if (multicast)
+ goto rx_accept;
+
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+ return RX_DROP_MONITOR;
+ }
+
+ if (mesh_hdr->flags & MESH_FLAGS_AE) {
+ struct mesh_path *mppath;
+ char *proxied_addr;
+
+ if (multicast)
+ proxied_addr = mesh_hdr->eaddr1;
+ else if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
+ /* has_a4 already checked in ieee80211_rx_mesh_check */
+ proxied_addr = mesh_hdr->eaddr2;
+ else
+ return RX_DROP_MONITOR;
+
+ rcu_read_lock();
+ mppath = mpp_path_lookup(sdata, proxied_addr);
+ if (!mppath) {
+ mpp_path_add(sdata, proxied_addr, eth->h_source);
+ } else {
+ spin_lock_bh(&mppath->state_lock);
+ if (!ether_addr_equal(mppath->mpp, eth->h_source))
+ memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
+ mppath->exp_time = jiffies;
+ spin_unlock_bh(&mppath->state_lock);
+ }
+ rcu_read_unlock();
+ }
+
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
+
+ ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
+ eth->h_dest, eth->h_source);
+ hdrlen = ieee80211_hdrlen(hdr.frame_control);
+ if (multicast) {
+ int extra_head = sizeof(struct ieee80211_hdr) - sizeof(*eth);
+
+ fwd_skb = skb_copy_expand(skb, local->tx_headroom + extra_head +
+ IEEE80211_ENCRYPT_HEADROOM,
+ tailroom, GFP_ATOMIC);
+ if (!fwd_skb)
+ goto rx_accept;
+ } else {
+ fwd_skb = skb;
+ skb = NULL;
+
+ if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
+ return RX_DROP_UNUSABLE;
+ }
+
+ fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
+ memcpy(fwd_hdr, &hdr, hdrlen - 2);
+ qos = ieee80211_get_qos_ctl(fwd_hdr);
+ qos[0] = qos[1] = 0;
+
+ skb_reset_mac_header(fwd_skb);
+ hdrlen += mesh_hdrlen;
+ if (ieee80211_get_8023_tunnel_proto(fwd_skb->data + hdrlen,
+ &fwd_skb->protocol))
+ hdrlen += ETH_ALEN;
+ else
+ fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
+ skb_set_network_header(fwd_skb, hdrlen);
+
+ info = IEEE80211_SKB_CB(fwd_skb);
+ memset(info, 0, sizeof(*info));
+ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
+ info->control.vif = &sdata->vif;
+ info->control.jiffies = jiffies;
+ if (multicast) {
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
+ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
+ /* update power mode indication when forwarding */
+ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
+ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
+ /* mesh power mode flags updated in mesh_nexthop_lookup */
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
+ } else {
+ /* unable to resolve next hop */
+ if (sta)
+ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
+ hdr.addr3, 0,
+ WLAN_REASON_MESH_PATH_NOFORWARD,
+ sta->sta.addr);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
+ kfree_skb(fwd_skb);
+ goto rx_accept;
+ }
+
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
+ fwd_skb->dev = sdata->dev;
+ ieee80211_add_pending_skb(local, fwd_skb);
+
+rx_accept:
+ if (!skb)
+ return RX_QUEUED;
+
+ ieee80211_strip_8023_mesh_hdr(skb);
+#endif
+
+ return RX_CONTINUE;
+}
+
static ieee80211_rx_result debug_noinline
__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
{
@@ -2728,6 +2896,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
+ static ieee80211_rx_result res;
struct ethhdr ethhdr;
const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
@@ -2746,6 +2915,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
break;
case NL80211_IFTYPE_MESH_POINT:
check_sa = NULL;
+ check_da = NULL;
break;
default:
break;
@@ -2760,20 +2930,43 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
data_offset, true))
return RX_DROP_UNUSABLE;
+ if (rx->sta && rx->sta->amsdu_mesh_control < 0) {
+ bool valid_std = ieee80211_is_valid_amsdu(skb, true);
+ bool valid_nonstd = ieee80211_is_valid_amsdu(skb, false);
+
+ if (valid_std && !valid_nonstd)
+ rx->sta->amsdu_mesh_control = 1;
+ else if (valid_nonstd && !valid_std)
+ rx->sta->amsdu_mesh_control = 0;
+ }
+
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
rx->sdata->vif.type,
rx->local->hw.extra_tx_headroom,
- check_da, check_sa);
+ check_da, check_sa,
+ rx->sta->amsdu_mesh_control);
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
- if (!ieee80211_frame_allowed(rx, fc)) {
- dev_kfree_skb(rx->skb);
+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
+ switch (res) {
+ case RX_QUEUED:
continue;
+ case RX_CONTINUE:
+ break;
+ default:
+ goto free;
}
+ if (!ieee80211_frame_allowed(rx, fc))
+ goto free;
+
ieee80211_deliver_skb(rx);
+ continue;
+
+free:
+ dev_kfree_skb(rx->skb);
}
return RX_QUEUED;
@@ -2806,6 +2999,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
if (!rx->sdata->u.mgd.use_4addr)
return RX_DROP_UNUSABLE;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
default:
return RX_DROP_UNUSABLE;
}
@@ -2834,160 +3029,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
return __ieee80211_rx_h_amsdu(rx, 0);
}
-#ifdef CONFIG_MAC80211_MESH
-static ieee80211_rx_result
-ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
-{
- struct ieee80211_hdr *fwd_hdr, *hdr;
- struct ieee80211_tx_info *info;
- struct ieee80211s_hdr *mesh_hdr;
- struct sk_buff *skb = rx->skb, *fwd_skb;
- struct ieee80211_local *local = rx->local;
- struct ieee80211_sub_if_data *sdata = rx->sdata;
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- u16 ac, q, hdrlen;
- int tailroom = 0;
-
- hdr = (struct ieee80211_hdr *) skb->data;
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
- /* make sure fixed part of mesh header is there, also checks skb len */
- if (!pskb_may_pull(rx->skb, hdrlen + 6))
- return RX_DROP_MONITOR;
-
- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
-
- /* make sure full mesh header is there, also checks skb len */
- if (!pskb_may_pull(rx->skb,
- hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
- return RX_DROP_MONITOR;
-
- /* reload pointers */
- hdr = (struct ieee80211_hdr *) skb->data;
- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
-
- if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) {
- int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) +
- sizeof(rfc1042_header);
- __be16 ethertype;
-
- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) ||
- skb_copy_bits(rx->skb, offset, &ethertype, 2) != 0 ||
- ethertype != rx->sdata->control_port_protocol)
- return RX_DROP_MONITOR;
- }
-
- /* frame is in RMC, don't forward */
- if (ieee80211_is_data(hdr->frame_control) &&
- is_multicast_ether_addr(hdr->addr1) &&
- mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
- return RX_DROP_MONITOR;
-
- if (!ieee80211_is_data(hdr->frame_control))
- return RX_CONTINUE;
-
- if (!mesh_hdr->ttl)
- return RX_DROP_MONITOR;
-
- if (mesh_hdr->flags & MESH_FLAGS_AE) {
- struct mesh_path *mppath;
- char *proxied_addr;
- char *mpp_addr;
-
- if (is_multicast_ether_addr(hdr->addr1)) {
- mpp_addr = hdr->addr3;
- proxied_addr = mesh_hdr->eaddr1;
- } else if ((mesh_hdr->flags & MESH_FLAGS_AE) ==
- MESH_FLAGS_AE_A5_A6) {
- /* has_a4 already checked in ieee80211_rx_mesh_check */
- mpp_addr = hdr->addr4;
- proxied_addr = mesh_hdr->eaddr2;
- } else {
- return RX_DROP_MONITOR;
- }
-
- rcu_read_lock();
- mppath = mpp_path_lookup(sdata, proxied_addr);
- if (!mppath) {
- mpp_path_add(sdata, proxied_addr, mpp_addr);
- } else {
- spin_lock_bh(&mppath->state_lock);
- if (!ether_addr_equal(mppath->mpp, mpp_addr))
- memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
- mppath->exp_time = jiffies;
- spin_unlock_bh(&mppath->state_lock);
- }
- rcu_read_unlock();
- }
-
- /* Frame has reached destination. Don't forward */
- if (!is_multicast_ether_addr(hdr->addr1) &&
- ether_addr_equal(sdata->vif.addr, hdr->addr3))
- return RX_CONTINUE;
-
- ac = ieee802_1d_to_ac[skb->priority];
- q = sdata->vif.hw_queue[ac];
- if (ieee80211_queue_stopped(&local->hw, q)) {
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
- return RX_DROP_MONITOR;
- }
- skb_set_queue_mapping(skb, ac);
-
- if (!--mesh_hdr->ttl) {
- if (!is_multicast_ether_addr(hdr->addr1))
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
- dropped_frames_ttl);
- goto out;
- }
-
- if (!ifmsh->mshcfg.dot11MeshForwarding)
- goto out;
-
- if (sdata->crypto_tx_tailroom_needed_cnt)
- tailroom = IEEE80211_ENCRYPT_TAILROOM;
-
- fwd_skb = skb_copy_expand(skb, local->tx_headroom +
- IEEE80211_ENCRYPT_HEADROOM,
- tailroom, GFP_ATOMIC);
- if (!fwd_skb)
- goto out;
-
- fwd_skb->dev = sdata->dev;
- fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
- fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
- info = IEEE80211_SKB_CB(fwd_skb);
- memset(info, 0, sizeof(*info));
- info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
- info->control.vif = &rx->sdata->vif;
- info->control.jiffies = jiffies;
- if (is_multicast_ether_addr(fwd_hdr->addr1)) {
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
- /* update power mode indication when forwarding */
- ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
- } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
- /* mesh power mode flags updated in mesh_nexthop_lookup */
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
- } else {
- /* unable to resolve next hop */
- mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
- fwd_hdr->addr3, 0,
- WLAN_REASON_MESH_PATH_NOFORWARD,
- fwd_hdr->addr2);
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
- kfree_skb(fwd_skb);
- return RX_DROP_MONITOR;
- }
-
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
- ieee80211_add_pending_skb(local, fwd_skb);
- out:
- if (is_multicast_ether_addr(hdr->addr1))
- return RX_CONTINUE;
- return RX_DROP_MONITOR;
-}
-#endif
-
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
{
@@ -2996,6 +3037,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
struct net_device *dev = sdata->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
__le16 fc = hdr->frame_control;
+ static ieee80211_rx_result res;
bool port_control;
int err;
@@ -3022,6 +3064,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
if (unlikely(err))
return RX_DROP_UNUSABLE;
+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
+ if (res != RX_CONTINUE)
+ return res;
+
if (!ieee80211_frame_allowed(rx, fc))
return RX_DROP_MONITOR;
@@ -3992,10 +4038,6 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
CALL_RXH(ieee80211_rx_h_defragment);
CALL_RXH(ieee80211_rx_h_michael_mic_verify);
/* must be after MMIC verify so header is counted in MPDU mic */
-#ifdef CONFIG_MAC80211_MESH
- if (ieee80211_vif_is_mesh(&rx->sdata->vif))
- CALL_RXH(ieee80211_rx_h_mesh_fwding);
-#endif
CALL_RXH(ieee80211_rx_h_amsdu);
CALL_RXH(ieee80211_rx_h_data);
@@ -4052,9 +4094,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
static bool
ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
{
- if (!sta->mlo)
- return false;
-
return !!(sta->valid_links & BIT(link_id));
}
@@ -4076,13 +4115,8 @@ static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
}
static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx,
- struct ieee80211_sta *pubsta,
- int link_id)
+ struct sta_info *sta, int link_id)
{
- struct sta_info *sta;
-
- sta = container_of(pubsta, struct sta_info, sta);
-
rx->link_id = link_id;
rx->sta = sta;
@@ -4091,6 +4125,8 @@ static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx,
if (!rx->sdata)
rx->sdata = sta->sdata;
rx->link_sta = &sta->deflink;
+ } else {
+ rx->link_sta = NULL;
}
if (link_id < 0)
@@ -4120,7 +4156,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
if (sta->sta.valid_links)
link_id = ffs(sta->sta.valid_links) - 1;
- if (!ieee80211_rx_data_set_sta(&rx, &sta->sta, link_id))
+ if (!ieee80211_rx_data_set_sta(&rx, sta, link_id))
return;
tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
@@ -4166,7 +4202,7 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
sta = container_of(pubsta, struct sta_info, sta);
- if (!ieee80211_rx_data_set_sta(&rx, pubsta, -1))
+ if (!ieee80211_rx_data_set_sta(&rx, sta, -1))
return;
rcu_read_lock();
@@ -4245,7 +4281,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
case NL80211_IFTYPE_STATION:
if (!bssid && !sdata->u.mgd.use_4addr)
return false;
- if (ieee80211_is_robust_mgmt_frame(skb) && !rx->sta)
+ if (ieee80211_is_first_frag(hdr->seq_ctrl) &&
+ ieee80211_is_robust_mgmt_frame(skb) && !rx->sta)
return false;
if (multicast)
return true;
@@ -4843,7 +4880,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
hdr = (struct ieee80211_hdr *)rx->skb->data;
}
- if (unlikely(rx->sta && rx->sta->sta.mlo)) {
+ if (unlikely(rx->sta && rx->sta->sta.mlo) &&
+ is_unicast_ether_addr(hdr->addr1)) {
/* translate to MLD addresses */
if (ether_addr_equal(link->conf->addr, hdr->addr1))
ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
@@ -4873,6 +4911,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_fast_rx *fast_rx;
struct ieee80211_rx_data rx;
+ struct sta_info *sta;
int link_id = -1;
memset(&rx, 0, sizeof(rx));
@@ -4900,7 +4939,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
* link_id is used only for stats purpose and updating the stats on
* the deflink is fine?
*/
- if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
+ sta = container_of(pubsta, struct sta_info, sta);
+ if (!ieee80211_rx_data_set_sta(&rx, sta, link_id))
goto drop;
fast_rx = rcu_dereference(rx.sta->fast_rx);
@@ -4940,7 +4980,7 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
link_id = status->link_id;
}
- if (!ieee80211_rx_data_set_sta(rx, &sta->sta, link_id))
+ if (!ieee80211_rx_data_set_sta(rx, sta, link_id))
return false;
return ieee80211_prepare_and_rx_handle(rx, skb, consume);
@@ -5007,7 +5047,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
link_id = status->link_id;
if (pubsta) {
- if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
+ sta = container_of(pubsta, struct sta_info, sta);
+ if (!ieee80211_rx_data_set_sta(&rx, sta, link_id))
goto out;
/*
@@ -5044,8 +5085,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
}
rx.sdata = prev_sta->sdata;
- if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
- link_id))
+ if (!ieee80211_rx_data_set_sta(&rx, prev_sta, link_id))
goto out;
if (!status->link_valid && prev_sta->sta.mlo)
@@ -5058,8 +5098,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (prev_sta) {
rx.sdata = prev_sta->sdata;
- if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
- link_id))
+ if (!ieee80211_rx_data_set_sta(&rx, prev_sta, link_id))
goto out;
if (!status->link_valid && prev_sta->sta.mlo)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 27c737fe7fb8..7d68dbc872d7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -594,6 +594,9 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->sta_state = IEEE80211_STA_NONE;
+ if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
+ sta->amsdu_mesh_control = -1;
+
/* Mark TID as unreserved */
sta->reserved_tid = IEEE80211_TID_UNRESERVED;
@@ -2418,7 +2421,7 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
{
- u16 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate);
+ u32 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate);
if (rate == STA_STATS_RATE_INVALID)
return -EINVAL;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c30f02874fb1..e8e482a82d77 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -622,6 +622,8 @@ struct link_sta_info {
* taken from HT/VHT capabilities or VHT operating mode notification
* @cparams: CoDel parameters for this station.
* @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
+ * @amsdu_mesh_control: track the mesh A-MSDU format used by the peer
+ * (-1: not yet known, 0: non-standard [without mesh header], 1: standard)
* @fast_tx: TX fastpath information
* @fast_rx: RX fastpath information
* @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to
@@ -707,6 +709,7 @@ struct sta_info {
struct codel_params cparams;
u8 reserved_tid;
+ s8 amsdu_mesh_control;
struct cfg80211_chan_def tdls_chandef;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index defe97a31724..7699fb410670 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4434,7 +4434,7 @@ static void ieee80211_mlo_multicast_tx(struct net_device *dev,
u32 ctrl_flags = IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX;
if (hweight16(links) == 1) {
- ctrl_flags |= u32_encode_bits(ffs(links) - 1,
+ ctrl_flags |= u32_encode_bits(__ffs(links),
IEEE80211_TX_CTRL_MLO_LINK);
__ieee80211_subif_start_xmit(skb, sdata->dev, 0, ctrl_flags,
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 803de5881485..c1250aa47808 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -625,7 +625,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
enum ieee80211_sta_rx_bandwidth new_bw;
struct sta_opmode_info sta_opmode = {};
u32 changed = 0;
- u8 nss;
+ u8 nss, cur_nss;
/* ignore - no support for BF yet */
if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)
@@ -636,10 +636,25 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
nss += 1;
if (link_sta->pub->rx_nss != nss) {
- link_sta->pub->rx_nss = nss;
- sta_opmode.rx_nss = nss;
- changed |= IEEE80211_RC_NSS_CHANGED;
- sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
+ cur_nss = link_sta->pub->rx_nss;
+ /* Reset rx_nss and call ieee80211_sta_set_rx_nss() which
+ * will set the same to max nss value calculated based on capability.
+ */
+ link_sta->pub->rx_nss = 0;
+ ieee80211_sta_set_rx_nss(link_sta);
+ /* Do not allow an nss change to rx_nss greater than max_nss
+ * negotiated and capped to APs capability during association.
+ */
+ if (nss <= link_sta->pub->rx_nss) {
+ link_sta->pub->rx_nss = nss;
+ sta_opmode.rx_nss = nss;
+ changed |= IEEE80211_RC_NSS_CHANGED;
+ sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
+ } else {
+ link_sta->pub->rx_nss = cur_nss;
+ pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d",
+ link_sta->pub->addr, nss);
+ }
}
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index b390ff245d5e..01fca7a10b4b 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -685,7 +685,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%s\n", rfkill->name);
+ return sysfs_emit(buf, "%s\n", rfkill->name);
}
static DEVICE_ATTR_RO(name);
@@ -694,7 +694,7 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%s\n", rfkill_types[rfkill->type]);
+ return sysfs_emit(buf, "%s\n", rfkill_types[rfkill->type]);
}
static DEVICE_ATTR_RO(type);
@@ -703,7 +703,7 @@ static ssize_t index_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%d\n", rfkill->idx);
+ return sysfs_emit(buf, "%d\n", rfkill->idx);
}
static DEVICE_ATTR_RO(index);
@@ -712,7 +712,7 @@ static ssize_t persistent_show(struct device *dev,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%d\n", rfkill->persistent);
+ return sysfs_emit(buf, "%d\n", rfkill->persistent);
}
static DEVICE_ATTR_RO(persistent);
@@ -721,7 +721,7 @@ static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 );
+ return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0);
}
static DEVICE_ATTR_RO(hard);
@@ -730,7 +730,7 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
+ return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0);
}
static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
@@ -764,7 +764,7 @@ static ssize_t hard_block_reasons_show(struct device *dev,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "0x%lx\n", rfkill->hard_block_reasons);
+ return sysfs_emit(buf, "0x%lx\n", rfkill->hard_block_reasons);
}
static DEVICE_ATTR_RO(hard_block_reasons);
@@ -783,7 +783,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
{
struct rfkill *rfkill = to_rfkill(dev);
- return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
+ return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state));
}
static ssize_t state_store(struct device *dev, struct device_attribute *attr,
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index e68923200018..0962770303b2 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -39,7 +39,7 @@ static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
wdev->u.ap.ssid_len = 0;
rdev_set_qos_map(rdev, dev, NULL);
if (notify)
- nl80211_send_ap_stopped(wdev);
+ nl80211_send_ap_stopped(wdev, link_id);
/* Should we apply the grace period during beaconing interface
* shutdown also?
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 0e5835cd8c61..0b7e81db383d 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1460,3 +1460,72 @@ struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
}
}
EXPORT_SYMBOL(wdev_chandef);
+
+struct cfg80211_per_bw_puncturing_values {
+ u8 len;
+ const u16 *valid_values;
+};
+
+static const u16 puncturing_values_80mhz[] = {
+ 0x8, 0x4, 0x2, 0x1
+};
+
+static const u16 puncturing_values_160mhz[] = {
+ 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1, 0xc0, 0x30, 0xc, 0x3
+};
+
+static const u16 puncturing_values_320mhz[] = {
+ 0xc000, 0x3000, 0xc00, 0x300, 0xc0, 0x30, 0xc, 0x3, 0xf000, 0xf00,
+ 0xf0, 0xf, 0xfc00, 0xf300, 0xf0c0, 0xf030, 0xf00c, 0xf003, 0xc00f,
+ 0x300f, 0xc0f, 0x30f, 0xcf, 0x3f
+};
+
+#define CFG80211_PER_BW_VALID_PUNCTURING_VALUES(_bw) \
+ { \
+ .len = ARRAY_SIZE(puncturing_values_ ## _bw ## mhz), \
+ .valid_values = puncturing_values_ ## _bw ## mhz \
+ }
+
+static const struct cfg80211_per_bw_puncturing_values per_bw_puncturing[] = {
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(80),
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(160),
+ CFG80211_PER_BW_VALID_PUNCTURING_VALUES(320)
+};
+
+bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
+ const struct cfg80211_chan_def *chandef)
+{
+ u32 idx, i, start_freq;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_80:
+ idx = 0;
+ start_freq = chandef->center_freq1 - 40;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ idx = 1;
+ start_freq = chandef->center_freq1 - 80;
+ break;
+ case NL80211_CHAN_WIDTH_320:
+ idx = 2;
+ start_freq = chandef->center_freq1 - 160;
+ break;
+ default:
+ *bitmap = 0;
+ break;
+ }
+
+ if (!*bitmap)
+ return true;
+
+ /* check if primary channel is punctured */
+ if (*bitmap & (u16)BIT((chandef->chan->center_freq - start_freq) / 20))
+ return false;
+
+ for (i = 0; i < per_bw_puncturing[idx].len; i++)
+ if (per_bw_puncturing[idx].valid_values[i] == *bitmap)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_valid_disable_subchannel_bitmap);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 58e1fb18f85a..81d3f40d6235 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -742,7 +742,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_AP_VLAN:
- if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)))
+ if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)) &&
+ (params->link_id < 0 ||
+ !ether_addr_equal(mgmt->bssid,
+ wdev->links[params->link_id].addr)))
err = -EINVAL;
break;
case NL80211_IFTYPE_MESH_POINT:
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 64cf6110ce9d..112b4bb009c8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -805,6 +805,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
+ [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
};
/* policy for the key attributes */
@@ -1548,10 +1549,14 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
if (wdev->connected)
return 0;
return -ENOLINK;
+ case NL80211_IFTYPE_NAN:
+ if (wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_NAN))
+ return 0;
+ return -EINVAL;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
case NUM_NL80211_IFTYPES:
@@ -3173,6 +3178,21 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
wdev->iftype == NL80211_IFTYPE_P2P_GO;
}
+static int nl80211_parse_punct_bitmap(struct cfg80211_registered_device *rdev,
+ struct genl_info *info,
+ const struct cfg80211_chan_def *chandef,
+ u16 *punct_bitmap)
+{
+ if (!wiphy_ext_feature_isset(&rdev->wiphy, NL80211_EXT_FEATURE_PUNCT))
+ return -EINVAL;
+
+ *punct_bitmap = nla_get_u32(info->attrs[NL80211_ATTR_PUNCT_BITMAP]);
+ if (!cfg80211_valid_disable_subchannel_bitmap(punct_bitmap, chandef))
+ return -EINVAL;
+
+ return 0;
+}
+
int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
struct genl_info *info,
struct cfg80211_chan_def *chandef)
@@ -3181,8 +3201,11 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
struct nlattr **attrs = info->attrs;
u32 control_freq;
- if (!attrs[NL80211_ATTR_WIPHY_FREQ])
+ if (!attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
+ "Frequency is missing");
return -EINVAL;
+ }
control_freq = MHZ_TO_KHZ(
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
@@ -5770,6 +5793,42 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
}
}
+static void nl80211_send_ap_started(struct wireless_dev *wdev,
+ unsigned int link_id)
+{
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_START_AP);
+ if (!hdr)
+ goto out;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
+ nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+ NL80211_ATTR_PAD) ||
+ (wdev->u.ap.ssid_len &&
+ nla_put(msg, NL80211_ATTR_SSID, wdev->u.ap.ssid_len,
+ wdev->u.ap.ssid)) ||
+ (wdev->valid_links &&
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
+ goto out;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
+ NL80211_MCGRP_MLME, GFP_KERNEL);
+ return;
+out:
+ nlmsg_free(msg);
+}
+
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5918,6 +5977,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}
+ if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+ err = nl80211_parse_punct_bitmap(rdev, info,
+ &params->chandef,
+ &params->punct_bitmap);
+ if (err)
+ goto out;
+ }
+
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params->chandef,
wdev->iftype)) {
err = -EINVAL;
@@ -6050,6 +6117,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
wdev->conn_owner_nlportid = info->snd_portid;
+
+ nl80211_send_ap_started(wdev, link_id);
}
out_unlock:
wdev_unlock(wdev);
@@ -6527,6 +6596,22 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
sinfo->assoc_req_ies))
goto nla_put_failure;
+ if (sinfo->assoc_resp_ies_len &&
+ nla_put(msg, NL80211_ATTR_RESP_IE, sinfo->assoc_resp_ies_len,
+ sinfo->assoc_resp_ies))
+ goto nla_put_failure;
+
+ if (sinfo->mlo_params_valid) {
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ sinfo->assoc_link_id))
+ goto nla_put_failure;
+
+ if (!is_zero_ether_addr(sinfo->mld_addr) &&
+ nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
+ sinfo->mld_addr))
+ goto nla_put_failure;
+ }
+
cfg80211_sinfo_release_content(sinfo);
genlmsg_end(msg, hdr);
return 0;
@@ -10057,6 +10142,14 @@ skip_beacons:
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true;
+ if (info->attrs[NL80211_ATTR_PUNCT_BITMAP]) {
+ err = nl80211_parse_punct_bitmap(rdev, info,
+ &params.chandef,
+ &params.punct_bitmap);
+ if (err)
+ goto free;
+ }
+
wdev_lock(wdev);
err = rdev_channel_switch(rdev, dev, &params);
wdev_unlock(wdev);
@@ -12253,6 +12346,10 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_P2P_DEVICE:
break;
case NL80211_IFTYPE_NAN:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_NAN))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -12310,6 +12407,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_P2P_GO:
break;
case NL80211_IFTYPE_NAN:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_NAN))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -12447,6 +12548,10 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
case NL80211_IFTYPE_P2P_DEVICE:
break;
case NL80211_IFTYPE_NAN:
+ if (!wiphy_ext_feature_isset(wdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_NAN))
+ return -EOPNOTSUPP;
+ break;
default:
return -EOPNOTSUPP;
}
@@ -18956,7 +19061,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct cfg80211_chan_def *chandef,
gfp_t gfp,
enum nl80211_commands notif,
- u8 count, bool quiet)
+ u8 count, bool quiet, u16 punct_bitmap)
{
struct wireless_dev *wdev = netdev->ieee80211_ptr;
struct sk_buff *msg;
@@ -18990,6 +19095,9 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
goto nla_put_failure;
}
+ if (nla_put_u32(msg, NL80211_ATTR_PUNCT_BITMAP, punct_bitmap))
+ goto nla_put_failure;
+
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -19002,7 +19110,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id)
+ unsigned int link_id, u16 punct_bitmap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -19011,7 +19119,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
ASSERT_WDEV_LOCK(wdev);
WARN_INVALID_LINK_ID(wdev, link_id);
- trace_cfg80211_ch_switch_notify(dev, chandef, link_id);
+ trace_cfg80211_ch_switch_notify(dev, chandef, link_id, punct_bitmap);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -19039,14 +19147,15 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
cfg80211_sched_dfs_chan_update(rdev);
nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
- NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
+ NL80211_CMD_CH_SWITCH_NOTIFY, 0, false,
+ punct_bitmap);
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id, u8 count,
- bool quiet)
+ bool quiet, u16 punct_bitmap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -19055,15 +19164,17 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
ASSERT_WDEV_LOCK(wdev);
WARN_INVALID_LINK_ID(wdev, link_id);
- trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id);
+ trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id,
+ punct_bitmap);
+
nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
- count, quiet);
+ count, quiet, punct_bitmap);
}
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
-int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
+int cfg80211_bss_color_notify(struct net_device *dev,
enum nl80211_commands cmd, u8 count,
u64 color_bitmap)
{
@@ -19077,7 +19188,7 @@ int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
@@ -19100,7 +19211,7 @@ int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
genlmsg_end(msg, hdr);
return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
- msg, 0, NL80211_MCGRP_MLME, gfp);
+ msg, 0, NL80211_MCGRP_MLME, GFP_KERNEL);
nla_put_failure:
nlmsg_free(msg);
@@ -19663,7 +19774,7 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
}
EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
-void nl80211_send_ap_stopped(struct wireless_dev *wdev)
+void nl80211_send_ap_stopped(struct wireless_dev *wdev, unsigned int link_id)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -19681,7 +19792,9 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
- NL80211_ATTR_PAD))
+ NL80211_ATTR_PAD) ||
+ (wdev->valid_links &&
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
goto out;
genlmsg_end(msg, hdr);
@@ -19720,7 +19833,9 @@ int cfg80211_external_auth_request(struct net_device *dev,
params->action) ||
nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
- params->ssid.ssid))
+ params->ssid.ssid) ||
+ (!is_zero_ether_addr(params->mld_addr) &&
+ nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN, params->mld_addr)))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@@ -19762,6 +19877,17 @@ void cfg80211_update_owe_info_event(struct net_device *netdev,
nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
goto nla_put_failure;
+ if (owe_info->assoc_link_id != -1) {
+ if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+ owe_info->assoc_link_id))
+ goto nla_put_failure;
+
+ if (!is_zero_ether_addr(owe_info->peer_mld_addr) &&
+ nla_put(msg, NL80211_ATTR_MLD_ADDR, ETH_ALEN,
+ owe_info->peer_mld_addr))
+ goto nla_put_failure;
+ }
+
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index ba9457e94c43..0278d817bb02 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -114,7 +114,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
enum nl80211_radar_event event,
struct net_device *netdev, gfp_t gfp);
-void nl80211_send_ap_stopped(struct wireless_dev *wdev);
+void nl80211_send_ap_stopped(struct wireless_dev *wdev, unsigned int link_id);
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index af65196c916e..0d40d6af7e10 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3160,6 +3160,9 @@ static void reg_process_self_managed_hint(struct wiphy *wiphy)
request.alpha2[1] = regd->alpha2[1];
request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
+ if (wiphy->flags & WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER)
+ reg_call_notifier(wiphy, &request);
+
nl80211_send_wiphy_reg_change_event(&request);
}
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 123248b2c0be..28ce13840a88 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -285,6 +285,15 @@ void cfg80211_conn_work(struct work_struct *work)
wiphy_unlock(&rdev->wiphy);
}
+static void cfg80211_step_auth_next(struct cfg80211_conn *conn,
+ struct cfg80211_bss *bss)
+{
+ memcpy(conn->bssid, bss->bssid, ETH_ALEN);
+ conn->params.bssid = conn->bssid;
+ conn->params.channel = bss->channel;
+ conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+}
+
/* Returned bss is reference counted and must be cleaned up appropriately. */
static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
{
@@ -302,10 +311,7 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
if (!bss)
return NULL;
- memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
- wdev->conn->params.bssid = wdev->conn->bssid;
- wdev->conn->params.channel = bss->channel;
- wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
+ cfg80211_step_auth_next(wdev->conn, bss);
schedule_work(&rdev->conn_work);
return bss;
@@ -597,7 +603,12 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
wdev->conn->params.ssid_len = wdev->u.client.ssid_len;
/* see if we have the bss already */
- bss = cfg80211_get_conn_bss(wdev);
+ bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
+ wdev->conn->params.bssid,
+ wdev->conn->params.ssid,
+ wdev->conn->params.ssid_len,
+ wdev->conn_bss_type,
+ IEEE80211_PRIVACY(wdev->conn->params.privacy));
if (prev_bssid) {
memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
@@ -608,6 +619,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
if (bss) {
enum nl80211_timeout_reason treason;
+ cfg80211_step_auth_next(wdev->conn, bss);
err = cfg80211_conn_do_work(wdev, &treason);
cfg80211_put_bss(wdev->wiphy, bss);
} else {
@@ -724,6 +736,7 @@ void __cfg80211_connect_result(struct net_device *dev,
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
const struct element *country_elem = NULL;
+ const struct element *ssid;
const u8 *country_data;
u8 country_datalen;
#ifdef CONFIG_CFG80211_WEXT
@@ -882,6 +895,22 @@ void __cfg80211_connect_result(struct net_device *dev,
country_data, country_datalen);
kfree(country_data);
+ if (!wdev->u.client.ssid_len) {
+ rcu_read_lock();
+ for_each_valid_link(cr, link) {
+ ssid = ieee80211_bss_get_elem(cr->links[link].bss,
+ WLAN_EID_SSID);
+
+ if (!ssid || !ssid->datalen)
+ continue;
+
+ memcpy(wdev->u.client.ssid, ssid->data, ssid->datalen);
+ wdev->u.client.ssid_len = ssid->datalen;
+ break;
+ }
+ rcu_read_unlock();
+ }
+
return;
out:
for_each_valid_link(cr, link)
@@ -1464,6 +1493,15 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
} else {
if (WARN_ON(connkeys))
return -EINVAL;
+
+ /* connect can point to wdev->wext.connect which
+ * can hold key data from a previous connection
+ */
+ connect->key = NULL;
+ connect->key_len = 0;
+ connect->key_idx = 0;
+ connect->crypto.cipher_group = 0;
+ connect->crypto.n_ciphers_pairwise = 0;
}
wdev->connect_keys = connkeys;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index a405c3edbc47..ca7474eec723 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -19,8 +19,6 @@
else \
eth_zero_addr(__entry->entry_mac); \
} while (0)
-#define MAC_PR_FMT "%pM"
-#define MAC_PR_ARG(entry_mac) (__entry->entry_mac)
#define MAXNAME 32
#define WIPHY_ENTRY __array(char, wiphy_name, 32)
@@ -454,10 +452,10 @@ DECLARE_EVENT_CLASS(key_handle,
__entry->pairwise = pairwise;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
- "key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+ "key_index: %u, pairwise: %s, mac addr: %pM",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
__entry->key_index, BOOL_TO_STR(__entry->pairwise),
- MAC_PR_ARG(mac_addr))
+ __entry->mac_addr)
);
DEFINE_EVENT(key_handle, rdev_get_key,
@@ -496,10 +494,10 @@ TRACE_EVENT(rdev_add_key,
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
"key_index: %u, mode: %u, pairwise: %s, "
- "mac addr: " MAC_PR_FMT,
+ "mac addr: %pM",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
__entry->key_index, __entry->mode,
- BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
+ BOOL_TO_STR(__entry->pairwise), __entry->mac_addr)
);
TRACE_EVENT(rdev_set_default_key,
@@ -813,11 +811,11 @@ DECLARE_EVENT_CLASS(station_add_change,
__entry->opmode_notif_used =
params->link_sta_params.opmode_notif_used;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: %pM"
", station flags mask: %u, station flags set: %u, "
"station modify mask: %u, listen interval: %d, aid: %u, "
"plink action: %u, plink state: %u, uapsd queues: %u, vlan:%s",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sta_mac,
__entry->sta_flags_mask, __entry->sta_flags_set,
__entry->sta_modify_mask, __entry->listen_interval,
__entry->aid, __entry->plink_action, __entry->plink_state,
@@ -849,8 +847,8 @@ DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt,
NETDEV_ASSIGN;
MAC_ASSIGN(sta_mac, mac);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", mac: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sta_mac)
);
DECLARE_EVENT_CLASS(station_del,
@@ -871,9 +869,9 @@ DECLARE_EVENT_CLASS(station_del,
__entry->subtype = params->subtype;
__entry->reason_code = params->reason_code;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: %pM"
", subtype: %u, reason_code: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sta_mac,
__entry->subtype, __entry->reason_code)
);
@@ -909,8 +907,8 @@ TRACE_EVENT(rdev_dump_station,
MAC_ASSIGN(sta_mac, mac);
__entry->idx = _idx;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT ", idx: %d",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: %pM, idx: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sta_mac,
__entry->idx)
);
@@ -947,9 +945,9 @@ DECLARE_EVENT_CLASS(mpath_evt,
MAC_ASSIGN(dst, dst);
MAC_ASSIGN(next_hop, next_hop);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT ", next hop: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dst),
- MAC_PR_ARG(next_hop))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: %pM, next hop: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->dst,
+ __entry->next_hop)
);
DEFINE_EVENT(mpath_evt, rdev_add_mpath,
@@ -988,10 +986,9 @@ TRACE_EVENT(rdev_dump_mpath,
MAC_ASSIGN(next_hop, next_hop);
__entry->idx = _idx;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
- MAC_PR_FMT ", next hop: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
- MAC_PR_ARG(next_hop))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: %pM, next hop: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, __entry->dst,
+ __entry->next_hop)
);
TRACE_EVENT(rdev_get_mpp,
@@ -1010,9 +1007,9 @@ TRACE_EVENT(rdev_get_mpp,
MAC_ASSIGN(dst, dst);
MAC_ASSIGN(mpp, mpp);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT
- ", mpp: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG,
- MAC_PR_ARG(dst), MAC_PR_ARG(mpp))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: %pM"
+ ", mpp: %pM", WIPHY_PR_ARG, NETDEV_PR_ARG,
+ __entry->dst, __entry->mpp)
);
TRACE_EVENT(rdev_dump_mpp,
@@ -1033,10 +1030,9 @@ TRACE_EVENT(rdev_dump_mpp,
MAC_ASSIGN(mpp, mpp);
__entry->idx = _idx;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
- MAC_PR_FMT ", mpp: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
- MAC_PR_ARG(mpp))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: %pM, mpp: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, __entry->dst,
+ __entry->mpp)
);
TRACE_EVENT(rdev_return_int_mpath_info,
@@ -1243,9 +1239,9 @@ TRACE_EVENT(rdev_auth,
eth_zero_addr(__entry->bssid);
__entry->auth_type = req->auth_type;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: " MAC_PR_FMT,
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", auth type: %d, bssid: %pM",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->auth_type,
- MAC_PR_ARG(bssid))
+ __entry->bssid)
);
TRACE_EVENT(rdev_assoc,
@@ -1294,10 +1290,10 @@ TRACE_EVENT(rdev_assoc,
memcpy(__get_dynamic_array(fils_nonces),
req->fils_nonces, 2 * FILS_NONCE_LEN);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
- ", previous bssid: " MAC_PR_FMT ", use mfp: %s, flags: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
- MAC_PR_ARG(prev_bssid), BOOL_TO_STR(__entry->use_mfp),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM"
+ ", previous bssid: %pM, use mfp: %s, flags: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid,
+ __entry->prev_bssid, BOOL_TO_STR(__entry->use_mfp),
__entry->flags)
);
@@ -1317,8 +1313,8 @@ TRACE_EVENT(rdev_deauth,
MAC_ASSIGN(bssid, req->bssid);
__entry->reason_code = req->reason_code;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", reason: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM, reason: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid,
__entry->reason_code)
);
@@ -1340,9 +1336,9 @@ TRACE_EVENT(rdev_disassoc,
__entry->reason_code = req->reason_code;
__entry->local_state_change = req->local_state_change;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM"
", reason: %u, local state change: %s",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid,
__entry->reason_code,
BOOL_TO_STR(__entry->local_state_change))
);
@@ -1413,12 +1409,12 @@ TRACE_EVENT(rdev_connect,
__entry->flags = sme->flags;
MAC_ASSIGN(prev_bssid, sme->prev_bssid);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM"
", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, "
- "flags: %u, previous bssid: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid,
+ "flags: %u, previous bssid: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid, __entry->ssid,
__entry->auth_type, BOOL_TO_STR(__entry->privacy),
- __entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid))
+ __entry->wpa_versions, __entry->flags, __entry->prev_bssid)
);
TRACE_EVENT(rdev_update_connect_params,
@@ -1542,8 +1538,8 @@ TRACE_EVENT(rdev_join_ibss,
memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
memcpy(__entry->ssid, params->ssid, params->ssid_len);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM, ssid: %s",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid, __entry->ssid)
);
TRACE_EVENT(rdev_join_ocb,
@@ -1664,9 +1660,9 @@ TRACE_EVENT(rdev_set_bitrate_mask,
__entry->link_id = link_id;
MAC_ASSIGN(peer, peer);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, peer: " MAC_PR_FMT,
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, peer: %pM",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
- MAC_PR_ARG(peer))
+ __entry->peer)
);
TRACE_EVENT(rdev_update_mgmt_frame_registrations,
@@ -1810,10 +1806,10 @@ TRACE_EVENT(rdev_tdls_mgmt,
__entry->initiator = initiator;
memcpy(__get_dynamic_array(buf), buf, len);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, "
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM, action_code: %u, "
"dialog_token: %u, status_code: %u, peer_capability: %u "
"initiator: %s buf: %#.2x ",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer,
__entry->action_code, __entry->dialog_token,
__entry->status_code, __entry->peer_capability,
BOOL_TO_STR(__entry->initiator),
@@ -1893,8 +1889,8 @@ TRACE_EVENT(rdev_tdls_oper,
MAC_ASSIGN(peer, peer);
__entry->oper = oper;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", oper: %d",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM, oper: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer, __entry->oper)
);
DECLARE_EVENT_CLASS(rdev_pmksa,
@@ -1911,8 +1907,8 @@ DECLARE_EVENT_CLASS(rdev_pmksa,
NETDEV_ASSIGN;
MAC_ASSIGN(bssid, pmksa->bssid);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid)
);
TRACE_EVENT(rdev_probe_client,
@@ -1929,8 +1925,8 @@ TRACE_EVENT(rdev_probe_client,
NETDEV_ASSIGN;
MAC_ASSIGN(peer, peer);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer)
);
DEFINE_EVENT(rdev_pmksa, rdev_set_pmksa,
@@ -2051,9 +2047,9 @@ TRACE_EVENT(rdev_tx_control_port,
__entry->unencrypted = unencrypted;
__entry->link_id = link_id;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ","
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM,"
" proto: 0x%x, unencrypted: %s, link: %d",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->dest,
be16_to_cpu(__entry->proto),
BOOL_TO_STR(__entry->unencrypted),
__entry->link_id)
@@ -2392,8 +2388,8 @@ TRACE_EVENT(rdev_add_tx_ts,
__entry->user_prio = user_prio;
__entry->admitted_time = admitted_time;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d, UP %d, time %d",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM, TSID %d, UP %d, time %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer,
__entry->tsid, __entry->user_prio, __entry->admitted_time)
);
@@ -2413,8 +2409,8 @@ TRACE_EVENT(rdev_del_tx_ts,
MAC_ASSIGN(peer, peer);
__entry->tsid = tsid;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tsid)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM, TSID %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer, __entry->tsid)
);
TRACE_EVENT(rdev_tdls_channel_switch,
@@ -2435,9 +2431,9 @@ TRACE_EVENT(rdev_tdls_channel_switch,
MAC_ASSIGN(addr, addr);
CHAN_DEF_ASSIGN(chandef);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM"
" oper class %d, " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->addr,
__entry->oper_class, CHAN_DEF_PR_ARG)
);
@@ -2455,8 +2451,8 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch,
NETDEV_ASSIGN;
MAC_ASSIGN(addr, addr);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->addr)
);
TRACE_EVENT(rdev_set_pmk,
@@ -2488,9 +2484,9 @@ TRACE_EVENT(rdev_set_pmk,
pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM"
"pmk_len=%u, pmk: %s pmk_r0_name: %s", WIPHY_PR_ARG,
- NETDEV_PR_ARG, MAC_PR_ARG(aa), __entry->pmk_len,
+ NETDEV_PR_ARG, __entry->aa, __entry->pmk_len,
__print_array(__get_dynamic_array(pmk),
__get_dynamic_array_len(pmk), 1),
__entry->pmk_r0_name_len ?
@@ -2515,8 +2511,8 @@ TRACE_EVENT(rdev_del_pmk,
MAC_ASSIGN(aa, aa);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->aa)
);
TRACE_EVENT(rdev_external_auth,
@@ -2528,6 +2524,7 @@ TRACE_EVENT(rdev_external_auth,
MAC_ENTRY(bssid)
__array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1)
__field(u16, status)
+ MAC_ENTRY(mld_addr)
),
TP_fast_assign(WIPHY_ASSIGN;
NETDEV_ASSIGN;
@@ -2536,10 +2533,12 @@ TRACE_EVENT(rdev_external_auth,
memcpy(__entry->ssid, params->ssid.ssid,
params->ssid.ssid_len);
__entry->status = params->status;
+ MAC_ASSIGN(mld_addr, params->mld_addr);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
- ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
- __entry->bssid, __entry->ssid, __entry->status)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: %pM"
+ ", ssid: %s, status: %u, mld_addr: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->bssid,
+ __entry->ssid, __entry->status, __entry->mld_addr)
);
TRACE_EVENT(rdev_start_radar_detection,
@@ -2720,8 +2719,8 @@ TRACE_EVENT(rdev_update_owe_info,
__entry->status = owe_info->status;
memcpy(__get_dynamic_array(ie),
owe_info->ie, owe_info->ie_len);),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT
- " status %d", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: %pM"
+ " status %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer,
__entry->status)
);
@@ -2739,8 +2738,8 @@ TRACE_EVENT(rdev_probe_mesh_link,
NETDEV_ASSIGN;
MAC_ASSIGN(dest, dest);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->dest)
);
TRACE_EVENT(rdev_set_tid_config,
@@ -2757,8 +2756,8 @@ TRACE_EVENT(rdev_set_tid_config,
NETDEV_ASSIGN;
MAC_ASSIGN(peer, tid_conf->peer);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer)
);
TRACE_EVENT(rdev_reset_tid_config,
@@ -2777,8 +2776,8 @@ TRACE_EVENT(rdev_reset_tid_config,
MAC_ASSIGN(peer, peer);
__entry->tids = tids;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", tids: 0x%x",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tids)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: %pM, tids: 0x%x",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer, __entry->tids)
);
TRACE_EVENT(rdev_set_sar_specs,
@@ -2881,8 +2880,8 @@ DECLARE_EVENT_CLASS(cfg80211_netdev_mac_evt,
NETDEV_ASSIGN;
MAC_ASSIGN(macaddr, macaddr);
),
- TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
- NETDEV_PR_ARG, MAC_PR_ARG(macaddr))
+ TP_printk(NETDEV_PR_FMT ", mac: %pM",
+ NETDEV_PR_ARG, __entry->macaddr)
);
DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_notify_new_peer_candidate,
@@ -2920,8 +2919,8 @@ TRACE_EVENT(cfg80211_send_rx_assoc,
MAC_ASSIGN(ap_addr,
data->ap_mld_addr ?: data->links[0].bss->bssid);
),
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT,
- NETDEV_PR_ARG, MAC_PR_ARG(ap_addr))
+ TP_printk(NETDEV_PR_FMT ", %pM",
+ NETDEV_PR_ARG, __entry->ap_addr)
);
DECLARE_EVENT_CLASS(netdev_frame_event,
@@ -2981,8 +2980,8 @@ DECLARE_EVENT_CLASS(netdev_mac_evt,
NETDEV_ASSIGN;
MAC_ASSIGN(mac, mac)
),
- TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT,
- NETDEV_PR_ARG, MAC_PR_ARG(mac))
+ TP_printk(NETDEV_PR_FMT ", mac: %pM",
+ NETDEV_PR_ARG, __entry->mac)
);
DEFINE_EVENT(netdev_mac_evt, cfg80211_send_auth_timeout,
@@ -3004,8 +3003,8 @@ TRACE_EVENT(cfg80211_send_assoc_failure,
MAC_ASSIGN(ap_addr, data->ap_mld_addr ?: data->bss[0]->bssid);
__entry->timeout = data->timeout;
),
- TP_printk(NETDEV_PR_FMT ", mac: " MAC_PR_FMT ", timeout: %d",
- NETDEV_PR_ARG, MAC_PR_ARG(ap_addr), __entry->timeout)
+ TP_printk(NETDEV_PR_FMT ", mac: %pM, timeout: %d",
+ NETDEV_PR_ARG, __entry->ap_addr, __entry->timeout)
);
TRACE_EVENT(cfg80211_michael_mic_failure,
@@ -3027,8 +3026,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure,
if (tsc)
memcpy(__entry->tsc, tsc, 6);
),
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm",
- NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type,
+ TP_printk(NETDEV_PR_FMT ", %pM, key type: %d, key id: %d, tsc: %pm",
+ NETDEV_PR_ARG, __entry->addr, __entry->key_type,
__entry->key_id, __entry->tsc)
);
@@ -3104,8 +3103,8 @@ TRACE_EVENT(cfg80211_new_sta,
MAC_ASSIGN(mac_addr, mac_addr);
SINFO_ASSIGN;
),
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT,
- NETDEV_PR_ARG, MAC_PR_ARG(mac_addr))
+ TP_printk(NETDEV_PR_FMT ", %pM",
+ NETDEV_PR_ARG, __entry->mac_addr)
);
DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_del_sta,
@@ -3182,8 +3181,8 @@ TRACE_EVENT(cfg80211_rx_control_port,
__entry->proto = be16_to_cpu(skb->protocol);
__entry->unencrypted = unencrypted;
),
- TP_printk(NETDEV_PR_FMT ", len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s",
- NETDEV_PR_ARG, __entry->len, MAC_PR_ARG(from),
+ TP_printk(NETDEV_PR_FMT ", len=%d, %pM, proto: 0x%x, unencrypted: %s",
+ NETDEV_PR_ARG, __entry->len, __entry->from,
__entry->proto, BOOL_TO_STR(__entry->unencrypted))
);
@@ -3245,39 +3244,47 @@ TRACE_EVENT(cfg80211_chandef_dfs_required,
TRACE_EVENT(cfg80211_ch_switch_notify,
TP_PROTO(struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id),
- TP_ARGS(netdev, chandef, link_id),
+ unsigned int link_id,
+ u16 punct_bitmap),
+ TP_ARGS(netdev, chandef, link_id, punct_bitmap),
TP_STRUCT__entry(
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field(unsigned int, link_id)
+ __field(u16, punct_bitmap)
),
TP_fast_assign(
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->link_id = link_id;
+ __entry->punct_bitmap = punct_bitmap;
),
- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d",
- NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id)
+ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d, punct_bitmap:%u",
+ NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id,
+ __entry->punct_bitmap)
);
TRACE_EVENT(cfg80211_ch_switch_started_notify,
TP_PROTO(struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- unsigned int link_id),
- TP_ARGS(netdev, chandef, link_id),
+ unsigned int link_id,
+ u16 punct_bitmap),
+ TP_ARGS(netdev, chandef, link_id, punct_bitmap),
TP_STRUCT__entry(
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field(unsigned int, link_id)
+ __field(u16, punct_bitmap)
),
TP_fast_assign(
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->link_id = link_id;
+ __entry->punct_bitmap = punct_bitmap;
),
- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d",
- NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id)
+ TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d, punct_bitmap:%u",
+ NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id,
+ __entry->punct_bitmap)
);
TRACE_EVENT(cfg80211_radar_event,
@@ -3324,7 +3331,7 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
NETDEV_ASSIGN;
MAC_ASSIGN(addr, addr);
),
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
+ TP_printk(NETDEV_PR_FMT ", %pM", NETDEV_PR_ARG, __entry->addr)
);
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
@@ -3351,8 +3358,8 @@ TRACE_EVENT(cfg80211_ibss_joined,
MAC_ASSIGN(bssid, bssid);
CHAN_ASSIGN(channel);
),
- TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
- NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+ TP_printk(NETDEV_PR_FMT ", bssid: %pM, " CHAN_PR_FMT,
+ NETDEV_PR_ARG, __entry->bssid, CHAN_PR_ARG)
);
TRACE_EVENT(cfg80211_probe_status,
@@ -3371,8 +3378,8 @@ TRACE_EVENT(cfg80211_probe_status,
__entry->cookie = cookie;
__entry->acked = acked;
),
- TP_printk(NETDEV_PR_FMT " addr:" MAC_PR_FMT ", cookie: %llu, acked: %s",
- NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->cookie,
+ TP_printk(NETDEV_PR_FMT " addr:%pM, cookie: %llu, acked: %s",
+ NETDEV_PR_ARG, __entry->addr, __entry->cookie,
BOOL_TO_STR(__entry->acked))
);
@@ -3389,8 +3396,8 @@ TRACE_EVENT(cfg80211_cqm_pktloss_notify,
MAC_ASSIGN(peer, peer);
__entry->num_packets = num_packets;
),
- TP_printk(NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", num of lost packets: %u",
- NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->num_packets)
+ TP_printk(NETDEV_PR_FMT ", peer: %pM, num of lost packets: %u",
+ NETDEV_PR_ARG, __entry->peer, __entry->num_packets)
);
DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_gtk_rekey_notify,
@@ -3414,8 +3421,8 @@ TRACE_EVENT(cfg80211_pmksa_candidate_notify,
MAC_ASSIGN(bssid, bssid);
__entry->preauth = preauth;
),
- TP_printk(NETDEV_PR_FMT ", index:%d, bssid: " MAC_PR_FMT ", pre auth: %s",
- NETDEV_PR_ARG, __entry->index, MAC_PR_ARG(bssid),
+ TP_printk(NETDEV_PR_FMT ", index:%d, bssid: %pM, pre auth: %s",
+ NETDEV_PR_ARG, __entry->index, __entry->bssid,
BOOL_TO_STR(__entry->preauth))
);
@@ -3455,8 +3462,8 @@ TRACE_EVENT(cfg80211_tdls_oper_request,
__entry->oper = oper;
__entry->reason_code = reason_code;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", oper: %d, reason_code %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->oper,
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: %pM, oper: %d, reason_code %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer, __entry->oper,
__entry->reason_code)
);
@@ -3494,10 +3501,10 @@ TRACE_EVENT(cfg80211_scan_done,
MAC_ASSIGN(tsf_bssid, info->tsf_bssid);
}
),
- TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: " MAC_PR_FMT,
+ TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: %pM",
BOOL_TO_STR(__entry->aborted),
(unsigned long long)__entry->scan_start_tsf,
- MAC_PR_ARG(tsf_bssid))
+ __entry->tsf_bssid)
);
DECLARE_EVENT_CLASS(wiphy_id_evt,
@@ -3546,9 +3553,9 @@ TRACE_EVENT(cfg80211_get_bss,
__entry->bss_type = bss_type;
__entry->privacy = privacy;
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT ", %pM"
", buf: %#.2x, bss_type: %d, privacy: %d",
- WIPHY_PR_ARG, CHAN_PR_ARG, MAC_PR_ARG(bssid),
+ WIPHY_PR_ARG, CHAN_PR_ARG, __entry->bssid,
((u8 *)__get_dynamic_array(ssid))[0], __entry->bss_type,
__entry->privacy)
);
@@ -3579,11 +3586,11 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
MAC_ASSIGN(parent_bssid, data->parent_bssid);
),
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT
- "(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: "
- MAC_PR_FMT, WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
+ "(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: %pM",
+ WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
__entry->signal, (unsigned long long)__entry->ts_boottime,
(unsigned long long)__entry->parent_tsf,
- MAC_PR_ARG(parent_bssid))
+ __entry->parent_bssid)
);
DECLARE_EVENT_CLASS(cfg80211_bss_evt,
@@ -3597,7 +3604,7 @@ DECLARE_EVENT_CLASS(cfg80211_bss_evt,
MAC_ASSIGN(bssid, pub->bssid);
CHAN_ASSIGN(pub->channel);
),
- TP_printk(MAC_PR_FMT ", " CHAN_PR_FMT, MAC_PR_ARG(bssid), CHAN_PR_ARG)
+ TP_printk("%pM, " CHAN_PR_FMT, __entry->bssid, CHAN_PR_ARG)
);
DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss,
@@ -3689,8 +3696,8 @@ TRACE_EVENT(cfg80211_ft_event,
memcpy(__get_dynamic_array(ric_ies), ft_event->ric_ies,
ft_event->ric_ies_len);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap))
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->target_ap)
);
TRACE_EVENT(cfg80211_stop_iface,
@@ -3724,10 +3731,10 @@ TRACE_EVENT(cfg80211_pmsr_report,
__entry->cookie = cookie;
MAC_ASSIGN(addr, addr);
),
- TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld, " MAC_PR_FMT,
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld, %pM",
WIPHY_PR_ARG, WDEV_PR_ARG,
(unsigned long long)__entry->cookie,
- MAC_PR_ARG(addr))
+ __entry->addr)
);
TRACE_EVENT(cfg80211_pmsr_complete,
@@ -3749,20 +3756,30 @@ TRACE_EVENT(cfg80211_pmsr_complete,
);
TRACE_EVENT(cfg80211_update_owe_info_event,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- struct cfg80211_update_owe_info *owe_info),
- TP_ARGS(wiphy, netdev, owe_info),
- TP_STRUCT__entry(WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(peer)
- __dynamic_array(u8, ie, owe_info->ie_len)),
- TP_fast_assign(WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(peer, owe_info->peer);
- memcpy(__get_dynamic_array(ie), owe_info->ie,
- owe_info->ie_len);),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_update_owe_info *owe_info),
+ TP_ARGS(wiphy, netdev, owe_info),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ __dynamic_array(u8, ie, owe_info->ie_len)
+ __field(int, assoc_link_id)
+ MAC_ENTRY(peer_mld_addr)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, owe_info->peer);
+ memcpy(__get_dynamic_array(ie), owe_info->ie,
+ owe_info->ie_len);
+ __entry->assoc_link_id = owe_info->assoc_link_id;
+ MAC_ASSIGN(peer_mld_addr, owe_info->peer_mld_addr);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: %pM,"
+ " assoc_link_id: %d, peer_mld_addr: %pM",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->peer,
+ __entry->assoc_link_id, __entry->peer_mld_addr)
);
TRACE_EVENT(cfg80211_bss_color_notify,
@@ -3800,8 +3817,8 @@ TRACE_EVENT(cfg80211_assoc_comeback,
MAC_ASSIGN(ap_addr, ap_addr);
__entry->timeout = timeout;
),
- TP_printk(WDEV_PR_FMT ", " MAC_PR_FMT ", timeout: %u TUs",
- WDEV_PR_ARG, MAC_PR_ARG(ap_addr), __entry->timeout)
+ TP_printk(WDEV_PR_FMT ", %pM, timeout: %u TUs",
+ WDEV_PR_ARG, __entry->ap_addr, __entry->timeout)
);
DECLARE_EVENT_CLASS(link_station_add_mod,
@@ -3859,10 +3876,10 @@ DECLARE_EVENT_CLASS(link_station_add_mod,
memcpy(__get_dynamic_array(eht_capa), params->eht_capa,
params->eht_capa_len);
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
- ", link mac: " MAC_PR_FMT ", link id: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(mld_mac),
- MAC_PR_ARG(link_mac), __entry->link_id)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: %pM"
+ ", link mac: %pM, link id: %u",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mld_mac,
+ __entry->link_mac, __entry->link_id)
);
DEFINE_EVENT(link_station_add_mod, rdev_add_link_station,
@@ -3895,9 +3912,9 @@ TRACE_EVENT(rdev_del_link_station,
memcpy(__entry->mld_mac, params->mld_mac, 6);
__entry->link_id = params->link_id;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: %pM"
", link id: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(mld_mac),
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->mld_mac,
__entry->link_id)
);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 38d3b434c18c..d1a89e82ead0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -542,6 +542,64 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
}
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
+bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
+{
+ const __be16 *hdr_proto = hdr + ETH_ALEN;
+
+ if (!(ether_addr_equal(hdr, rfc1042_header) &&
+ *hdr_proto != htons(ETH_P_AARP) &&
+ *hdr_proto != htons(ETH_P_IPX)) &&
+ !ether_addr_equal(hdr, bridge_tunnel_header))
+ return false;
+
+ *proto = *hdr_proto;
+
+ return true;
+}
+EXPORT_SYMBOL(ieee80211_get_8023_tunnel_proto);
+
+int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb)
+{
+ const void *mesh_addr;
+ struct {
+ struct ethhdr eth;
+ u8 flags;
+ } payload;
+ int hdrlen;
+ int ret;
+
+ ret = skb_copy_bits(skb, 0, &payload, sizeof(payload));
+ if (ret)
+ return ret;
+
+ hdrlen = sizeof(payload.eth) + __ieee80211_get_mesh_hdrlen(payload.flags);
+
+ if (likely(pskb_may_pull(skb, hdrlen + 8) &&
+ ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
+ &payload.eth.h_proto)))
+ hdrlen += ETH_ALEN + 2;
+ else if (!pskb_may_pull(skb, hdrlen))
+ return -EINVAL;
+
+ mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN;
+ switch (payload.flags & MESH_FLAGS_AE) {
+ case MESH_FLAGS_AE_A4:
+ memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN);
+ break;
+ case MESH_FLAGS_AE_A5_A6:
+ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN);
+ break;
+ default:
+ break;
+ }
+
+ pskb_pull(skb, hdrlen - sizeof(payload.eth));
+ memcpy(skb->data, &payload.eth, sizeof(payload.eth));
+
+ return 0;
+}
+EXPORT_SYMBOL(ieee80211_strip_8023_mesh_hdr);
+
int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
const u8 *addr, enum nl80211_iftype iftype,
u8 data_offset, bool is_amsdu)
@@ -553,7 +611,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
} payload;
struct ethhdr tmp;
u16 hdrlen;
- u8 mesh_flags = 0;
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
return -1;
@@ -574,12 +631,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
- if (iftype == NL80211_IFTYPE_MESH_POINT &&
- skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0)
- return -1;
-
- mesh_flags &= MESH_FLAGS_AE;
-
switch (hdr->frame_control &
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
case cpu_to_le16(IEEE80211_FCTL_TODS):
@@ -593,17 +644,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
iftype != NL80211_IFTYPE_AP_VLAN &&
iftype != NL80211_IFTYPE_STATION))
return -1;
- if (iftype == NL80211_IFTYPE_MESH_POINT) {
- if (mesh_flags == MESH_FLAGS_AE_A4)
- return -1;
- if (mesh_flags == MESH_FLAGS_AE_A5_A6 &&
- skb_copy_bits(skb, hdrlen +
- offsetof(struct ieee80211s_hdr, eaddr1),
- tmp.h_dest, 2 * ETH_ALEN) < 0)
- return -1;
-
- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
- }
break;
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
if ((iftype != NL80211_IFTYPE_STATION &&
@@ -612,16 +652,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
(is_multicast_ether_addr(tmp.h_dest) &&
ether_addr_equal(tmp.h_source, addr)))
return -1;
- if (iftype == NL80211_IFTYPE_MESH_POINT) {
- if (mesh_flags == MESH_FLAGS_AE_A5_A6)
- return -1;
- if (mesh_flags == MESH_FLAGS_AE_A4 &&
- skb_copy_bits(skb, hdrlen +
- offsetof(struct ieee80211s_hdr, eaddr1),
- tmp.h_source, ETH_ALEN) < 0)
- return -1;
- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
- }
break;
case cpu_to_le16(0):
if (iftype != NL80211_IFTYPE_ADHOC &&
@@ -631,15 +661,11 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
break;
}
- if (likely(skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
- ((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
- payload.proto != htons(ETH_P_AARP) &&
- payload.proto != htons(ETH_P_IPX)) ||
- ether_addr_equal(payload.hdr, bridge_tunnel_header)))) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType */
+ if (likely(!is_amsdu && iftype != NL80211_IFTYPE_MESH_POINT &&
+ skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
+ ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation */
hdrlen += ETH_ALEN + 2;
- tmp.h_proto = payload.proto;
skb_postpull_rcsum(skb, &payload, ETH_ALEN + 2);
} else {
tmp.h_proto = htons(skb->len - hdrlen);
@@ -711,7 +737,8 @@ __ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame,
static struct sk_buff *
__ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
- int offset, int len, bool reuse_frag)
+ int offset, int len, bool reuse_frag,
+ int min_len)
{
struct sk_buff *frame;
int cur_len = len;
@@ -725,7 +752,7 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
* in the stack later.
*/
if (reuse_frag)
- cur_len = min_t(int, len, 32);
+ cur_len = min_t(int, len, min_len);
/*
* Allocate and reserve two bytes more for payload
@@ -735,6 +762,7 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
if (!frame)
return NULL;
+ frame->priority = skb->priority;
skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
@@ -748,28 +776,72 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
return frame;
}
+bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr)
+{
+ int offset = 0, remaining, subframe_len, padding;
+
+ for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
+ struct {
+ __be16 len;
+ u8 mesh_flags;
+ } hdr;
+ u16 len;
+
+ if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
+ return false;
+
+ if (mesh_hdr)
+ len = le16_to_cpu(*(__le16 *)&hdr.len) +
+ __ieee80211_get_mesh_hdrlen(hdr.mesh_flags);
+ else
+ len = ntohs(hdr.len);
+
+ subframe_len = sizeof(struct ethhdr) + len;
+ padding = (4 - subframe_len) & 0x3;
+ remaining = skb->len - offset;
+
+ if (subframe_len > remaining)
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(ieee80211_is_valid_amsdu);
+
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
const unsigned int extra_headroom,
- const u8 *check_da, const u8 *check_sa)
+ const u8 *check_da, const u8 *check_sa,
+ bool mesh_control)
{
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
- u16 ethertype;
- u8 *payload;
int offset = 0, remaining;
- struct ethhdr eth;
+ struct {
+ struct ethhdr eth;
+ uint8_t flags;
+ } hdr;
bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
bool reuse_skb = false;
bool last = false;
+ int copy_len = sizeof(hdr.eth);
+
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
+ copy_len = sizeof(hdr);
while (!last) {
unsigned int subframe_len;
- int len;
+ int len, mesh_len = 0;
u8 padding;
- skb_copy_bits(skb, offset, &eth, sizeof(eth));
- len = ntohs(eth.h_proto);
+ skb_copy_bits(skb, offset, &hdr, copy_len);
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
+ mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
+ if (mesh_control)
+ len = le16_to_cpu(*(__le16 *)&hdr.eth.h_proto) + mesh_len;
+ else
+ len = ntohs(hdr.eth.h_proto);
+
subframe_len = sizeof(struct ethhdr) + len;
padding = (4 - subframe_len) & 0x3;
@@ -778,16 +850,16 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
if (subframe_len > remaining)
goto purge;
/* mitigate A-MSDU aggregation injection attacks */
- if (ether_addr_equal(eth.h_dest, rfc1042_header))
+ if (ether_addr_equal(hdr.eth.h_dest, rfc1042_header))
goto purge;
offset += sizeof(struct ethhdr);
last = remaining <= subframe_len + padding;
/* FIXME: should we really accept multicast DA? */
- if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
- !ether_addr_equal(check_da, eth.h_dest)) ||
- (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
+ if ((check_da && !is_multicast_ether_addr(hdr.eth.h_dest) &&
+ !ether_addr_equal(check_da, hdr.eth.h_dest)) ||
+ (check_sa && !ether_addr_equal(check_sa, hdr.eth.h_source))) {
offset += len + padding;
continue;
}
@@ -799,7 +871,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
reuse_skb = true;
} else {
frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
- reuse_frag);
+ reuse_frag, 32 + mesh_len);
if (!frame)
goto purge;
@@ -810,16 +882,11 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
frame->dev = skb->dev;
frame->priority = skb->priority;
- payload = frame->data;
- ethertype = (payload[6] << 8) | payload[7];
- if (likely((ether_addr_equal(payload, rfc1042_header) &&
- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
- ether_addr_equal(payload, bridge_tunnel_header))) {
- eth.h_proto = htons(ethertype);
+ if (likely(iftype != NL80211_IFTYPE_MESH_POINT &&
+ ieee80211_get_8023_tunnel_proto(frame->data, &hdr.eth.h_proto)))
skb_pull(frame, ETH_ALEN + 2);
- }
- memcpy(skb_push(frame, sizeof(eth)), &eth, sizeof(eth));
+ memcpy(skb_push(frame, sizeof(hdr.eth)), &hdr.eth, sizeof(hdr.eth));
__skb_queue_tail(list, frame);
}