* [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios
@ 2024-10-02 11:45 Felix Fietkau
2024-10-02 11:45 ` [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios Felix Fietkau
` (10 more replies)
0 siblings, 11 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
This series adds support for restricting vifs to a set of radios.
The allowed radios mask is used to restrict scanning, off-channel activity,
and can be used by the driver to selectively enable monitoring and manage
radio state.
It also adds support for monitoring on multiple channels at the same time.
Changes since RFC:
- split cfg80211 and mac80211 changes
- remove mac80211 per-radio tracking for monitor state
- remove per-radio start/stop calls
- remove radio index from rx status
- rewrite multi-channel monitor support
Felix Fietkau (11):
wifi: cfg80211: add option for vif allowed radios
wifi: mac80211: use vif radio mask to limit ibss scan frequencies
wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel
wifi: cfg80211: report per wiphy radio antenna mask
wifi: mac80211: remove status->ampdu_delimiter_crc
wifi: cfg80211: pass net_device to .set_monitor_channel
wifi: mac80211: add flag to opt out of virtual monitor support
wifi: cfg80211: add monitor SKIP_TX flag
wifi: mac80211: add support for the monitor SKIP_TX flag
wifi: mac80211: refactor ieee80211_rx_monitor
wifi: mac80211: filter on monitor interfaces based on configured channel
drivers/net/wireless/ath/wil6210/cfg80211.c | 1 +-
drivers/net/wireless/marvell/libertas/cfg.c | 1 +-
drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 +-
include/net/cfg80211.h | 18 ++++-
include/net/mac80211.h | 12 +--
include/uapi/linux/nl80211.h | 10 ++-
net/mac80211/cfg.c | 45 ++++++----
net/mac80211/chan.c | 27 +++++-
net/mac80211/debugfs.c | 1 +-
net/mac80211/driver-ops.c | 1 +-
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/iface.c | 24 +++--
net/mac80211/rx.c | 71 ++++++++-------
net/mac80211/scan.c | 10 +-
net/mac80211/status.c | 5 +-
net/mac80211/tx.c | 6 +-
net/mac80211/util.c | 14 ++-
net/wireless/chan.c | 3 +-
net/wireless/core.h | 1 +-
net/wireless/nl80211.c | 65 +++++++++++---
net/wireless/rdev-ops.h | 5 +-
net/wireless/scan.c | 10 +-
net/wireless/trace.h | 8 +-
net/wireless/util.c | 29 ++++++-
net/wireless/wext-compat.c | 2 +-
25 files changed, 280 insertions(+), 94 deletions(-)
base-commit: 5a4d42c1688c88f3be6aef46b0ea6c32694cd2b8
--
git-series 0.9.1
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 12:55 ` Johannes Berg
2024-10-02 11:45 ` [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies Felix Fietkau
` (9 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
This allows users to prevent a vif from affecting radios other than the
configured ones. This can be useful in cases where e.g. an AP is running
on one radio, and triggering a scan on another radio should not disturb it.
Changing the allowed radios list for a vif is supported, but only while
it is down.
While it is possible to achieve the same by always explicitly specifying
a frequency list for scan requests and ensuring that the wrong channel/band
is never accidentally set on an unrelated interface, this change makes
multi-radio wiphy setups a lot easier to deal with for CLI users.
By itself, this patch only enforces the radio mask for scanning requests.
Follow-up changes build on this to limit configurable frequencies and
remain-on-channel requests.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/cfg80211.h | 12 ++++++++-
include/uapi/linux/nl80211.h | 5 +++-
net/wireless/nl80211.c | 58 +++++++++++++++++++++++++++++++------
net/wireless/scan.c | 10 ++++--
net/wireless/util.c | 29 +++++++++++++++++++-
5 files changed, 103 insertions(+), 11 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 69ec1eb41a09..73df4a8e8cce 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6223,6 +6223,7 @@ enum ieee80211_ap_reg_power {
* entered.
* @links.cac_time_ms: CAC time in ms
* @valid_links: bitmap describing what elements of @links are valid
+ * @radio_mask: Bitmask of radios that this interface is allowed to operate on.
*/
struct wireless_dev {
struct wiphy *wiphy;
@@ -6335,6 +6336,8 @@ struct wireless_dev {
unsigned int cac_time_ms;
} links[IEEE80211_MLD_MAX_NUM_LINKS];
u16 valid_links;
+
+ u32 radio_mask;
};
static inline const u8 *wdev_address(struct wireless_dev *wdev)
@@ -6521,6 +6524,15 @@ bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio,
const struct cfg80211_chan_def *chandef);
/**
+ * cfg80211_wdev_channel_allowed - Check if the wdev may use the channel
+ *
+ * @wdev: the wireless device
+ * @chan: channel to check
+ */
+bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev,
+ struct ieee80211_channel *chan);
+
+/**
* ieee80211_get_response_rate - get basic rate for a given rate
*
* @sband: the band to look for rates in
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f97f5adc8d51..d31ccee99cc7 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2868,6 +2868,9 @@ enum nl80211_commands {
* nested item, it contains attributes defined in
* &enum nl80211_if_combination_attrs.
*
+ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
+ * A value of 0 means all radios.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3416,6 +3419,8 @@ enum nl80211_attrs {
NL80211_ATTR_WIPHY_RADIOS,
NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
+ NL80211_ATTR_VIF_RADIO_MASK,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9ab777e0bd4d..8f86b23e106a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -829,6 +829,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLO_TTLM_DLINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
[NL80211_ATTR_MLO_TTLM_ULINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
[NL80211_ATTR_ASSOC_SPP_AMSDU] = { .type = NLA_FLAG },
+ [NL80211_ATTR_VIF_RADIO_MASK] = { .type = NLA_U32 },
};
/* policy for the key attributes */
@@ -3996,7 +3997,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
nla_put_u32(msg, NL80211_ATTR_GENERATION,
rdev->devlist_generation ^
(cfg80211_rdev_list_generation << 2)) ||
- nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
+ nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr) ||
+ nla_put_u32(msg, NL80211_ATTR_VIF_RADIO_MASK, wdev->radio_mask))
goto nla_put_failure;
if (rdev->ops->get_channel && !wdev->valid_links) {
@@ -4312,6 +4314,27 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
return -EOPNOTSUPP;
}
+static int nl80211_parse_vif_radio_mask(struct genl_info *info,
+ u32 *radio_mask)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct nlattr *attr = info->attrs[NL80211_ATTR_VIF_RADIO_MASK];
+ u32 mask, allowed;
+
+ if (!attr)
+ return 0;
+
+ allowed = BIT(rdev->wiphy.n_radio) - 1;
+ mask = nla_get_u32(attr);
+ if (mask & ~allowed)
+ return -EINVAL;
+ if (!mask)
+ mask = allowed;
+ *radio_mask = mask;
+
+ return 1;
+}
+
static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -4319,6 +4342,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
int err;
enum nl80211_iftype otype, ntype;
struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ u32 radio_mask = 0;
bool change = false;
memset(¶ms, 0, sizeof(params));
@@ -4332,8 +4357,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_MESH_ID]) {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
if (ntype != NL80211_IFTYPE_MESH_POINT)
return -EINVAL;
if (otype != NL80211_IFTYPE_MESH_POINT)
@@ -4364,6 +4387,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
if (err > 0)
change = true;
+ err = nl80211_parse_vif_radio_mask(info, &radio_mask);
+ if (err < 0)
+ return err;
+ if (radio_mask && netif_running(dev))
+ return -EBUSY;
+
if (change)
err = cfg80211_change_iface(rdev, dev, ntype, ¶ms);
else
@@ -4372,11 +4401,11 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
if (!err && params.use_4addr != -1)
dev->ieee80211_ptr->use_4addr = params.use_4addr;
- if (change && !err) {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
+ if (radio_mask)
+ wdev->radio_mask = radio_mask;
+ if (change && !err)
nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
- }
return err;
}
@@ -4387,6 +4416,7 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
struct vif_params params;
struct wireless_dev *wdev;
struct sk_buff *msg;
+ u32 radio_mask;
int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -4424,6 +4454,11 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
if (err < 0)
return err;
+ radio_mask = BIT(rdev->wiphy.n_radio) - 1;
+ err = nl80211_parse_vif_radio_mask(info, &radio_mask);
+ if (err < 0)
+ return err;
+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return -ENOMEM;
@@ -4465,6 +4500,8 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
break;
}
+ wdev->radio_mask = radio_mask;
+
if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
nlmsg_free(msg);
@@ -9180,6 +9217,9 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
lockdep_assert_wiphy(wdev->wiphy);
+ if (!cfg80211_wdev_channel_allowed(wdev, chan))
+ return false;
+
if (!cfg80211_beaconing_iface_active(wdev))
return true;
@@ -9392,7 +9432,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
/* ignore disabled channels */
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ !cfg80211_wdev_channel_allowed(wdev, chan))
continue;
request->channels[i] = chan;
@@ -9412,7 +9453,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
chan = &wiphy->bands[band]->channels[j];
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ !cfg80211_wdev_channel_allowed(wdev, chan))
continue;
request->channels[i] = chan;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 59a90bf3c0d6..279af47651c1 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -956,7 +956,8 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
struct ieee80211_channel *chan =
ieee80211_get_channel(&rdev->wiphy, ap->center_freq);
- if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED ||
+ !cfg80211_wdev_channel_allowed(rdev_req->wdev, chan))
continue;
for (i = 0; i < rdev_req->n_channels; i++) {
@@ -3515,9 +3516,12 @@ int cfg80211_wext_siwscan(struct net_device *dev,
continue;
for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
+ struct ieee80211_channel *chan;
+
/* ignore disabled channels */
- if (wiphy->bands[band]->channels[j].flags &
- IEEE80211_CHAN_DISABLED)
+ chan = &wiphy->bands[band]->channels[j];
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ !cfg80211_wdev_channel_allowed(creq->wdev, chan))
continue;
/* If we have a wireless request structure and the
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f49b55724f83..9ccc9602ac25 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2923,3 +2923,32 @@ bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio,
return true;
}
EXPORT_SYMBOL(cfg80211_radio_chandef_valid);
+
+bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev,
+ struct ieee80211_channel *chan)
+{
+ struct wiphy *wiphy = wdev->wiphy;
+ const struct wiphy_radio *radio;
+ struct cfg80211_chan_def chandef;
+ u32 radio_mask;
+ int i;
+
+ radio_mask = wdev->radio_mask;
+ if (!wiphy->n_radio || radio_mask == BIT(wiphy->n_radio) - 1)
+ return true;
+
+ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
+ for (i = 0; i < wiphy->n_radio; i++) {
+ if (!(radio_mask & BIT(i)))
+ continue;
+
+ radio = &wiphy->radio[i];
+ if (!cfg80211_radio_chandef_valid(radio, &chandef))
+ continue;
+
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_wdev_channel_allowed);
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
2024-10-02 11:45 ` [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 12:57 ` Johannes Berg
2024-10-02 11:45 ` [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel Felix Fietkau
` (8 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Reject frequencies not supported by any radio that the vif is allowed to use.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/scan.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index adb88c06b598..8b77b782696c 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1200,7 +1200,9 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
&local->hw.wiphy->bands[band]->channels[i];
if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR |
- IEEE80211_CHAN_DISABLED))
+ IEEE80211_CHAN_DISABLED) ||
+ !cfg80211_wdev_channel_allowed(&sdata->wdev,
+ tmp_ch))
continue;
local->int_scan_req->channels[n_ch] = tmp_ch;
@@ -1215,14 +1217,16 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
} else {
for (i = 0; i < n_channels; i++) {
if (channels[i]->flags & (IEEE80211_CHAN_NO_IR |
- IEEE80211_CHAN_DISABLED))
+ IEEE80211_CHAN_DISABLED) ||
+ !cfg80211_wdev_channel_allowed(&sdata->wdev,
+ channels[i]))
continue;
local->int_scan_req->channels[n_ch] = channels[i];
n_ch++;
}
- if (WARN_ON_ONCE(n_ch == 0))
+ if (n_ch == 0)
goto unlock;
local->int_scan_req->n_channels = n_ch;
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
2024-10-02 11:45 ` [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios Felix Fietkau
2024-10-02 11:45 ` [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 12:58 ` Johannes Berg
2024-10-02 11:45 ` [PATCH 04/11] wifi: cfg80211: report per wiphy radio antenna mask Felix Fietkau
` (7 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Reject frequencies not supported by any radio that the vif is allowed to use.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/chan.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index cca6d14084d2..fbc3b28953a6 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -1169,7 +1169,7 @@ ieee80211_replace_chanctx(struct ieee80211_local *local,
static bool
ieee80211_find_available_radio(struct ieee80211_local *local,
const struct ieee80211_chan_req *chanreq,
- int *radio_idx)
+ u32 radio_mask, int *radio_idx)
{
struct wiphy *wiphy = local->hw.wiphy;
const struct wiphy_radio *radio;
@@ -1180,6 +1180,9 @@ ieee80211_find_available_radio(struct ieee80211_local *local,
return true;
for (i = 0; i < wiphy->n_radio; i++) {
+ if (!(radio_mask & BIT(i)))
+ continue;
+
radio = &wiphy->radio[i];
if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
continue;
@@ -1213,7 +1216,9 @@ int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
if (!new_ctx) {
if (ieee80211_can_create_new_chanctx(local, -1) &&
- ieee80211_find_available_radio(local, chanreq, &radio_idx))
+ ieee80211_find_available_radio(local, chanreq,
+ sdata->wdev.radio_mask,
+ &radio_idx))
new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
false, radio_idx);
else
@@ -1883,7 +1888,9 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
/* Note: context is now reserved */
if (ctx)
reserved = true;
- else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
+ else if (!ieee80211_find_available_radio(local, chanreq,
+ sdata->wdev.radio_mask,
+ &radio_idx))
ctx = ERR_PTR(-EBUSY);
else
ctx = ieee80211_new_chanctx(local, chanreq, mode,
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 04/11] wifi: cfg80211: report per wiphy radio antenna mask
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (2 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 05/11] wifi: mac80211: remove status->ampdu_delimiter_crc Felix Fietkau
` (6 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
With multi-radio devices, each radio typically gets a fixed set of antennas.
In order to be able to disable specific antennas for some radios, user space
needs to know which antenna mask bits are assigned to which radio.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/cfg80211.h | 4 ++++
include/uapi/linux/nl80211.h | 3 +++
net/wireless/nl80211.c | 4 +++-
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 73df4a8e8cce..8bb5fb80cd7b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5436,6 +5436,8 @@ struct wiphy_radio_freq_range {
* @iface_combinations: Valid interface combinations array, should not
* list single interface types.
* @n_iface_combinations: number of entries in @iface_combinations array.
+ *
+ * @antenna_mask: bitmask of antennas connected to this radio.
*/
struct wiphy_radio {
const struct wiphy_radio_freq_range *freq_range;
@@ -5443,6 +5445,8 @@ struct wiphy_radio {
const struct ieee80211_iface_combination *iface_combinations;
int n_iface_combinations;
+
+ u32 antenna_mask;
};
#define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index d31ccee99cc7..1b8827f920ff 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -8036,6 +8036,8 @@ enum nl80211_ap_settings_flags {
* @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
* combination for this radio. Attribute may be present multiple times
* and contains attributes defined in &enum nl80211_if_combination_attrs.
+ * @NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK: bitmask (u32) of antennas
+ * connected to this radio.
*
* @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
* @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
@@ -8046,6 +8048,7 @@ enum nl80211_wiphy_radio_attrs {
NL80211_WIPHY_RADIO_ATTR_INDEX,
NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
+ NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK,
/* keep last */
__NL80211_WIPHY_RADIO_ATTR_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8f86b23e106a..5c54e1793539 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2428,7 +2428,9 @@ static int nl80211_put_radio(struct wiphy *wiphy, struct sk_buff *msg, int idx)
if (!radio)
return -ENOBUFS;
- if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx))
+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx) ||
+ nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK,
+ r->antenna_mask))
goto nla_put_failure;
for (i = 0; i < r->n_freq_range; i++) {
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 05/11] wifi: mac80211: remove status->ampdu_delimiter_crc
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (3 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 04/11] wifi: cfg80211: report per wiphy radio antenna mask Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 06/11] wifi: cfg80211: pass net_device to .set_monitor_channel Felix Fietkau
` (5 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
This was never used by any driver, so remove it to free up some space.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/mac80211.h | 6 +-----
net/mac80211/rx.c | 7 +------
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 954dff901b69..be916e1e5e1d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1448,8 +1448,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU
* @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected
* on this subframe
- * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
- * is stored in the @ampdu_delimiter_crc field)
* @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was
* done by the hardware
* @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without
@@ -1521,7 +1519,7 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_LAST_KNOWN = BIT(12),
RX_FLAG_AMPDU_IS_LAST = BIT(13),
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(14),
- RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(15),
+ /* one free bit at 15 */
RX_FLAG_MACTIME = BIT(16) | BIT(17),
RX_FLAG_MACTIME_PLCP_START = 1 << 16,
RX_FLAG_MACTIME_START = 2 << 16,
@@ -1618,7 +1616,6 @@ enum mac80211_rx_encoding {
* @rx_flags: internal RX flags for mac80211
* @ampdu_reference: A-MPDU reference number, must be a different value for
* each A-MPDU but the same for each subframe within one A-MPDU
- * @ampdu_delimiter_crc: A-MPDU delimiter CRC
* @zero_length_psdu_type: radiotap type of the 0-length PSDU
* @link_valid: if the link which is identified by @link_id is valid. This flag
* is set only when connection is MLO.
@@ -1656,7 +1653,6 @@ struct ieee80211_rx_status {
s8 signal;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
- u8 ampdu_delimiter_crc;
u8 zero_length_psdu_type;
u8 link_valid:1, link_id:4;
};
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 59ad24a71141..718f02f0a181 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -508,18 +508,13 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR)
flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
- if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
- flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
if (status->flag & RX_FLAG_AMPDU_EOF_BIT_KNOWN)
flags |= IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN;
if (status->flag & RX_FLAG_AMPDU_EOF_BIT)
flags |= IEEE80211_RADIOTAP_AMPDU_EOF;
put_unaligned_le16(flags, pos);
pos += 2;
- if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
- *pos++ = status->ampdu_delimiter_crc;
- else
- *pos++ = 0;
+ *pos++ = 0;
*pos++ = 0;
}
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 06/11] wifi: cfg80211: pass net_device to .set_monitor_channel
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (4 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 05/11] wifi: mac80211: remove status->ampdu_delimiter_crc Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 07/11] wifi: mac80211: add flag to opt out of virtual monitor support Felix Fietkau
` (4 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Preparation for allowing multiple monitor interfaces with different channels
on a multi-radio wiphy.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 1 +
drivers/net/wireless/marvell/libertas/cfg.c | 1 +
drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 ++-
include/net/cfg80211.h | 1 +
net/mac80211/cfg.c | 1 +
net/wireless/chan.c | 3 ++-
net/wireless/core.h | 1 +
net/wireless/nl80211.c | 2 +-
net/wireless/rdev-ops.h | 5 +++--
net/wireless/trace.h | 8 +++++---
net/wireless/wext-compat.c | 2 +-
11 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e8f1d30a8d73..a1a0a9223e74 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1493,6 +1493,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
}
static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index b700c213d10c..c1f462bb6a3f 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len)
*/
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct lbs_private *priv = wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index eb37b228d54e..9977be0020fe 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
}
static int set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wilc *wl = wiphy_priv(wiphy);
@@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct wilc_vif *vif = netdev_priv(dev);
int ret;
- ret = set_channel(wiphy, &settings->chandef);
+ ret = set_channel(wiphy, dev, &settings->chandef);
if (ret != 0)
netdev_err(dev, "Error in setting channel\n");
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8bb5fb80cd7b..4dd537da0873 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4696,6 +4696,7 @@ struct cfg80211_ops {
struct ieee80211_channel *chan);
int (*set_monitor_channel)(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef);
int (*scan)(struct wiphy *wiphy,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 847304a3a29a..b1ea7006f8d3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -879,6 +879,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index e579d7e1425f..035f3b099d0f 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1628,6 +1628,7 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy,
EXPORT_SYMBOL(cfg80211_reg_check_beaconing);
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
if (!rdev->ops->set_monitor_channel)
@@ -1635,7 +1636,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
if (!cfg80211_has_monitors_only(rdev))
return -EBUSY;
- return rdev_set_monitor_channel(rdev, chandef);
+ return rdev_set_monitor_channel(rdev, dev, chandef);
}
bool cfg80211_any_usable_channels(struct wiphy *wiphy,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3b3e3cd7027a..4c45f994a8c0 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -516,6 +516,7 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
}
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef);
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5c54e1793539..69cdffa87d8e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3564,7 +3564,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_MESH_POINT:
return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
case NL80211_IFTYPE_MONITOR:
- return cfg80211_set_monitor_channel(rdev, &chandef);
+ return cfg80211_set_monitor_channel(rdev, dev, &chandef);
default:
break;
}
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index f5adbf6b5c84..adb6105bbb7d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -445,11 +445,12 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev,
static inline int
rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
int ret;
- trace_rdev_set_monitor_channel(&rdev->wiphy, chandef);
- ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef);
+ trace_rdev_set_monitor_channel(&rdev->wiphy, dev, chandef);
+ ret = rdev->ops->set_monitor_channel(&rdev->wiphy, dev, chandef);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 97c21b627791..dc217086c155 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1318,19 +1318,21 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel,
);
TRACE_EVENT(rdev_set_monitor_channel,
- TP_PROTO(struct wiphy *wiphy,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_chan_def *chandef),
TP_ARGS(wiphy, chandef),
TP_STRUCT__entry(
WIPHY_ENTRY
+ NETDEV_ENTRY
CHAN_DEF_ENTRY
),
TP_fast_assign(
WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_PR_ARG)
);
TRACE_EVENT(rdev_auth,
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 2371069f3c43..fd3d01359807 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -830,7 +830,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
ret = -EINVAL;
break;
}
- ret = cfg80211_set_monitor_channel(rdev, &chandef);
+ ret = cfg80211_set_monitor_channel(rdev, dev, &chandef);
break;
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wextfreq);
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 07/11] wifi: mac80211: add flag to opt out of virtual monitor support
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (5 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 06/11] wifi: cfg80211: pass net_device to .set_monitor_channel Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 08/11] wifi: cfg80211: add monitor SKIP_TX flag Felix Fietkau
` (3 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
This is useful for multi-radio devices that are capable of monitoring on
multiple channels simultanenously. When this flag is set, each monitor
interface is passed to the driver individually and can have a configured
channel.
The vif mac address for non-active monitor interfaces is cleared, in order
to allow the driver to tell them apart from active ones.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/mac80211.h | 6 +++++-
net/mac80211/cfg.c | 44 +++++++++++++++++++++++++---------------
net/mac80211/chan.c | 14 ++++++++++++-
net/mac80211/debugfs.c | 1 +-
net/mac80211/driver-ops.c | 1 +-
net/mac80211/iface.c | 22 +++++++++++++++-----
net/mac80211/rx.c | 3 +++-
net/mac80211/tx.c | 6 +++--
net/mac80211/util.c | 14 +++++++++----
9 files changed, 83 insertions(+), 28 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index be916e1e5e1d..1343ea4f8103 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2679,6 +2679,11 @@ struct ieee80211_txq {
* a virtual monitor interface when monitor interfaces are the only
* active interfaces.
*
+ * @IEEE80211_HW_NO_VIRTUAL_MONITOR: The driver would like to be informed
+ * of any monitor interface, as well as their configured channel.
+ * This is useful for supporting multiple monitor interfaces on different
+ * channels.
+ *
* @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
* be created. It is expected user-space will create vifs as
* desired (and thus have them named as desired).
@@ -2838,6 +2843,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
IEEE80211_HW_MFP_CAPABLE,
IEEE80211_HW_WANT_MONITOR_VIF,
+ IEEE80211_HW_NO_VIRTUAL_MONITOR,
IEEE80211_HW_NO_AUTO_VIF,
IEEE80211_HW_SW_CRYPTO_CONTROL,
IEEE80211_HW_SUPPORT_FAST_XMIT,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b1ea7006f8d3..a67f38bc3961 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -105,8 +105,11 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
}
/* also validate MU-MIMO change */
- monitor_sdata = wiphy_dereference(local->hw.wiphy,
- local->monitor_sdata);
+ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ monitor_sdata = sdata;
+ else
+ monitor_sdata = wiphy_dereference(local->hw.wiphy,
+ local->monitor_sdata);
if (!monitor_sdata &&
(params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
@@ -114,7 +117,9 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
/* apply all changes now - no failures allowed */
- if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+ if (monitor_sdata &&
+ (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) ||
+ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)))
ieee80211_set_mu_mimo_follow(monitor_sdata, params);
if (params->flags) {
@@ -889,22 +894,25 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
lockdep_assert_wiphy(local->hw.wiphy);
- if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
- &chanreq.oper))
- return 0;
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
+ &chanreq.oper))
+ return 0;
- sdata = wiphy_dereference(local->hw.wiphy,
- local->monitor_sdata);
- if (!sdata)
- goto done;
+ sdata = wiphy_dereference(wiphy, local->monitor_sdata);
+ if (!sdata)
+ goto done;
+ }
- if (cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
+ if (rcu_access_pointer(sdata->deflink.conf->chanctx_conf) &&
+ cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
&chanreq.oper))
return 0;
ieee80211_link_release_channel(&sdata->deflink);
ret = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
- IEEE80211_CHANCTX_EXCLUSIVE);
+ IEEE80211_CHANCTX_SHARED);
if (ret)
return ret;
done:
@@ -3053,7 +3061,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
if (wdev) {
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return -EOPNOTSUPP;
@@ -3101,7 +3110,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
}
list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
has_monitor = true;
continue;
}
@@ -3111,7 +3121,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
sdata->vif.bss_conf.txpower_type = txp_type;
}
list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
continue;
ieee80211_recalc_txpower(sdata, update_txp_type);
}
@@ -4302,7 +4313,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
if (chanctx_conf) {
*chandef = link->conf->chanreq.oper;
ret = 0;
- } else if (local->open_count > 0 &&
+ } else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
+ local->open_count > 0 &&
local->open_count == local->monitors &&
sdata->vif.type == NL80211_IFTYPE_MONITOR) {
*chandef = local->monitor_chanreq.oper;
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index fbc3b28953a6..c375c86dd38c 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -339,6 +339,10 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_NAN:
continue;
+ case NL80211_IFTYPE_MONITOR:
+ WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
+ NO_VIRTUAL_MONITOR));
+ fallthrough;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_OCB:
@@ -347,7 +351,6 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_UNSPECIFIED:
case NUM_NL80211_IFTYPES:
- case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
WARN_ON_ONCE(1);
@@ -956,6 +959,10 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
if (!link->sdata->u.mgd.associated)
continue;
break;
+ case NL80211_IFTYPE_MONITOR:
+ if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ continue;
+ break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
@@ -968,6 +975,11 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
continue;
+ if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+ rx_chains_dynamic = rx_chains_static = local->rx_chains;
+ break;
+ }
+
switch (link->smps_mode) {
default:
WARN_ONCE(1, "Invalid SMPS mode %d\n",
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 02b5476a4376..b777240c924e 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -456,6 +456,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_DYNAMIC_PS),
FLAG(MFP_CAPABLE),
FLAG(WANT_MONITOR_VIF),
+ FLAG(NO_VIRTUAL_MONITOR),
FLAG(NO_AUTO_VIF),
FLAG(SW_CRYPTO_CONTROL),
FLAG(SUPPORT_FAST_XMIT),
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index fe868b521622..8179310595ac 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -65,6 +65,7 @@ int drv_add_interface(struct ieee80211_local *local,
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
(sdata->vif.type == NL80211_IFTYPE_MONITOR &&
!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))))
return -EINVAL;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 6ef0990d3d29..3aefc62034ba 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -279,8 +279,13 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
ret = eth_mac_addr(sdata->dev, sa);
if (ret == 0) {
- memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
- ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
+ if (check_dup) {
+ memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
+ ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
+ } else {
+ memset(sdata->vif.addr, 0, ETH_ALEN);
+ memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
+ }
}
/* Regardless of eth_mac_addr() return we still want to add the
@@ -699,9 +704,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
ieee80211_recalc_idle(local);
ieee80211_recalc_offload(local);
- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
+ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
break;
+ ieee80211_link_release_channel(&sdata->deflink);
fallthrough;
default:
if (!going_down)
@@ -1131,7 +1138,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
ASSERT_RTNL();
lockdep_assert_wiphy(local->hw.wiphy);
- if (local->monitor_sdata)
+ if (local->monitor_sdata ||
+ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
return 0;
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
@@ -1193,6 +1201,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
+ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ return;
+
ASSERT_RTNL();
lockdep_assert_wiphy(local->hw.wiphy);
@@ -1328,7 +1339,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
break;
}
- if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
+ if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
+ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
res = drv_add_interface(local, sdata);
if (res)
goto err_stop;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 718f02f0a181..b35e1b472e82 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -840,6 +840,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
bool last_monitor = list_is_last(&sdata->u.mntr.list,
&local->mon_list);
+ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
+
if (!monskb)
monskb = ieee80211_make_monitor_skb(local, &origskb,
rate, rtap_space,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a9ee86982259..f55f0518b35e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1763,7 +1763,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
- if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
+ if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
+ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
vif = &sdata->vif;
break;
}
@@ -3952,7 +3953,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
switch (tx.sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
- if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
+ if ((tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
+ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
vif = &tx.sdata->vif;
break;
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f94faa86ba8a..279210fabd35 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -756,7 +756,8 @@ static void __iterate_interfaces(struct ieee80211_local *local,
lockdep_is_held(&local->hw.wiphy->mtx)) {
switch (sdata->vif.type) {
case NL80211_IFTYPE_MONITOR:
- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
+ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
continue;
break;
case NL80211_IFTYPE_AP_VLAN:
@@ -1873,8 +1874,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ continue;
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_MONITOR &&
ieee80211_sdata_running(sdata)) {
res = drv_add_interface(local, sdata);
if (WARN_ON(res))
@@ -1887,11 +1890,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
*/
if (res) {
list_for_each_entry_continue_reverse(sdata, &local->interfaces,
- list)
+ list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ continue;
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_MONITOR &&
ieee80211_sdata_running(sdata))
drv_remove_interface(local, sdata);
+ }
ieee80211_handle_reconfig_failure(local);
return res;
}
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 08/11] wifi: cfg80211: add monitor SKIP_TX flag
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (6 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 07/11] wifi: mac80211: add flag to opt out of virtual monitor support Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 09/11] wifi: mac80211: add support for the " Felix Fietkau
` (2 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
This can be used to indicate that the user is not interested in receiving
locally sent packets on the monitor interface.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/cfg80211.h | 1 +
include/uapi/linux/nl80211.h | 2 ++
net/wireless/nl80211.c | 1 +
3 files changed, 4 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4dd537da0873..de6c585fb1c2 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2278,6 +2278,7 @@ enum monitor_flags {
MONITOR_FLAG_OTHER_BSS = BIT(NL80211_MNTR_FLAG_OTHER_BSS),
MONITOR_FLAG_COOK_FRAMES = BIT(NL80211_MNTR_FLAG_COOK_FRAMES),
MONITOR_FLAG_ACTIVE = BIT(NL80211_MNTR_FLAG_ACTIVE),
+ MONITOR_FLAG_SKIP_TX = BIT(NL80211_MNTR_FLAG_SKIP_TX),
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1b8827f920ff..6d11437596b9 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4703,6 +4703,7 @@ enum nl80211_survey_info {
* overrides all other flags.
* @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address
* and ACK incoming unicast packets.
+ * @NL80211_MNTR_FLAG_SKIP_TX: do not pass local tx packets
*
* @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
* @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
@@ -4715,6 +4716,7 @@ enum nl80211_mntr_flags {
NL80211_MNTR_FLAG_OTHER_BSS,
NL80211_MNTR_FLAG_COOK_FRAMES,
NL80211_MNTR_FLAG_ACTIVE,
+ NL80211_MNTR_FLAG_SKIP_TX,
/* keep last */
__NL80211_MNTR_FLAG_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 69cdffa87d8e..e2aab62fd8fd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4203,6 +4203,7 @@ static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
[NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
[NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
[NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
+ [NL80211_MNTR_FLAG_SKIP_TX] = { .type = NLA_FLAG },
};
static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 09/11] wifi: mac80211: add support for the monitor SKIP_TX flag
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (7 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 08/11] wifi: cfg80211: add monitor SKIP_TX flag Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 10/11] wifi: mac80211: refactor ieee80211_rx_monitor Felix Fietkau
2024-10-02 11:45 ` [PATCH 11/11] wifi: mac80211: filter on monitor interfaces based on configured channel Felix Fietkau
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Do not pass locally sent packets to monitor interfaces with this flag set.
Skip processing tx packets on the status call entirely if no monitor
interfaces without this flag are present.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/iface.c | 2 ++
net/mac80211/status.c | 5 ++++-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4f0390918b60..d697e9dab70d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1370,7 +1370,7 @@ struct ieee80211_local {
spinlock_t queue_stop_reason_lock;
int open_count;
- int monitors, cooked_mntrs;
+ int monitors, cooked_mntrs, tx_mntrs;
/* number of interfaces with corresponding FIF_ flags */
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
fif_probe_req;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 3aefc62034ba..54060ba97b98 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1094,6 +1094,8 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
ADJUST(CONTROL, control);
ADJUST(CONTROL, pspoll);
ADJUST(OTHER_BSS, other_bss);
+ if (!(flags & MONITOR_FLAG_SKIP_TX))
+ local->tx_mntrs += offset;
#undef ADJUST
}
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index d1cf987de13b..eb889cda8bf9 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -927,6 +927,9 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
if (!ieee80211_sdata_running(sdata))
continue;
+ if (sdata->u.mntr.flags & MONITOR_FLAG_SKIP_TX)
+ continue;
+
if ((sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) &&
!send_to_cooked)
continue;
@@ -1099,7 +1102,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
* This is a bit racy but we can avoid a lot of work
* with this test...
*/
- if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
+ if (!local->tx_mntrs && (!send_to_cooked || !local->cooked_mntrs)) {
if (status->free_list)
list_add_tail(&skb->list, status->free_list);
else
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 10/11] wifi: mac80211: refactor ieee80211_rx_monitor
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (8 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 09/11] wifi: mac80211: add support for the " Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 11/11] wifi: mac80211: filter on monitor interfaces based on configured channel Felix Fietkau
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Rework the monitor mode interface iteration to get rid of hte last_monitor
condition. Preparation for further filtering received monitor packets.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/rx.c | 54 ++++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 26 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b35e1b472e82..5e43905fd26c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -762,8 +762,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
struct ieee80211_rate *rate)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
- struct ieee80211_sub_if_data *sdata;
- struct sk_buff *monskb = NULL;
+ struct ieee80211_sub_if_data *sdata, *prev_sdata = NULL;
+ struct sk_buff *skb, *monskb = NULL;
int present_fcs_len = 0;
unsigned int rtap_space = 0;
struct ieee80211_sub_if_data *monitor_sdata =
@@ -837,8 +837,10 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
- bool last_monitor = list_is_last(&sdata->u.mntr.list,
- &local->mon_list);
+ if (!prev_sdata) {
+ prev_sdata = sdata;
+ continue;
+ }
if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
@@ -846,34 +848,34 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
if (!monskb)
monskb = ieee80211_make_monitor_skb(local, &origskb,
rate, rtap_space,
- only_monitor &&
- last_monitor);
+ false);
+ if (!monskb)
+ continue;
- if (monskb) {
- struct sk_buff *skb;
+ skb = skb_clone(monskb, GFP_ATOMIC);
+ if (!skb)
+ continue;
- if (last_monitor) {
- skb = monskb;
- monskb = NULL;
- } else {
- skb = skb_clone(monskb, GFP_ATOMIC);
- }
+ skb->dev = prev_sdata->dev;
+ dev_sw_netstats_rx_add(skb->dev, skb->len);
+ netif_receive_skb(skb);
+ prev_sdata = sdata;
+ }
- if (skb) {
- skb->dev = sdata->dev;
- dev_sw_netstats_rx_add(skb->dev, skb->len);
- netif_receive_skb(skb);
- }
+ if (prev_sdata) {
+ if (monskb)
+ skb = monskb;
+ else
+ skb = ieee80211_make_monitor_skb(local, &origskb,
+ rate, rtap_space,
+ only_monitor);
+ if (skb) {
+ skb->dev = prev_sdata->dev;
+ dev_sw_netstats_rx_add(skb->dev, skb->len);
+ netif_receive_skb(skb);
}
-
- if (last_monitor)
- break;
}
- /* this happens if last_monitor was erroneously false */
- dev_kfree_skb(monskb);
-
- /* ditto */
if (!origskb)
return NULL;
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 11/11] wifi: mac80211: filter on monitor interfaces based on configured channel
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
` (9 preceding siblings ...)
2024-10-02 11:45 ` [PATCH 10/11] wifi: mac80211: refactor ieee80211_rx_monitor Felix Fietkau
@ 2024-10-02 11:45 ` Felix Fietkau
10 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 11:45 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
When a monitor interface has an assigned channel (only happens with the
NO_VIRTUAL_MONITOR feature), only pass packets received on that channel.
This is useful for monitoring on multiple channels at the same time using
multiple monitor interfaces.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/rx.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5e43905fd26c..6df0f3953eec 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -837,6 +837,13 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
+ struct cfg80211_chan_def *chandef;
+
+ chandef = &sdata->vif.bss_conf.chanreq.oper;
+ if (chandef->chan &&
+ chandef->chan->center_freq != status->freq)
+ continue;
+
if (!prev_sdata) {
prev_sdata = sdata;
continue;
--
git-series 0.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios
2024-10-02 11:45 ` [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios Felix Fietkau
@ 2024-10-02 12:55 ` Johannes Berg
0 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2024-10-02 12:55 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
> + * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
> + * A value of 0 means all radios.
The handling of 0 seems inconsistent, you don't always initialize it, so
0 could be reported to userspace (for interfaces created other than
through nl80211), but setting it to 0 results in non-zero "full" bitmap.
Probably just need to always initialize it in cfg80211_init_wdev()?
Though not quite sure how that meshes with the nl80211 creation.
> +static int nl80211_parse_vif_radio_mask(struct genl_info *info,
> + u32 *radio_mask)
> +{
> + struct cfg80211_registered_device *rdev = info->user_ptr[0];
> + struct nlattr *attr = info->attrs[NL80211_ATTR_VIF_RADIO_MASK];
> + u32 mask, allowed;
> +
> + if (!attr)
> + return 0;
Might be nicer to also initialize *radio_mask here
> + err = nl80211_parse_vif_radio_mask(info, &radio_mask);
> + if (err < 0)
> + return err;
> + if (radio_mask && netif_running(dev))
> + return -EBUSY;
and use the return value (==1) to distinguish this, rather than the
value you initialized radio_mask to (which is then not needed)?
Not sure, I can see benefits of this approach too I guess, just got
confused about it - and especially due to the zero issue pointed out
above.
johannes
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies
2024-10-02 11:45 ` [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies Felix Fietkau
@ 2024-10-02 12:57 ` Johannes Berg
0 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2024-10-02 12:57 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
On Wed, 2024-10-02 at 13:45 +0200, Felix Fietkau wrote:
>
> @@ -1215,14 +1217,16 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
> } else {
> for (i = 0; i < n_channels; i++) {
> if (channels[i]->flags & (IEEE80211_CHAN_NO_IR |
> - IEEE80211_CHAN_DISABLED))
> + IEEE80211_CHAN_DISABLED) ||
> + !cfg80211_wdev_channel_allowed(&sdata->wdev,
> + channels[i]))
> continue;
>
> local->int_scan_req->channels[n_ch] = channels[i];
> n_ch++;
> }
>
> - if (WARN_ON_ONCE(n_ch == 0))
> + if (n_ch == 0)
> goto unlock;
-EBUSY seems somewhat confusing in this case?
johannes
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel
2024-10-02 11:45 ` [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel Felix Fietkau
@ 2024-10-02 12:58 ` Johannes Berg
2024-10-02 14:38 ` Felix Fietkau
0 siblings, 1 reply; 16+ messages in thread
From: Johannes Berg @ 2024-10-02 12:58 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless
On Wed, 2024-10-02 at 13:45 +0200, Felix Fietkau wrote:
> Reject frequencies not supported by any radio that the vif is allowed to use.
>
Not sure how this does anything for remain-on-channel?
But arguably remain-on-channel also should/can be in cfg80211?
johannes
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel
2024-10-02 12:58 ` Johannes Berg
@ 2024-10-02 14:38 ` Felix Fietkau
0 siblings, 0 replies; 16+ messages in thread
From: Felix Fietkau @ 2024-10-02 14:38 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
On 02.10.24 14:58, Johannes Berg wrote:
> On Wed, 2024-10-02 at 13:45 +0200, Felix Fietkau wrote:
>> Reject frequencies not supported by any radio that the vif is allowed to use.
>>
>
> Not sure how this does anything for remain-on-channel?
>
> But arguably remain-on-channel also should/can be in cfg80211?
Right, I moved this description bit to the wrong patch, it's in cfg80211
already.
Thanks,
- Felix
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-10-02 14:38 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-02 11:45 [PATCH 00/11] wifi: cfg80211/mac80211: improve support for multiple radios Felix Fietkau
2024-10-02 11:45 ` [PATCH 01/11] wifi: cfg80211: add option for vif allowed radios Felix Fietkau
2024-10-02 12:55 ` Johannes Berg
2024-10-02 11:45 ` [PATCH 02/11] wifi: mac80211: use vif radio mask to limit ibss scan frequencies Felix Fietkau
2024-10-02 12:57 ` Johannes Berg
2024-10-02 11:45 ` [PATCH 03/11] wifi: mac80211: use vif radio mask to limit chanctx and remain-on-channel Felix Fietkau
2024-10-02 12:58 ` Johannes Berg
2024-10-02 14:38 ` Felix Fietkau
2024-10-02 11:45 ` [PATCH 04/11] wifi: cfg80211: report per wiphy radio antenna mask Felix Fietkau
2024-10-02 11:45 ` [PATCH 05/11] wifi: mac80211: remove status->ampdu_delimiter_crc Felix Fietkau
2024-10-02 11:45 ` [PATCH 06/11] wifi: cfg80211: pass net_device to .set_monitor_channel Felix Fietkau
2024-10-02 11:45 ` [PATCH 07/11] wifi: mac80211: add flag to opt out of virtual monitor support Felix Fietkau
2024-10-02 11:45 ` [PATCH 08/11] wifi: cfg80211: add monitor SKIP_TX flag Felix Fietkau
2024-10-02 11:45 ` [PATCH 09/11] wifi: mac80211: add support for the " Felix Fietkau
2024-10-02 11:45 ` [PATCH 10/11] wifi: mac80211: refactor ieee80211_rx_monitor Felix Fietkau
2024-10-02 11:45 ` [PATCH 11/11] wifi: mac80211: filter on monitor interfaces based on configured channel Felix Fietkau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox