Skip to contentSkip to conversation

mac80211: Take bitrates into account when building IEs.

PATCH In review [email protected] 2 participants 24 messages Oct 20, 2015 – Jun 21, 2016

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/2 mac80211: Take bitrates into account when building IEs.

From: Ben Greear <[email protected]>

If a user restricts the rateset for some reason, then the probe requests should not advertise rates that are not selected by the user.

To implement this, we save the requested bitrates at the mac80211 level and take it into account when building the IEs.

This allows one to create a more realistic /b mode station on modern hardware, for instance. Good for testing, and likely good for other things as well.

---
v2: Only save rates when given explicit flag from user-space.

 drivers/net/wireless/ath/ath6kl/cfg80211.c |  3 +-
 drivers/net/wireless/mwifiex/cfg80211.c    |  3 +-
 include/net/cfg80211.h                     |  3 +-
 include/net/mac80211.h                     |  4 ++
 include/uapi/linux/nl80211.h               |  2 +
 net/mac80211/cfg.c                         |  9 ++-
 net/mac80211/ieee80211_i.h                 | 18 +++++-
 net/mac80211/scan.c                        | 26 +++++++-
 net/mac80211/util.c                        | 97 +++++++++++++++++++++++++++---
 net/wireless/nl80211.c                     |  5 +-
 net/wireless/rdev-ops.h                    |  6 +-
 net/wireless/wext-compat.c                 |  2 +-
 12 files changed, 160 insertions(+), 18 deletions(-)
drivers/net/wireless/ath/ath6kl/cfg80211.c +2 -1
index a511ef3..5b3d79e 100644
@@ -3354,7 +3354,8 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
 static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       const u8 *addr,
-				       const struct cfg80211_bitrate_mask *mask)
+				       const struct cfg80211_bitrate_mask *mask,
+				       bool is_advert_mask)
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	struct ath6kl_vif *vif = netdev_priv(dev);
drivers/net/wireless/mwifiex/cfg80211.c +2 -1
index b15e4c7..7888916 100644
@@ -1542,7 +1542,8 @@ mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
 				struct net_device *dev,
 				const u8 *peer,
-				const struct cfg80211_bitrate_mask *mask)
+				const struct cfg80211_bitrate_mask *mask,
+				bool is_advert_mask)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
include/net/cfg80211.h +2 -1
index 038de33..0804268 100644
@@ -2594,7 +2594,8 @@ struct cfg80211_ops {
 	int	(*set_bitrate_mask)(struct wiphy *wiphy,
 				    struct net_device *dev,
 				    const u8 *peer,
-				    const struct cfg80211_bitrate_mask *mask);
+				    const struct cfg80211_bitrate_mask *mask,
+				    bool is_advert_bitmask);
 
 	int	(*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
 			int idx, struct survey_info *info);
include/net/mac80211.h +4 -0
index 6b1077c..970372d 100644
@@ -2073,10 +2073,14 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
  * struct ieee80211_scan_request - hw scan request
  *
  * @ies: pointers different parts of IEs (in req.ie)
+ * @disable_ht: Ensure nothing related to HT is in the probe request
+ * @disable_vht: Ensure nothing related to VHT is in the probe request
  * @req: cfg80211 request.
  */
 struct ieee80211_scan_request {
 	struct ieee80211_scan_ies ies;
+	bool disable_ht[IEEE80211_NUM_BANDS];
+	bool disable_vht[IEEE80211_NUM_BANDS];
 
 	/* Keep last */
 	struct cfg80211_scan_request req;
include/uapi/linux/nl80211.h +2 -0
index c0ab6b0..4573f87 100644
@@ -2130,6 +2130,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_REG_INDOOR,
 
+	NL80211_ATTR_TX_ADVERT_RATEMASK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
net/mac80211/cfg.c +8 -1
index bf7023f..0c0c5cf 100644
@@ -2457,12 +2457,19 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
 				      struct net_device *dev,
 				      const u8 *addr,
-				      const struct cfg80211_bitrate_mask *mask)
+				      const struct cfg80211_bitrate_mask *mask,
+				      bool is_advert_bitmask)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	int i, ret;
 
+	if (is_advert_bitmask) {
+		memcpy(&sdata->cfg_advert_bitrate_mask, mask, sizeof(*mask));
+		sdata->cfg_advert_bitrate_mask_set = true;
+		return 0;
+	}
+
 	if (!ieee80211_sdata_running(sdata))
 		return -ENETDOWN;
 
net/mac80211/ieee80211_i.h +17 -1
index b15559c..5e43e99 100644
@@ -904,6 +904,13 @@ struct ieee80211_sub_if_data {
 	bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
 	u8  rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
 
+	/* Store bitrate mask configured from user-space.  This is for
+	 * rates that should be advertised in probe requests, etc.  This
+	 * is NOT directly related to the tx-rate-ctrl logic configuration.
+	 */
+	struct cfg80211_bitrate_mask cfg_advert_bitrate_mask;
+	bool cfg_advert_bitrate_mask_set; /* Has user set the mask? */
+
 	union {
 		struct ieee80211_if_ap ap;
 		struct ieee80211_if_wds wds;
@@ -1549,6 +1556,14 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata);
 
 /* scan/BSS handling */
+void ieee80211_check_disabled_rates(struct ieee80211_sub_if_data *sdata,
+				    bool *disable_ht,
+				    bool *disable_vht);
+void ieee80211_check_all_rates_disabled(u8 bands_used,
+					bool *disable_ht_cfg,
+					bool *disable_vht_cfg,
+					bool *disable_ht,
+					bool *disable_vht);
 void ieee80211_scan_work(struct work_struct *work);
 int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 				const u8 *ssid, u8 ssid_len,
@@ -1937,7 +1952,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     struct ieee80211_scan_ies *ie_desc,
 			     const u8 *ie, size_t ie_len,
 			     u8 bands_used, u32 *rate_masks,
-			     struct cfg80211_chan_def *chandef);
+			     struct cfg80211_chan_def *chandef,
+			     bool disable_ht, bool disable_vht);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 					  const u8 *src, const u8 *dst,
 					  u32 ratemask,
net/mac80211/scan.c +24 -2
index 6e857d1..6ff1138 100644
@@ -262,6 +262,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 	struct cfg80211_chan_def chandef;
 	u8 bands_used = 0;
 	int i, ielen, n_chans;
+	bool disable_ht;
+	bool disable_vht;
 
 	req = rcu_dereference_protected(local->scan_req,
 					lockdep_is_held(&local->mtx));
@@ -297,6 +299,11 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 		} while (!n_chans);
 	}
 
+	ieee80211_check_all_rates_disabled(bands_used,
+					   local->hw_scan_req->disable_ht,
+					   local->hw_scan_req->disable_vht,
+					   &disable_ht, &disable_vht);
+
 	local->hw_scan_req->req.n_channels = n_chans;
 	ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
 
@@ -305,7 +312,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 					 local->hw_scan_ies_bufsize,
 					 &local->hw_scan_req->ies,
 					 req->ie, req->ie_len,
-					 bands_used, req->rates, &chandef);
+					 bands_used, req->rates, &chandef,
+					 disable_ht, disable_vht);
 	local->hw_scan_req->req.ie_len = ielen;
 	local->hw_scan_req->req.no_cck = req->no_cck;
 	ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
@@ -563,6 +571,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
 		local->hw_scan_band = 0;
 
+		ieee80211_check_disabled_rates(sdata,
+					       local->hw_scan_req->disable_ht,
+					       local->hw_scan_req->disable_vht);
+
 		/*
 		 * After allocating local->hw_scan_req, we must
 		 * go through until ieee80211_prep_hw_scan(), so
@@ -1079,6 +1091,10 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
 	struct cfg80211_chan_def chandef;
 	int ret, i, iebufsz, num_bands = 0;
 	u32 rate_masks[IEEE80211_NUM_BANDS] = {};
+	bool disable_ht_cfg[IEEE80211_NUM_BANDS];
+	bool disable_vht_cfg[IEEE80211_NUM_BANDS];
+	bool disable_ht;
+	bool disable_vht;
 	u8 bands_used = 0;
 	u8 *ie;
 	size_t len;
@@ -1106,10 +1122,16 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
 
 	ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
 
+	ieee80211_check_disabled_rates(sdata, disable_ht_cfg, disable_vht_cfg);
+	ieee80211_check_all_rates_disabled(bands_used, disable_ht_cfg,
+					   disable_vht_cfg,
+					   &disable_ht, &disable_vht);
+
 	len = ieee80211_build_preq_ies(local, ie, num_bands * iebufsz,
 				       &sched_scan_ies, req->ie,
 				       req->ie_len, bands_used,
-				       rate_masks, &chandef);
+				       rate_masks, &chandef, disable_ht,
+				       disable_vht);
 
 	ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
 	if (ret == 0) {
net/mac80211/util.c +90 -7

147 lines not on this page · raw message

net/wireless/nl80211.c +4 -1
index 24fac43..7b0a82b 100644
@@ -400,6 +400,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
 	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
 	[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
+	[NL80211_ATTR_TX_ADVERT_RATEMASK] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -8284,6 +8285,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 	struct nlattr *tx_rates;
 	struct ieee80211_supported_band *sband;
 	u16 vht_tx_mcs_map;
+	bool is_advert_mask;
 
 	if (!rdev->ops->set_bitrate_mask)
 		return -EOPNOTSUPP;
@@ -8312,6 +8314,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 	if (!info->attrs[NL80211_ATTR_TX_RATES])
 		goto out;
 
+	is_advert_mask = nla_get_flag(info->attrs[NL80211_ATTR_TX_ADVERT_RATEMASK]);
 	/*
 	 * The nested attribute uses enum nl80211_band as the index. This maps
 	 * directly to the enum ieee80211_band values used in cfg80211.
@@ -8404,7 +8407,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 	}
 
 out:
-	return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
+	return rdev_set_bitrate_mask(rdev, dev, NULL, &mask, is_advert_mask);
 }
 
 static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
net/wireless/rdev-ops.h +4 -2
index c6e83a7..2531881 100644
@@ -590,11 +590,13 @@ static inline int rdev_testmode_dump(struct cfg80211_registered_device *rdev,
 static inline int
 rdev_set_bitrate_mask(struct cfg80211_registered_device *rdev,
 		      struct net_device *dev, const u8 *peer,
-		      const struct cfg80211_bitrate_mask *mask)
+		      const struct cfg80211_bitrate_mask *mask,
+		      bool is_advert_mask)
 {
 	int ret;
 	trace_rdev_set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
-	ret = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+	ret = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, peer, mask,
+					  is_advert_mask);
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
net/wireless/wext-compat.c +1 -1
index fd68283..7874f4f 100644
@@ -1266,7 +1266,7 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
 	if (!match)
 		return -EINVAL;
 
-	return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
+	return rdev_set_bitrate_mask(rdev, dev, NULL, &mask, false);
 }
 
 static int cfg80211_wext_giwrate(struct net_device *dev,
Signature · 1 line
2.4.3
#1 lore raw

PATCH v2 2/2 mac80211: ensure association req uses configured ratemask.

From: Ben Greear <[email protected]>

When sending the association request, pay attention to the legacy rates configured by the user, and do not advertise support for any that are not configured.

This makes the assoc request packet look more correct when making modern hardware act like a /b mode station, for instance.

---
 net/mac80211/ieee80211_i.h |  2 +-
 net/mac80211/mlme.c        | 49 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 48 insertions(+), 3 deletions(-)
net/mac80211/ieee80211_i.h +1 -1
index 5e43e99..e9fcdc2 100644
@@ -383,7 +383,7 @@ struct ieee80211_mgd_auth_data {
 
 struct ieee80211_mgd_assoc_data {
 	struct cfg80211_bss *bss;
-	const u8 *supp_rates;
+	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
 
 	unsigned long timeout;
 	int tries;
net/mac80211/mlme.c +47 -2

67 lines not on this page · raw message

Signature · 1 line
2.4.3
maintainer
#2 lore raw

Re: [PATCH-v2 2/2] mac80211: ensure association req uses configured ratemask.

Quoted 9 lines · On Tue, 2015-10-20 at 10:24 -0700, [email protected] wrote:

From: Ben Greear <[email protected]>

When sending the association request, pay attention to the legacy rates configured by the user, and do not advertise support for any that are not configured.

This makes the assoc request packet look more correct when making modern hardware act like a /b mode station, for instance.

This is what I meant by "playing whack-a-mole" :)

Next you'll have to fix TDLS too, etc. I feel that overall this is too complex and we need to address this at a lower level, to actually get the capabilities that all the code already looks at into the restricted state you need for this kind of testing.

johannes

author
#3 lore raw
In reply to [email protected]
Quoted 6 lines · On 10/20/2015 10:24 AM, [email protected] wrote:

From: Ben Greear <[email protected]>

If a user restricts the rateset for some reason, then the probe requests should not advertise rates that are not selected by the user.

Quoted 7 lines

To implement this, we save the requested bitrates at the mac80211 level and take it into account when building the IEs.

This allows one to create a more realistic /b mode station on modern hardware, for instance. Good for testing, and likely good for other things as well.

Any comments on these patches?

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#4 lore raw
Quoted 3 lines · Ben Greear


Any comments on these patches?

As I said to Janusz earlier, I haven't been looking much due to kernel summit and now the merge window. I'll resume next week or so once the trees have stabilized a bit.

johannes

maintainer
#5 lore raw
In reply to [email protected]

include/uapi/linux/nl80211.h enum nl80211_attrs { · line 2133

Quoted 7 lines · On Tue, 2015-10-20 at 10:24 -0700, [email protected] wrote:
include/uapi/linux/nl80211.h +0 -0
@@ -2130,6 +2130,8 @@ enum nl80211_attrs {


  NL80211_ATTR_REG_INDOOR,

include/uapi/linux/nl80211.h +1 -0
+	NL80211_ATTR_TX_ADVERT_RATEMASK,

First of all, this is missing documentation. It's a FLAG as far as I can tell, but if it's set should it affect only the advertised or both?

I also think you added this because I had commented that we might not want to do it unconditionally, but is there really a good reason not to do it unconditionally? I was probably more thinking out loud what would happen with P2P, but there we already say "no cck" for scanning so it shouldn't really have any effect.

But given that we have NL80211_ATTR_SCAN_SUPP_RATES, where does your patch even have an effect, other than this not handling HT/VHT?

I'm a bit wary that we're introducing two ways of achieving a very similar thing.

Also, adding these overrides all over the code seems very complex. Perhaps we can achieve the goal of being able to pretend to have limited hardware capabilities by actually restricting hardware capabilities instead? That would also avoid having to play whack-a-mole with code paths using the device capabilities.

I'd imagine an API along the lines of doing some kind of higher-layer re-register of the wiphy in mac80211 with limited capabilites. At that point you'd allocate a copy of the original capabilities (as far as the new restricted ones overwrite the data), and remove the device from the system as far as higher layers like cfg80211 are concerned.

Would something like that work for you?

johannes

author
#6 lore raw
Quoted 13 lines · Johannes Berg

include/uapi/linux/nl80211.h enum nl80211_attrs { · line 2133

Quoted 7 lines · On Tue, 2015-10-20 at 10:24 -0700, [email protected] wrote:
include/uapi/linux/nl80211.h +1 -0
@@ -2130,6 +2130,8 @@ enum nl80211_attrs {
 
  	NL80211_ATTR_REG_INDOOR,
 
+	NL80211_ATTR_TX_ADVERT_RATEMASK,

First of all, this is missing documentation. It's a FLAG as far as I can tell, but if it's set should it affect only the advertised or both?

Quoted 5 lines

I also think you added this because I had commented that we might not want to do it unconditionally, but is there really a good reason not to do it unconditionally? I was probably more thinking out loud what would happen with P2P, but there we already say "no cck" for scanning so it shouldn't really have any effect.

Turns out, I did want this flag. The reason is that I might want to advertise as a normal-ish /g station (ie, full /b/g rateset), but actually fix the TX rate as 24Mbps (or whatever).

So, I do need a way to set an advertise ratemask vs a tx-rate-mask.

With my current patch, and my patches to supplicant, it seems to at least mostly do what I want, but there is a user-space issue where if you set the ADVERT_RATEMASK on kernels that do not support that flag, it will just set the tx rates instead. Not the end of the world, but possibly there needs to be a feature flag
that user-space could query for this feature.

Quoted 12 lines

But given that we have NL80211_ATTR_SCAN_SUPP_RATES, where does your patch even have an effect, other than this not handling HT/VHT?

I'm a bit wary that we're introducing two ways of achieving a very similar thing.

Also, adding these overrides all over the code seems very complex. Perhaps we can achieve the goal of being able to pretend to have limited hardware capabilities by actually restricting hardware capabilities instead? That would also avoid having to play whack-a-mole with code paths using the device capabilities.

Quoted 7 lines

I'd imagine an API along the lines of doing some kind of higher-layer re-register of the wiphy in mac80211 with limited capabilites. At that point you'd allocate a copy of the original capabilities (as far as the new restricted ones overwrite the data), and remove the device from the system as far as higher layers like cfg80211 are concerned.

Would something like that work for you?

As far as I can tell, that will not work, because I want to have multiple station devices per radio, and have each of them be able to use a different configuration. So, one station may be /g, and another /n and another /AC. Same with APs. In addition, some stations may want to use all available rates for their mode,
and others may want to use a fixed rate or subset of available rates.

Thanks,
Ben

Quoted 3 lines

johannes

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#7 lore raw
Quoted 6 lines · Ben Greear

As far as I can tell, that will not work, because I want to have multiple station devices per radio, and have each of them be able to use a different configuration.  So, one station may be /g, and another /n and another /AC.  Same with APs.  In addition, some stations may want to use all available rates for their mode, and others may want to use a fixed rate or subset of available rates.

So let's agree that we're splitting the *used* rates (which we have today) and the *advertised* rates/modes/...

Even if we can't modify the wiphy capabilities, perhaps we could still handle it more consistently at mac80211 level, e.g. by introducing and using "sdata->capa.bands" (and similar for all the other wiphy capabilities you want to manipulate), and then allowing that to point to something modified?

johannes

author
#8 lore raw
Quoted 11 lines · Johannes Berg
Quoted 6 lines · Ben Greear

As far as I can tell, that will not work, because I want to have multiple station devices per radio, and have each of them be able to use a different configuration. So, one station may be /g, and another /n and another /AC. Same with APs. In addition, some stations may want to use all available rates for their mode, and others may want to use a fixed rate or subset of available rates.

So let's agree that we're splitting the *used* rates (which we have today) and the *advertised* rates/modes/...

Yes, I think that will work well, and unless I mis-understand, that is basically what I implemented so far.

Quoted 5 lines

Even if we can't modify the wiphy capabilities, perhaps we could still handle it more consistently at mac80211 level, e.g. by introducing and using "sdata->capa.bands" (and similar for all the other wiphy capabilities you want to manipulate), and then allowing that to point to something modified?

Copied state might be tricky. I think if we hold any copies of capabilities data in
the sdata, then it should be logically compared with a mask and then treated as an AND with whatever the wiphy has. I'm reluctant to propose any serious mac80211 change at this point, though perhaps
as more of this type of features are added, then it will become more obvious how
to nicely consolidate things in mac80211.

To be honest, I thought my -v2 patches were fairly non-invasive compared to my normal hackings :)

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#9 lore raw
Quoted 11 lines · Ben Greear
Quoted 10 lines · Johannes Berg
Quoted 7 lines · Ben Greear

As far as I can tell, that will not work, because I want to have multiple station devices per radio, and have each of them be able to
use a different configuration.  So, one station may be /g, and another /n and another /AC.  Same with APs.  In addition, some stations may want to use all available rates for their mode, and others may want to use a fixed rate or subset of available rates.

Quoted 5 lines
Quoted 2 lines

So let's agree that we're splitting the *used* rates (which we have today) and the *advertised* rates/modes/...

Yes, I think that will work well, and unless I mis-understand, that is basically what I implemented so far.

Yes.

Quoted 3 lines

Copied state might be tricky.  I think if we hold any copies of capabilities data in the sdata, then it should be logically compared with a mask and then treated as an AND with whatever the wiphy has.

Not sure what you're saying here. I was thinking we'd simply do one of these two:

1) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht & user-config (semantically, not implementation of course)
2) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht

and change mac80211 to use sdata->sband instead of wiphy->sband wherever the latter is used today. That way, we can avoid touching all these things.

I think, for example, that you missed TDLS in your changes. Changing everything throughout would mean that grepping for "wiphy->sband" would immediately show such bugs, making it far easier to maintain.

Quoted 4 lines

  I'm reluctant to propose any serious mac80211 change at this point, though perhaps as more of this type of features are added, then it will become more obvious how to nicely consolidate things in mac80211.

I don't really think this would be a "serious" change? It's basically pointering changes, you could (and perhaps should, to catch it all) use an spatch to make the initial change.

Quoted 3 lines

To be honest, I thought my -v2 patches were fairly non-invasive compared to my normal hackings :)

:)

johannes

author
#10 lore raw
Quoted 31 lines · Johannes Berg
Quoted 11 lines · Ben Greear
Quoted 10 lines · Johannes Berg
Quoted 7 lines · Ben Greear

As far as I can tell, that will not work, because I want to have multiple station devices per radio, and have each of them be able to
use a different configuration. So, one station may be /g, and another /n and another /AC. Same with APs. In addition, some stations may want to use all available rates for their mode, and others may want to use a fixed rate or subset of available rates.

Quoted 5 lines
Quoted 2 lines

So let's agree that we're splitting the *used* rates (which we have today) and the *advertised* rates/modes/...

Yes, I think that will work well, and unless I mis-understand, that is basically what I implemented so far.

Yes.

Quoted 3 lines

Copied state might be tricky. I think if we hold any copies of capabilities data in the sdata, then it should be logically compared with a mask and then treated as an AND with whatever the wiphy has.

Not sure what you're saying here. I was thinking we'd simply do one of these two:

1) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht & user-config (semantically, not implementation of course)
2) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht

Quoted 7 lines

and change mac80211 to use sdata->sband instead of wiphy->sband wherever the latter is used today. That way, we can avoid touching all these things.

I think, for example, that you missed TDLS in your changes. Changing everything throughout would mean that grepping for "wiphy->sband" would immediately show such bugs, making it far easier to maintain.

I think option 1 might be better. For option 2, I'd be worried about someone changing the wiphy somehow and vdevs getting out of sync.

Any opinions on the lifetime for the sdata->sband_user_config data?

For instance, could be cleared when station dis-associates, or we could make it persist until changed or until vdev goes away?

And, while this would take care of some of the issues (3x3 vs 2x2?), it still wouldn't let someone have full control over the advertised rates vs configured-rates and such, would it?

So, your proposal is in addition to allowing advertised-rates to be configured?

Thanks,
Ben

Quoted 17 lines
Quoted 4 lines

I'm reluctant to propose any serious mac80211 change at this point,
though perhaps as more of this type of features are added, then it will become more obvious how to nicely consolidate things in mac80211.

I don't really think this would be a "serious" change? It's basically pointering changes, you could (and perhaps should, to catch it all) use an spatch to make the initial change.

Quoted 3 lines

To be honest, I thought my -v2 patches were fairly non-invasive compared to my normal hackings :)

:)

johannes

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#11 lore raw
Quoted 6 lines · Ben Greear
Quoted 3 lines

1) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht & user-config (semantically, not implementation of course)
2) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht

I think option 1 might be better.  For option 2, I'd be worried about someone changing the wiphy somehow and vdevs getting out of sync.

Huh? I'm confused. Those two options above weren't meant as options, they were meant as two sides of an "if (have-user-config)" branch :)

Quoted 4 lines

Any opinions on the lifetime for the sdata->sband_user_config data?

For instance, could be cleared when station dis-associates, or we could make it persist until changed or until vdev goes away?

Should probably persist.

Quoted 3 lines

And, while this would take care of some of the issues (3x3 vs 2x2?), it still wouldn't let someone have full control over the advertised rates vs configured-rates and such, would it?

Why not? The sband also contains the rates list. I was just using VHT as an example.

johannes

author
#12 lore raw
Quoted 11 lines · Johannes Berg
Quoted 6 lines · Ben Greear
Quoted 3 lines

1) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht & user-config (semantically, not implementation of course)
2) sdata->sband[5GHZ].vht = wiphy->sband[5GHZ].vht

I think option 1 might be better. For option 2, I'd be worried about someone changing the wiphy somehow and vdevs getting out of sync.

Huh? I'm confused. Those two options above weren't meant as options, they were meant as two sides of an "if (have-user-config)" branch :)

Oh. In that case, what if this happens:

wiphy created and init
vdev created, vht copied from wiphy
....
wiphy vht info changes? Can this ever happen? I'm thinking maybe when
a user uses 'iw' to set the rx/rx chainmask on a phy? Possibly nasty
debugfs hacks that have worked so far?

I wouldn't want to try to re-propagate that to already-created vdevs.

So, I think it should be more like:

if (vdata->have-user-config) {
return sdata->user_config_vht & sdata->wiphy->vht;
}
else {
return sdata->wiphy->vht;
}

Point of the above 'code' is that we do not want to ever have duplicate state (ie, a copy of wiphy->vht in sdata->vht, because then they can get out of sync. But, we can have a set of over-ride data in sdata, and since we logically AND that with wiphy data, then we should never exceed the capabilities of either sdata or wiphy.

That make sense?

Quoted 7 lines
Quoted 5 lines

Any opinions on the lifetime for the sdata->sband_user_config data?

For instance, could be cleared when station dis-associates, or we could make it persist until changed or until vdev goes away?

Should probably persist.

That is fine with me, would make supplicant patches easier than my method, probably.

Quoted 7 lines
Quoted 4 lines

And, while this would take care of some of the issues (3x3 vs 2x2?), it still wouldn't let someone have full control over the advertised rates vs configured-rates and such, would it?

Why not? The sband also contains the rates list. I was just using VHT as an example.

Ok, the details of mac80211 have leaked out of my skull since the start of this thread...I'll see if I can make a stab at implementing this proposal. But, likely it will be a bit, as I'm swamped with other things at the moment. If someone else is interested in trying this, then of course be my guest!

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#13 lore raw
Quoted 9 lines · Ben Greear

Oh.  In that case, what if this happens:

wiphy created and init
vdev created, vht copied from wiphy
....
wiphy vht info changes?  Can this ever happen?  I'm thinking maybe when
  a user uses 'iw' to set the rx/rx chainmask on a phy?  Possibly nasty debugfs hacks that have worked so far?

Ah, but I don't think this is something that's supposed to happen.

Then again, there were some people talking about this last week, with a use case that seemed valid (shared antennas and reconfiguration or so), but we can require that to cause some action to propagate it. My gut reaction was to just re-register the entire wiphy, but that may be too big of a hammer.

In any case, I think this isn't something we really need to consider too much. If there are bugs in this area then we'll fix them one way or another (or perhaps we'll just never find them since I don't expect many people to use this functionality).

Quoted 9 lines

So, I think it should be more like:

if (vdata->have-user-config) {
   return sdata->user_config_vht & sdata->wiphy->vht; }
else {
   return sdata->wiphy->vht;
}

Quoted 7 lines

Point of the above 'code' is that we do not want to ever have duplicate state (ie, a copy of wiphy->vht in sdata->vht, because then they can get out of sync.  But, we can have a set of over-ride data in sdata, and since we logically AND that with wiphy data, then we should never exceed the capabilities of either sdata or wiphy.

That make sense?

Yeah, it does, at least if you assume that the capabilities can actually change. We assume they don't though, hostapd/wpa_s for example will never re-query them after startup.

I also don't like the whole "call a function to get the capabilities" not much more than what you have now in the code, since then we'll have to deal with allocations (or stack memory) for the data we want and it just generally makes the code using the capabilities much more complex (for a pretty fringe use case.)

I'd much rather have the data structure that we can use as today without additional hoops to jump through, just possibly "redirecting" it for the use cases you have in mind.

Quoted 6 lines

Ok, the details of mac80211 have leaked out of my skull since the start of this thread...I'll see if I can make a stab at implementing this proposal.  But, likely it will be a bit, as I'm swamped with other things at the moment.  If someone else is interested in trying this, then of course be my guest!

Looked like Cedric Debarge had a similar idea, I've pointed him to this thread (as you probably saw.)

johannes

author
#14 lore raw
Quoted 40 lines · Johannes Berg
Quoted 9 lines · Ben Greear

Oh. In that case, what if this happens:

wiphy created and init
vdev created, vht copied from wiphy
....
wiphy vht info changes? Can this ever happen? I'm thinking maybe when
a user uses 'iw' to set the rx/rx chainmask on a phy? Possibly
nasty debugfs hacks that have worked so far?

Ah, but I don't think this is something that's supposed to happen.

Then again, there were some people talking about this last week, with a use case that seemed valid (shared antennas and reconfiguration or so), but we can require that to cause some action to propagate it. My gut reaction was to just re-register the entire wiphy, but that may be too big of a hammer.

In any case, I think this isn't something we really need to consider too much. If there are bugs in this area then we'll fix them one way or another (or perhaps we'll just never find them since I don't expect many people to use this functionality).

Quoted 15 lines

So, I think it should be more like:

if (vdata->have-user-config) {
    return sdata->user_config_vht & sdata->wiphy->vht;
}
else {
    return sdata->wiphy->vht;
}

Point of the above 'code' is that we do not want to ever have duplicate state (ie, a copy of wiphy->vht in sdata->vht, because then they can get out of sync. But, we can have a set of over-ride data in sdata, and since we logically AND that with wiphy data, then we should never exceed the capabilities of either sdata or wiphy.

Quoted 5 lines
Quoted 1 line

That make sense?

Yeah, it does, at least if you assume that the capabilities can actually change. We assume they don't though, hostapd/wpa_s for example will never re-query them after startup.

Restarting supplicant, even if it came to that, might be less of an issue than having to re-create the vdev to have it grab proper new settings from the wiphy...

Quoted 9 lines

I also don't like the whole "call a function to get the capabilities" not much more than what you have now in the code, since then we'll have to deal with allocations (or stack memory) for the data we want and it just generally makes the code using the capabilities much more complex (for a pretty fringe use case.)

I'd much rather have the data structure that we can use as today without additional hoops to jump through, just possibly "redirecting" it for the use cases you have in mind.

Well, it would be easy enough to make a method that updated an vdev/sdata->vht from wiphy, so could just call that as needed (ie, when certain things set or are changed by wiphy).

Quoted 9 lines
Quoted 6 lines

Ok, the details of mac80211 have leaked out of my skull since the start of this thread...I'll see if I can make a stab at implementing this proposal. But, likely it will be a bit, as I'm swamped with other things at the moment. If someone else is interested in trying this, then of course be my guest!

Looked like Cedric Debarge had a similar idea, I've pointed him to this thread (as you probably saw.)

Yeah, I tried to read the patch when first posted, but I am not sure I understand what he is trying to do.

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#15 lore raw
Quoted 11 lines · Ben Greear
Quoted 3 lines

Yeah, it does, at least if you assume that the capabilities can actually change. We assume they don't though, hostapd/wpa_s for example will never re-query them after startup.

Restarting supplicant, even if it came to that, might be less of an issue than having to re-create the vdev to have it grab proper new settings from the wiphy...

Well, it would be easy enough to make a method that updated an vdev/sdata->vht from wiphy, so could just call that as needed (ie, when certain things set or are changed by wiphy).

Yeah, I think we'll just have to deal with this when it comes along. This multi-antenna-sharing case (unfortunately I forgot who was talking about it) is the only thing that comes to mind where we really may have to deal with this.

johannes

author
#16 lore raw
Quoted 10 lines · Johannes Berg
Quoted 7 lines · Ben Greear
Quoted 3 lines

Yeah, it does, at least if you assume that the capabilities can actually change. We assume they don't though, hostapd/wpa_s for example will never re-query them after startup.

Restarting supplicant, even if it came to that, might be less of an issue than having to re-create the vdev to have it grab proper new settings from the wiphy...

Quoted 8 lines
Quoted 3 lines

Well, it would be easy enough to make a method that updated an vdev/sdata->vht from wiphy, so could just call that as needed (ie, when certain things set or are changed by wiphy).

Yeah, I think we'll just have to deal with this when it comes along. This multi-antenna-sharing case (unfortunately I forgot who was talking about it) is the only thing that comes to mind where we really may have to deal with this.

I started looking at making these changes...and I have a few questions.

First, are you proposing that I make a copy of the entire local->hw.wiphy->bands array and store it locally in sdata?

And then, I would provide some API to modify the bands[i]->bitrates and other variables to properly select the advertised features?

I am a bit concerned about making copies (and then changing) the driver's bitrates array. Likely it will work with ath10k, but it seems fragile at best.

Or, did I mis-understand your suggestion with regards to what data structures should be copied to sdata in mac80211 and then made modifiable?

With regard to my original patch, are there any other things that I could do to make it more acceptable without making copies of the driver data?

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#17 lore raw
Quoted 2 lines · Ben Greear

First, are you proposing that I make a copy of the entire  local-

Quoted 1 line

hw.wiphy->bands array and store it locally in sdata?

No, I think it should be pointers there, say

sdata->bands[X] pointing to the same thing as local->hw.wiphy->bands[X] is pointing to.

So the first patch would introduce that, and replace each and every use of local->hw.wiphy->bands[] with sdata->bands[], if necessary annotating the remaining ones with why they're OK and should stay.

Quoted 2 lines

And then, I would provide some API to modify the bands[i]->bitrates and other variables to properly select the advertised features?

Kinda. You'd provide some kind of helper function or API to take the local->hw.wiphy->bands[X] and duplicate it into a newly allocated buffer, modifying it along the way, before assigning it to the per- sdata stuff in sdata->bands[X].

Quoted 3 lines

I am a bit concerned about making copies (and then changing) the driver's bitrates array.  Likely it will work with ath10k, but it seems fragile at best.

That's an interesting point, we currently use the rate *index* a lot, so we have to find some way of preserving that. Perhaps we need to introduce a flag indicating a given rate is disabled?

johannes

author
#18 lore raw
Quoted 22 lines · Johannes Berg
Quoted 2 lines · Ben Greear

First, are you proposing that I make a copy of the entire local-

Quoted 1 line

hw.wiphy->bands array and store it locally in sdata?

No, I think it should be pointers there, say

sdata->bands[X] pointing to the same thing as local->hw.wiphy->bands[X] is pointing to.

So the first patch would introduce that, and replace each and every use of local->hw.wiphy->bands[] with sdata->bands[], if necessary annotating the remaining ones with why they're OK and should stay.

Quoted 2 lines

And then, I would provide some API to modify the bands[i]->bitrates and other variables to properly select the advertised features?

Kinda. You'd provide some kind of helper function or API to take the local->hw.wiphy->bands[X] and duplicate it into a newly allocated buffer, modifying it along the way, before assigning it to the per- sdata stuff in sdata->bands[X].

Quoted 7 lines
Quoted 3 lines

I am a bit concerned about making copies (and then changing) the driver's bitrates array. Likely it will work with ath10k, but it seems fragile at best.

That's an interesting point, we currently use the rate *index* a lot, so we have to find some way of preserving that. Perhaps we need to introduce a flag indicating a given rate is disabled?

The logic I wrote is basically exactly this. It uses the configured rates to specify which of the hardware's rates are allowed and disabled.

I will look more at providing some accessor functions or otherwise abstracting it without making copies of the driver's ratesets.

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#19 lore raw
Quoted 5 lines · Ben Greear


The logic I wrote is basically exactly this.  It uses the configured rates to specify which of the hardware's rates are allowed and disabled.

I understand that. I just take issue with the fact that we have to sprinkle "magic pixie dust" (in form of the override function calls) everywhere throughout the code.

johannes

author
#20 lore raw
Quoted 7 lines · Johannes Berg
Quoted 5 lines · Ben Greear

The logic I wrote is basically exactly this. It uses the configured rates to specify which of the hardware's rates are allowed and disabled.

Quoted 6 lines

I understand that. I just take issue with the fact that we have to sprinkle "magic pixie dust" (in form of the override function calls) everywhere throughout the code.

johannes

So, I never could think up a way to make this more acceptable and meet my own goals.

Any chance I could get just the netlink enum in place, even if it is called something like 'api_placeholder_x'?

Otherwise, it is about impossible for me to keep any sane forward/back compatibility with my hostap patches....

include/uapi/linux/nl80211.h +2 -0
index c0ab6b0..4573f87 100644
@@ -2130,6 +2130,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_REG_INDOOR,
 
+	NL80211_ATTR_TX_ADVERT_RATEMASK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,

Or, is there some other way to handle out-of-tree netlink stuff better?

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#21 lore raw
Quoted 14 lines · Ben Greear
Quoted 13 lines · Johannes Berg
Quoted 6 lines · Ben Greear

The logic I wrote is basically exactly this.  It uses the configured
rates to specify which of the hardware's rates are allowed and disabled.

I understand that. I just take issue with the fact that we have to sprinkle "magic pixie dust" (in form of the override function calls)
everywhere throughout the code.

Quoted 9 lines
Quoted 2 lines

johannes

So, I never could think up a way to make this more acceptable and meet my own goals.

Any chance I could get just the netlink enum in place, even if it is called something like 'api_placeholder_x'?

No, I don't think I want to do that.

But if you're not too worried about space consumption, you could pick a higher number:

	/* add attributes here, update the policy in nl80211.c */

	NL80211_ATTR_TX_ADVERT_RATEMASK = 300,

	__NL80211_ATTR_AFTER_LAST,

We currently use about 230 attributes, so that'll give you lots of breathing room.

johannes

author
#22 lore raw
Quoted 30 lines · Johannes Berg
Quoted 14 lines · Ben Greear
Quoted 13 lines · Johannes Berg
Quoted 6 lines · Ben Greear

The logic I wrote is basically exactly this. It uses the configured
rates to specify which of the hardware's rates are allowed and disabled.

I understand that. I just take issue with the fact that we have to sprinkle "magic pixie dust" (in form of the override function calls)
everywhere throughout the code.

Quoted 9 lines
Quoted 2 lines

johannes

So, I never could think up a way to make this more acceptable and meet my own goals.

Any chance I could get just the netlink enum in place, even if it is called something like 'api_placeholder_x'?

No, I don't think I want to do that.

But if you're not too worried about space consumption, you could pick a higher number:

Quoted 8 lines
	/* add attributes here, update the policy in nl80211.c */

	NL80211_ATTR_TX_ADVERT_RATEMASK = 300,

	__NL80211_ATTR_AFTER_LAST,

We currently use about 230 attributes, so that'll give you lots of breathing room.

From a pure hack point of view, maybe re-purposing some already existing attribute that has nothing to do with scanning is the way to go.

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
maintainer
#23 lore raw
In reply to Ben Greear
Quoted 5 lines · Ben Greear


With regard to my original patch, are there any other things that I could do to make it more acceptable without making copies of the driver data?

Oops, saw this too late.

I can't really think of anything that would really make me think it gets much better - by way of how it works we'd have to put code into every single place using this data, and I can't think of a way to abstract that out easily.

Perhaps if you can find a way to have some kind of "accessor functions" that would do the overrides, but I don't really see how that'd be possible.

johannes