linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] scan bitrate advertising
@ 2011-07-18 16:08 Johannes Berg
  2011-07-18 16:08 ` [PATCH 1/2] cfg80211: allow userspace to control supported rates in scan Johannes Berg
  2011-07-18 16:08 ` [PATCH 2/2] mac80211: implement scan supported rates Johannes Berg
  0 siblings, 2 replies; 3+ messages in thread
From: Johannes Berg @ 2011-07-18 16:08 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

P2P requires to not advertise 11b rates in some
scans, but we scan on the main interface so we
need to know from userspace.

These two patches add the ability for userspace
to control the rates that are advertised.

johannes


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] cfg80211: allow userspace to control supported rates in scan
  2011-07-18 16:08 [PATCH 0/2] scan bitrate advertising Johannes Berg
@ 2011-07-18 16:08 ` Johannes Berg
  2011-07-18 16:08 ` [PATCH 2/2] mac80211: implement scan supported rates Johannes Berg
  1 sibling, 0 replies; 3+ messages in thread
From: Johannes Berg @ 2011-07-18 16:08 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Some P2P scans are not allowed to advertise
11b rates, but that is a rather special case
so instead of having that, allow userspace
to request the rate sets (per band) that are
advertised in scan probe request frames.

Since it's needed in two places now, factor
out some common code parsing a rate array.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |    7 ++++++
 include/net/cfg80211.h  |    3 ++
 net/wireless/core.h     |    4 +++
 net/wireless/nl80211.c  |   50 +++++++++++++++++++++++++++++-------------------
 net/wireless/scan.c     |    3 ++
 net/wireless/util.c     |   35 +++++++++++++++++++++++++++++++++
 6 files changed, 83 insertions(+), 19 deletions(-)

--- a/include/linux/nl80211.h	2011-07-18 14:05:02.000000000 +0200
+++ b/include/linux/nl80211.h	2011-07-18 15:18:13.000000000 +0200
@@ -1014,6 +1014,11 @@ enum nl80211_commands {
  * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
  *	necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
  *
+ * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
+ *	nested array attribute containing an entry for each band, with the entry
+ *	being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but
+ *	without the length restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1217,6 +1222,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
 	NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
 
+	NL80211_ATTR_SCAN_SUPP_RATES,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
--- a/include/net/cfg80211.h	2011-07-18 14:13:47.000000000 +0200
+++ b/include/net/cfg80211.h	2011-07-18 14:15:16.000000000 +0200
@@ -772,6 +772,7 @@ struct cfg80211_ssid {
  * @n_channels: total number of channels to scan
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
  * @dev: the interface
  * @aborted: (internal) scan request was notified as aborted
@@ -783,6 +784,8 @@ struct cfg80211_scan_request {
 	const u8 *ie;
 	size_t ie_len;
 
+	u32 rates[IEEE80211_NUM_BANDS];
+
 	/* internal */
 	struct wiphy *wiphy;
 	struct net_device *dev;
--- a/net/wireless/nl80211.c	2011-07-18 14:15:48.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-07-18 15:31:38.000000000 +0200
@@ -177,6 +177,7 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
 	[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
 	[NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
+	[NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
 };
 
 /* policy for the key attributes */
@@ -3324,7 +3325,6 @@ static int nl80211_trigger_scan(struct s
 	struct nlattr *attr;
 	struct wiphy *wiphy;
 	int err, tmp, n_ssids = 0, n_channels, i;
-	enum ieee80211_band band;
 	size_t ie_len;
 
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
@@ -3344,6 +3344,7 @@ static int nl80211_trigger_scan(struct s
 		if (!n_channels)
 			return -EINVAL;
 	} else {
+		enum ieee80211_band band;
 		n_channels = 0;
 
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -3404,6 +3405,8 @@ static int nl80211_trigger_scan(struct s
 			i++;
 		}
 	} else {
+		enum ieee80211_band band;
+
 		/* all channels */
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 			int j;
@@ -3450,6 +3453,28 @@ static int nl80211_trigger_scan(struct s
 		       request->ie_len);
 	}
 
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		request->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
+
+	if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
+		nla_for_each_nested(attr,
+				    info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
+				    tmp) {
+			enum ieee80211_band band = nla_type(attr);
+
+			if (band < 0 || band > IEEE80211_NUM_BANDS) {
+				err = -EINVAL;
+				goto out_free;
+			}
+			err = ieee80211_get_ratemask(wiphy->bands[band],
+						     nla_data(attr),
+						     nla_len(attr),
+						     &request->rates[band]);
+			if (err)
+				goto out_free;
+		}
+	}
+
 	request->dev = dev;
 	request->wiphy = &rdev->wiphy;
 
@@ -4336,25 +4361,12 @@ static int nl80211_join_ibss(struct sk_b
 			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
 		struct ieee80211_supported_band *sband =
 			wiphy->bands[ibss.channel->band];
-		int i, j;
-
-		if (n_rates == 0)
-			return -EINVAL;
+		int err;
 
-		for (i = 0; i < n_rates; i++) {
-			int rate = (rates[i] & 0x7f) * 5;
-			bool found = false;
-
-			for (j = 0; j < sband->n_bitrates; j++) {
-				if (sband->bitrates[j].bitrate == rate) {
-					found = true;
-					ibss.basic_rates |= BIT(j);
-					break;
-				}
-			}
-			if (!found)
-				return -EINVAL;
-		}
+		err = ieee80211_get_ratemask(sband, rates, n_rates,
+					     &ibss.basic_rates);
+		if (err)
+			return err;
 	}
 
 	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
--- a/net/wireless/core.h	2011-07-18 15:15:23.000000000 +0200
+++ b/net/wireless/core.h	2011-07-18 15:15:31.000000000 +0200
@@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_re
 
 u16 cfg80211_calculate_bitrate(struct rate_info *rate);
 
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+			   const u8 *rates, unsigned int n_rates,
+			   u32 *mask);
+
 int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 				 u32 beacon_int);
 
--- a/net/wireless/util.c	2011-07-18 15:13:31.000000000 +0200
+++ b/net/wireless/util.c	2011-07-18 15:37:10.000000000 +0200
@@ -1006,3 +1006,38 @@ int cfg80211_can_change_interface(struct
 
 	return -EBUSY;
 }
+
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+			   const u8 *rates, unsigned int n_rates,
+			   u32 *mask)
+{
+	int i, j;
+
+	if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
+		return -EINVAL;
+
+	*mask = 0;
+
+	for (i = 0; i < n_rates; i++) {
+		int rate = (rates[i] & 0x7f) * 5;
+		bool found = false;
+
+		for (j = 0; j < sband->n_bitrates; j++) {
+			if (sband->bitrates[j].bitrate == rate) {
+				found = true;
+				*mask |= BIT(j);
+				break;
+			}
+		}
+		if (!found)
+			return -EINVAL;
+	}
+
+	/*
+	 * mask must have at least one bit set here since we
+	 * didn't accept a 0-length rates array nor allowed
+	 * entries in the array that didn't exist
+	 */
+
+	return 0;
+}
--- a/net/wireless/scan.c	2011-07-18 14:16:06.000000000 +0200
+++ b/net/wireless/scan.c	2011-07-18 15:28:54.000000000 +0200
@@ -863,6 +863,9 @@ int cfg80211_wext_siwscan(struct net_dev
 			creq->n_ssids = 0;
 	}
 
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
+
 	rdev->scan_req = creq;
 	err = rdev->ops->scan(wiphy, dev, creq);
 	if (err) {



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/2] mac80211: implement scan supported rates
  2011-07-18 16:08 [PATCH 0/2] scan bitrate advertising Johannes Berg
  2011-07-18 16:08 ` [PATCH 1/2] cfg80211: allow userspace to control supported rates in scan Johannes Berg
@ 2011-07-18 16:08 ` Johannes Berg
  1 sibling, 0 replies; 3+ messages in thread
From: Johannes Berg @ 2011-07-18 16:08 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

Scanning currently uses the TX rate mask to
restrict the rate set, which is bogus. Make
it use the new set of rates from userspace.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h |    4 ++--
 net/mac80211/mlme.c        |    5 +++--
 net/mac80211/scan.c        |    6 +++---
 net/mac80211/util.c        |   12 +++++-------
 net/mac80211/work.c        |    3 ++-
 5 files changed, 15 insertions(+), 15 deletions(-)

--- a/net/mac80211/ieee80211_i.h	2011-07-18 17:50:39.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h	2011-07-18 17:52:50.000000000 +0200
@@ -1376,14 +1376,14 @@ int ieee80211_build_preq_ies(struct ieee
 			     enum ieee80211_band band, u32 rate_mask,
 			     u8 channel);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  u8 *dst,
+					  u8 *dst, u32 ratemask,
 					  const u8 *ssid, size_t ssid_len,
 					  const u8 *ie, size_t ie_len,
 					  bool directed);
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
 			      const u8 *ie, size_t ie_len,
-			      bool directed);
+			      u32 ratemask, bool directed);
 
 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
 				  const size_t supp_rates_len,
--- a/net/mac80211/mlme.c	2011-07-18 17:50:39.000000000 +0200
+++ b/net/mac80211/mlme.c	2011-07-18 17:52:50.000000000 +0200
@@ -1219,7 +1219,7 @@ static void ieee80211_mgd_probe_ap_send(
 	} else {
 		ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
 		ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
-					 true);
+					 (u32) -1, true);
 	}
 
 	ifmgd->probe_send_count++;
@@ -1304,7 +1304,8 @@ struct sk_buff *ieee80211_ap_probereq_ge
 
 	ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
 	skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
-					ssid + 2, ssid[1], NULL, 0, true);
+					(u32) -1, ssid + 2, ssid[1],
+					NULL, 0, true);
 
 	return skb;
 }
--- a/net/mac80211/scan.c	2011-07-18 17:50:39.000000000 +0200
+++ b/net/mac80211/scan.c	2011-07-18 17:52:50.000000000 +0200
@@ -228,7 +228,6 @@ ieee80211_scan_rx(struct ieee80211_sub_i
 static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 {
 	struct cfg80211_scan_request *req = local->scan_req;
-	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
 	enum ieee80211_band band;
 	int i, ielen, n_chans;
 
@@ -253,7 +252,7 @@ static bool ieee80211_prep_hw_scan(struc
 
 	ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
 					 req->ie, req->ie_len, band,
-					 sdata->rc_rateidx_mask[band], 0);
+					 req->rates[band], 0);
 	local->hw_scan_req->ie_len = ielen;
 
 	return true;
@@ -653,6 +652,7 @@ static void ieee80211_scan_state_send_pr
 {
 	int i;
 	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+	enum ieee80211_band band = local->hw.conf.channel->band;
 
 	for (i = 0; i < local->scan_req->n_ssids; i++)
 		ieee80211_send_probe_req(
@@ -660,7 +660,7 @@ static void ieee80211_scan_state_send_pr
 			local->scan_req->ssids[i].ssid,
 			local->scan_req->ssids[i].ssid_len,
 			local->scan_req->ie, local->scan_req->ie_len,
-			false);
+			local->scan_req->rates[band], false);
 
 	/*
 	 * After sending probe requests, wait for probe responses
--- a/net/mac80211/util.c	2011-07-18 17:50:39.000000000 +0200
+++ b/net/mac80211/util.c	2011-07-18 17:52:50.000000000 +0200
@@ -1016,7 +1016,7 @@ int ieee80211_build_preq_ies(struct ieee
 }
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  u8 *dst,
+					  u8 *dst, u32 ratemask,
 					  const u8 *ssid, size_t ssid_len,
 					  const u8 *ie, size_t ie_len,
 					  bool directed)
@@ -1049,9 +1049,7 @@ struct sk_buff *ieee80211_build_probe_re
 
 	buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
 					   local->hw.conf.channel->band,
-					   sdata->rc_rateidx_mask
-					   [local->hw.conf.channel->band],
-					   chan);
+					   ratemask, chan);
 
 	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
 				     ssid, ssid_len,
@@ -1072,12 +1070,12 @@ struct sk_buff *ieee80211_build_probe_re
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
 			      const u8 *ie, size_t ie_len,
-			      bool directed)
+			      u32 ratemask, bool directed)
 {
 	struct sk_buff *skb;
 
-	skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len,
-					directed);
+	skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
+					ie, ie_len, directed);
 	if (skb)
 		ieee80211_tx_skb(sdata, skb);
 }
--- a/net/mac80211/work.c	2011-07-18 17:50:39.000000000 +0200
+++ b/net/mac80211/work.c	2011-07-18 17:52:50.000000000 +0200
@@ -450,7 +450,8 @@ ieee80211_direct_probe(struct ieee80211_
 	 * will not answer to direct packet in unassociated state.
 	 */
 	ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
-				 wk->probe_auth.ssid_len, NULL, 0, true);
+				 wk->probe_auth.ssid_len, NULL, 0,
+				 (u32) -1, true);
 
 	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
 	run_again(local, wk->timeout);



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-07-18 16:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-18 16:08 [PATCH 0/2] scan bitrate advertising Johannes Berg
2011-07-18 16:08 ` [PATCH 1/2] cfg80211: allow userspace to control supported rates in scan Johannes Berg
2011-07-18 16:08 ` [PATCH 2/2] mac80211: implement scan supported rates Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).