* [PATCH v3 0/3] mac80211/cfg80211 scan improvements
@ 2009-03-31 10:12 Johannes Berg
2009-03-31 10:12 ` [PATCH v3 1/3] cfg80211: introduce scan IE limit attribute Johannes Berg
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Johannes Berg @ 2009-03-31 10:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, j
We currently don't tell userspace what the max IE length is,
fix that. We also have hw_scan build the probe request, which
is not necessary, mac80211 can do that.
I have, but will submit over a different channel, a patch to
fix up iwlwifi to support proper scanning after this series.
johannes
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v3 1/3] cfg80211: introduce scan IE limit attribute 2009-03-31 10:12 [PATCH v3 0/3] mac80211/cfg80211 scan improvements Johannes Berg @ 2009-03-31 10:12 ` Johannes Berg 2009-03-31 10:12 ` [PATCH v3 2/3] mac80211: pass all probe request IEs to driver Johannes Berg 2009-03-31 10:12 ` [PATCH v3 3/3] mac80211: include HT capabilities in probe request Johannes Berg 2 siblings, 0 replies; 5+ messages in thread From: Johannes Berg @ 2009-03-31 10:12 UTC (permalink / raw) To: John Linville; +Cc: linux-wireless, j This patch introduces a new attribute for a wiphy that tells userspace how long the information elements added to a probe request frame can be at most. It also updates the at76 to advertise that it cannot support that, and, for now until I can fix that, iwlwifi too. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- drivers/net/wireless/at76c50x-usb.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 1 + include/linux/nl80211.h | 4 ++++ include/net/wireless.h | 1 + net/mac80211/main.c | 13 ++++++++++++- net/mac80211/util.c | 2 ++ net/wireless/nl80211.c | 7 +++++++ 7 files changed, 28 insertions(+), 1 deletion(-) --- wireless-testing.orig/include/net/wireless.h 2009-03-31 11:42:22.000000000 +0200 +++ wireless-testing/include/net/wireless.h 2009-03-31 11:48:50.000000000 +0200 @@ -222,6 +222,7 @@ struct wiphy { int bss_priv_size; u8 max_scan_ssids; + u16 max_scan_ie_len; /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't --- wireless-testing.orig/net/wireless/nl80211.c 2009-03-31 11:42:22.000000000 +0200 +++ wireless-testing/net/wireless/nl80211.c 2009-03-31 11:48:50.000000000 +0200 @@ -151,6 +151,8 @@ static int nl80211_send_wiphy(struct sk_ NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); + NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, + dev->wiphy.max_scan_ie_len); nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) @@ -2492,6 +2494,11 @@ static int nl80211_trigger_scan(struct s else ie_len = 0; + if (ie_len > wiphy->max_scan_ie_len) { + err = -EINVAL; + goto out; + } + request = kzalloc(sizeof(*request) + sizeof(*ssid) * n_ssids + sizeof(channel) * n_channels --- wireless-testing.orig/include/linux/nl80211.h 2009-03-31 11:42:22.000000000 +0200 +++ wireless-testing/include/linux/nl80211.h 2009-03-31 11:48:50.000000000 +0200 @@ -380,6 +380,8 @@ enum nl80211_commands { * * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -492,6 +494,8 @@ enum nl80211_attrs { NL80211_ATTR_AUTH_TYPE, NL80211_ATTR_REASON_CODE, + NL80211_ATTR_MAX_SCAN_IE_LEN, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, --- wireless-testing.orig/net/mac80211/main.c 2009-03-31 11:48:49.000000000 +0200 +++ wireless-testing/net/mac80211/main.c 2009-03-31 11:48:50.000000000 +0200 @@ -724,7 +724,18 @@ struct ieee80211_hw *ieee80211_alloc_hw( return NULL; wiphy->privid = mac80211_wiphy_privid; - wiphy->max_scan_ssids = 4; + + if (!ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + wiphy->max_scan_ssids = 4; + + /* we support a maximum of 32 rates in cfg80211 */ + wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN + - 2 - 32 /* SSID */ + - 4 - 32 /* (ext) supp rates */; + + } + /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); --- wireless-testing.orig/net/mac80211/util.c 2009-03-31 11:48:49.000000000 +0200 +++ wireless-testing/net/mac80211/util.c 2009-03-31 11:48:50.000000000 +0200 @@ -891,6 +891,8 @@ void ieee80211_send_probe_req(struct iee *pos = rate->bitrate / 5; } + /* if adding more here, adjust max_scan_ie_len */ + if (ie) memcpy(skb_put(skb, ie_len), ie, ie_len); --- wireless-testing.orig/drivers/net/wireless/at76c50x-usb.c 2009-03-31 11:42:22.000000000 +0200 +++ wireless-testing/drivers/net/wireless/at76c50x-usb.c 2009-03-31 11:48:50.000000000 +0200 @@ -2248,6 +2248,7 @@ static int at76_init_new_device(struct a /* mac80211 initialisation */ priv->hw->wiphy->max_scan_ssids = 1; + priv->hw->wiphy->max_scan_ie_len = 0; priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | --- wireless-testing.orig/drivers/net/wireless/iwlwifi/iwl-core.c 2009-03-31 11:42:22.000000000 +0200 +++ wireless-testing/drivers/net/wireless/iwlwifi/iwl-core.c 2009-03-31 11:48:50.000000000 +0200 @@ -1306,6 +1306,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->wiphy->custom_regulatory = true; hw->wiphy->max_scan_ssids = 1; + hw->wiphy->max_scan_ie_len = 0; /* XXX for now */ /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; -- ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/3] mac80211: pass all probe request IEs to driver 2009-03-31 10:12 [PATCH v3 0/3] mac80211/cfg80211 scan improvements Johannes Berg 2009-03-31 10:12 ` [PATCH v3 1/3] cfg80211: introduce scan IE limit attribute Johannes Berg @ 2009-03-31 10:12 ` Johannes Berg 2009-04-01 9:58 ` [PATCH v4 " Johannes Berg 2009-03-31 10:12 ` [PATCH v3 3/3] mac80211: include HT capabilities in probe request Johannes Berg 2 siblings, 1 reply; 5+ messages in thread From: Johannes Berg @ 2009-03-31 10:12 UTC (permalink / raw) To: John Linville; +Cc: linux-wireless, j Instead of just passing the cfg80211-requested IEs, pass the locally generated ones as well. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- v2: * assume wiphy->max_scan_ie_len contains the limit *including* the IEs mac80211 passes (since the driver cannot know how long those will be) and adjust the driver's limit accordingly * keep track of original IEs and hand back the pristine cfg80211 request structure * mark the IE pointer const in the request struct v3: * move code to correct place (register_hw) * calculate upper limit for userspace scan IEs more accurately include/net/cfg80211.h | 2 - include/net/mac80211.h | 13 ++++--- net/mac80211/ieee80211_i.h | 9 +++-- net/mac80211/main.c | 49 +++++++++++++++++++-------- net/mac80211/scan.c | 24 +++++++++++++ net/mac80211/util.c | 79 +++++++++++++++++++++++++++------------------ net/wireless/nl80211.c | 3 + 7 files changed, 123 insertions(+), 56 deletions(-) --- wireless-testing.orig/include/net/mac80211.h 2009-03-31 11:42:15.000000000 +0200 +++ wireless-testing/include/net/mac80211.h 2009-03-31 11:48:51.000000000 +0200 @@ -1330,11 +1330,14 @@ enum ieee80211_ampdu_mlme_action { * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's * registered bands. The hardware (or the driver) needs to make sure - * that power save is disabled. When the scan finishes, - * ieee80211_scan_completed() must be called; note that it also must - * be called when the scan cannot finish because the hardware is - * turned off! Anything else is a bug! Returns a negative error code - * which will be seen in userspace. + * that power save is disabled. + * The @req ie/ie_len members are rewritten by mac80211 to contain the + * entire IEs after the SSID, so that drivers need not look at these + * at all but just send them after the SSID -- mac80211 includes the + * (extended) supported rates and HT information (where applicable). + * When the scan finishes, ieee80211_scan_completed() must be called; + * note that it also must be called when the scan cannot finish due to + * any error unless this callback returned a negative error code. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-03-31 11:42:15.000000000 +0200 +++ wireless-testing/net/mac80211/ieee80211_i.h 2009-03-31 11:48:51.000000000 +0200 @@ -671,7 +671,10 @@ struct ieee80211_local { struct cfg80211_scan_request int_scan_req; struct cfg80211_scan_request *scan_req; struct ieee80211_channel *scan_channel; + const u8 *orig_ies; + int orig_ies_len; int scan_channel_idx; + int scan_ies_len; enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; unsigned long last_scan_completed; @@ -1093,9 +1096,11 @@ void ieee80211_send_auth(struct ieee8021 u16 transaction, u16 auth_alg, u8 *extra, size_t extra_len, const u8 *bssid, int encrypt); +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len); + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, --- wireless-testing.orig/net/mac80211/util.c 2009-03-31 11:48:50.000000000 +0200 +++ wireless-testing/net/mac80211/util.c 2009-03-31 11:48:51.000000000 +0200 @@ -832,16 +832,57 @@ void ieee80211_send_auth(struct ieee8021 ieee80211_tx_skb(sdata, skb, encrypt); } +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_supported_band *sband; + u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; + int i; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + pos = buffer; + + *pos++ = WLAN_EID_SUPP_RATES; + supp_rates_len = pos; + *pos++ = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + + if (esupp_rates_len) { + *esupp_rates_len += 1; + } else if (*supp_rates_len == 8) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + esupp_rates_len = pos; + *pos++ = 1; + } else + *supp_rates_len += 1; + + *pos++ = rate->bitrate / 5; + } + + /* + * If adding more here, adjust code in main.c + * that calculates local->scan_ies_len. + */ + + if (ie) { + memcpy(pos, ie, ie_len); + pos += ie_len; + } + + return pos - buffer; +} + void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len) + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; + u8 *pos; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ie_len); @@ -868,33 +909,9 @@ void ieee80211_send_probe_req(struct iee *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; memcpy(pos, ssid, ssid_len); + pos += ssid_len; - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - /* if adding more here, adjust max_scan_ie_len */ - - if (ie) - memcpy(skb_put(skb, ie_len), ie, ie_len); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } --- wireless-testing.orig/net/mac80211/main.c 2009-03-31 11:48:50.000000000 +0200 +++ wireless-testing/net/mac80211/main.c 2009-03-31 11:48:51.000000000 +0200 @@ -725,22 +725,12 @@ struct ieee80211_hw *ieee80211_alloc_hw( wiphy->privid = mac80211_wiphy_privid; - if (!ops->hw_scan) { - /* For hw_scan, driver needs to set these up. */ - wiphy->max_scan_ssids = 4; - - /* we support a maximum of 32 rates in cfg80211 */ - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN - - 2 - 32 /* SSID */ - - 4 - 32 /* (ext) supp rates */; - - } - /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); local = wiphy_priv(wiphy); + local->hw.wiphy = wiphy; local->hw.priv = (char *)local + @@ -827,7 +817,7 @@ int ieee80211_register_hw(struct ieee802 enum ieee80211_band band; struct net_device *mdev; struct ieee80211_master_priv *mpriv; - int channels, i, j; + int channels, i, j, max_bitrates; /* * generic code guarantees at least one band, @@ -835,18 +825,23 @@ int ieee80211_register_hw(struct ieee802 * that hw.conf.channel is assigned */ channels = 0; + max_bitrates = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; - if (sband && !local->oper_channel) { + if (!sband) + continue; + if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = local->oper_channel = local->scan_channel = &sband->channels[0]; } - if (sband) - channels += sband->n_channels; + channels += sband->n_channels; + + if (max_bitrates < sband->n_bitrates) + max_bitrates = sband->n_bitrates; } local->int_scan_req.n_channels = channels; @@ -866,6 +861,30 @@ int ieee80211_register_hw(struct ieee802 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + /* + * Calculate scan IE length -- we need this to alloc + * memory and to subtract from the driver limit. It + * includes the (extended) supported rates and HT + * information -- SSID is the driver's responsibility. + */ + local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + + if (!local->ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + local->hw.wiphy->max_scan_ssids = 4; + local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + } + + /* + * If the driver supports any scan IEs, then assume the + * limit includes the IEs mac80211 will add, otherwise + * leave it at zero and let the driver sort it out; we + * still pass our IEs to the driver but userspace will + * not be allowed to in that case. + */ + if (local->hw.wiphy->max_scan_ie_len) + local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; --- wireless-testing.orig/net/mac80211/scan.c 2009-03-31 11:48:49.000000000 +0200 +++ wireless-testing/net/mac80211/scan.c 2009-03-31 11:48:51.000000000 +0200 @@ -286,6 +286,12 @@ void ieee80211_scan_completed(struct iee if (WARN_ON(!local->scan_req)) return; + if (local->hw_scanning) { + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; + } + if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; @@ -456,12 +462,28 @@ int ieee80211_start_scan(struct ieee8021 } if (local->ops->hw_scan) { - int rc; + u8 *ies; + int rc, ielen; + + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; local->hw_scanning = true; rc = drv_hw_scan(local, req); if (rc) { local->hw_scanning = false; + kfree(ies); + req->ie_len = local->orig_ies_len; + req->ie = local->orig_ies; return rc; } local->scan_sdata = scan_sdata; --- wireless-testing.orig/include/net/cfg80211.h 2009-03-31 11:42:15.000000000 +0200 +++ wireless-testing/include/net/cfg80211.h 2009-03-31 11:48:51.000000000 +0200 @@ -504,7 +504,7 @@ struct cfg80211_scan_request { int n_ssids; struct ieee80211_channel **channels; u32 n_channels; - u8 *ie; + const u8 *ie; size_t ie_len; /* internal */ --- wireless-testing.orig/net/wireless/nl80211.c 2009-03-31 11:48:50.000000000 +0200 +++ wireless-testing/net/wireless/nl80211.c 2009-03-31 11:48:51.000000000 +0200 @@ -2561,7 +2561,8 @@ static int nl80211_trigger_scan(struct s if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); - memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), + memcpy((void *)request->ie, + nla_data(info->attrs[NL80211_ATTR_IE]), request->ie_len); } -- ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 2/3] mac80211: pass all probe request IEs to driver 2009-03-31 10:12 ` [PATCH v3 2/3] mac80211: pass all probe request IEs to driver Johannes Berg @ 2009-04-01 9:58 ` Johannes Berg 0 siblings, 0 replies; 5+ messages in thread From: Johannes Berg @ 2009-04-01 9:58 UTC (permalink / raw) To: John Linville; +Cc: linux-wireless, j Instead of just passing the cfg80211-requested IEs, pass the locally generated ones as well. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- v2: * assume wiphy->max_scan_ie_len contains the limit *including* the IEs mac80211 passes (since the driver cannot know how long those will be) and adjust the driver's limit accordingly * keep track of original IEs and hand back the pristine cfg80211 request structure * mark the IE pointer const in the request struct v3: * move code to correct place (register_hw) * calculate upper limit for userspace scan IEs more accurately v4: * apply w/o op dbg patch include/net/cfg80211.h | 2 - include/net/mac80211.h | 13 ++++--- net/mac80211/ieee80211_i.h | 9 +++-- net/mac80211/main.c | 49 +++++++++++++++++++-------- net/mac80211/scan.c | 24 +++++++++++++ net/mac80211/util.c | 79 +++++++++++++++++++++++++++------------------ net/wireless/nl80211.c | 3 + 7 files changed, 123 insertions(+), 56 deletions(-) --- wireless-testing.orig/include/net/mac80211.h 2009-04-01 11:55:50.000000000 +0200 +++ wireless-testing/include/net/mac80211.h 2009-04-01 11:56:47.000000000 +0200 @@ -1330,11 +1330,14 @@ enum ieee80211_ampdu_mlme_action { * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's * registered bands. The hardware (or the driver) needs to make sure - * that power save is disabled. When the scan finishes, - * ieee80211_scan_completed() must be called; note that it also must - * be called when the scan cannot finish because the hardware is - * turned off! Anything else is a bug! Returns a negative error code - * which will be seen in userspace. + * that power save is disabled. + * The @req ie/ie_len members are rewritten by mac80211 to contain the + * entire IEs after the SSID, so that drivers need not look at these + * at all but just send them after the SSID -- mac80211 includes the + * (extended) supported rates and HT information (where applicable). + * When the scan finishes, ieee80211_scan_completed() must be called; + * note that it also must be called when the scan cannot finish due to + * any error unless this callback returned a negative error code. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-04-01 11:55:49.000000000 +0200 +++ wireless-testing/net/mac80211/ieee80211_i.h 2009-04-01 11:56:47.000000000 +0200 @@ -671,7 +671,10 @@ struct ieee80211_local { struct cfg80211_scan_request int_scan_req; struct cfg80211_scan_request *scan_req; struct ieee80211_channel *scan_channel; + const u8 *orig_ies; + int orig_ies_len; int scan_channel_idx; + int scan_ies_len; enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; unsigned long last_scan_completed; @@ -1093,9 +1096,11 @@ void ieee80211_send_auth(struct ieee8021 u16 transaction, u16 auth_alg, u8 *extra, size_t extra_len, const u8 *bssid, int encrypt); +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len); + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, --- wireless-testing.orig/net/mac80211/util.c 2009-04-01 11:56:02.000000000 +0200 +++ wireless-testing/net/mac80211/util.c 2009-04-01 11:56:47.000000000 +0200 @@ -831,16 +831,57 @@ void ieee80211_send_auth(struct ieee8021 ieee80211_tx_skb(sdata, skb, encrypt); } +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_supported_band *sband; + u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; + int i; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + pos = buffer; + + *pos++ = WLAN_EID_SUPP_RATES; + supp_rates_len = pos; + *pos++ = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + + if (esupp_rates_len) { + *esupp_rates_len += 1; + } else if (*supp_rates_len == 8) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + esupp_rates_len = pos; + *pos++ = 1; + } else + *supp_rates_len += 1; + + *pos++ = rate->bitrate / 5; + } + + /* + * If adding more here, adjust code in main.c + * that calculates local->scan_ies_len. + */ + + if (ie) { + memcpy(pos, ie, ie_len); + pos += ie_len; + } + + return pos - buffer; +} + void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len) + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; + u8 *pos; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ie_len); @@ -867,33 +908,9 @@ void ieee80211_send_probe_req(struct iee *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; memcpy(pos, ssid, ssid_len); + pos += ssid_len; - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - /* if adding more here, adjust max_scan_ie_len */ - - if (ie) - memcpy(skb_put(skb, ie_len), ie, ie_len); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } --- wireless-testing.orig/net/mac80211/main.c 2009-04-01 11:56:02.000000000 +0200 +++ wireless-testing/net/mac80211/main.c 2009-04-01 11:56:47.000000000 +0200 @@ -729,22 +729,12 @@ struct ieee80211_hw *ieee80211_alloc_hw( wiphy->privid = mac80211_wiphy_privid; - if (!ops->hw_scan) { - /* For hw_scan, driver needs to set these up. */ - wiphy->max_scan_ssids = 4; - - /* we support a maximum of 32 rates in cfg80211 */ - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN - - 2 - 32 /* SSID */ - - 4 - 32 /* (ext) supp rates */; - - } - /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); local = wiphy_priv(wiphy); + local->hw.wiphy = wiphy; local->hw.priv = (char *)local + @@ -831,7 +821,7 @@ int ieee80211_register_hw(struct ieee802 enum ieee80211_band band; struct net_device *mdev; struct ieee80211_master_priv *mpriv; - int channels, i, j; + int channels, i, j, max_bitrates; /* * generic code guarantees at least one band, @@ -839,18 +829,23 @@ int ieee80211_register_hw(struct ieee802 * that hw.conf.channel is assigned */ channels = 0; + max_bitrates = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; - if (sband && !local->oper_channel) { + if (!sband) + continue; + if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = local->oper_channel = local->scan_channel = &sband->channels[0]; } - if (sband) - channels += sband->n_channels; + channels += sband->n_channels; + + if (max_bitrates < sband->n_bitrates) + max_bitrates = sband->n_bitrates; } local->int_scan_req.n_channels = channels; @@ -870,6 +865,30 @@ int ieee80211_register_hw(struct ieee802 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + /* + * Calculate scan IE length -- we need this to alloc + * memory and to subtract from the driver limit. It + * includes the (extended) supported rates and HT + * information -- SSID is the driver's responsibility. + */ + local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + + if (!local->ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + local->hw.wiphy->max_scan_ssids = 4; + local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + } + + /* + * If the driver supports any scan IEs, then assume the + * limit includes the IEs mac80211 will add, otherwise + * leave it at zero and let the driver sort it out; we + * still pass our IEs to the driver but userspace will + * not be allowed to in that case. + */ + if (local->hw.wiphy->max_scan_ie_len) + local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; --- wireless-testing.orig/net/mac80211/scan.c 2009-04-01 11:55:51.000000000 +0200 +++ wireless-testing/net/mac80211/scan.c 2009-04-01 11:56:47.000000000 +0200 @@ -285,6 +285,12 @@ void ieee80211_scan_completed(struct iee if (WARN_ON(!local->scan_req)) return; + if (local->hw_scanning) { + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; + } + if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; @@ -457,12 +463,28 @@ int ieee80211_start_scan(struct ieee8021 } if (local->ops->hw_scan) { - int rc; + u8 *ies; + int rc, ielen; + + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; local->hw_scanning = true; rc = local->ops->hw_scan(local_to_hw(local), req); if (rc) { local->hw_scanning = false; + kfree(ies); + req->ie_len = local->orig_ies_len; + req->ie = local->orig_ies; return rc; } local->scan_sdata = scan_sdata; --- wireless-testing.orig/include/net/cfg80211.h 2009-04-01 11:55:50.000000000 +0200 +++ wireless-testing/include/net/cfg80211.h 2009-04-01 11:56:47.000000000 +0200 @@ -504,7 +504,7 @@ struct cfg80211_scan_request { int n_ssids; struct ieee80211_channel **channels; u32 n_channels; - u8 *ie; + const u8 *ie; size_t ie_len; /* internal */ --- wireless-testing.orig/net/wireless/nl80211.c 2009-04-01 11:56:02.000000000 +0200 +++ wireless-testing/net/wireless/nl80211.c 2009-04-01 11:56:47.000000000 +0200 @@ -2561,7 +2561,8 @@ static int nl80211_trigger_scan(struct s if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); - memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), + memcpy((void *)request->ie, + nla_data(info->attrs[NL80211_ATTR_IE]), request->ie_len); } ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 3/3] mac80211: include HT capabilities in probe request 2009-03-31 10:12 [PATCH v3 0/3] mac80211/cfg80211 scan improvements Johannes Berg 2009-03-31 10:12 ` [PATCH v3 1/3] cfg80211: introduce scan IE limit attribute Johannes Berg 2009-03-31 10:12 ` [PATCH v3 2/3] mac80211: pass all probe request IEs to driver Johannes Berg @ 2009-03-31 10:12 ` Johannes Berg 2 siblings, 0 replies; 5+ messages in thread From: Johannes Berg @ 2009-03-31 10:12 UTC (permalink / raw) To: John Linville; +Cc: linux-wireless, j Include the HT capabilities in the probe request frame. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> --- v2: fix the HT IE net/mac80211/main.c | 5 +++++ net/mac80211/util.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) --- wireless-testing.orig/net/mac80211/util.c 2009-03-31 11:48:51.000000000 +0200 +++ wireless-testing/net/mac80211/util.c 2009-03-31 11:48:51.000000000 +0200 @@ -862,6 +862,22 @@ int ieee80211_build_preq_ies(struct ieee *pos++ = rate->bitrate / 5; } + if (sband->ht_cap.ht_supported) { + __le16 tmp = cpu_to_le16(sband->ht_cap.cap); + + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + /* TODO: needs a define here for << 2 */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << 2); + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ + } + /* * If adding more here, adjust code in main.c * that calculates local->scan_ies_len. --- wireless-testing.orig/net/mac80211/main.c 2009-03-31 11:48:51.000000000 +0200 +++ wireless-testing/net/mac80211/main.c 2009-03-31 11:48:51.000000000 +0200 @@ -818,6 +818,7 @@ int ieee80211_register_hw(struct ieee802 struct net_device *mdev; struct ieee80211_master_priv *mpriv; int channels, i, j, max_bitrates; + bool supp_ht; /* * generic code guarantees at least one band, @@ -826,6 +827,7 @@ int ieee80211_register_hw(struct ieee802 */ channels = 0; max_bitrates = 0; + supp_ht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; @@ -842,6 +844,7 @@ int ieee80211_register_hw(struct ieee802 if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; + supp_ht = supp_ht || sband->ht_cap.ht_supported; } local->int_scan_req.n_channels = channels; @@ -868,6 +871,8 @@ int ieee80211_register_hw(struct ieee802 * information -- SSID is the driver's responsibility. */ local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + if (supp_ht) + local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ -- ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-04-01 9:59 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-03-31 10:12 [PATCH v3 0/3] mac80211/cfg80211 scan improvements Johannes Berg 2009-03-31 10:12 ` [PATCH v3 1/3] cfg80211: introduce scan IE limit attribute Johannes Berg 2009-03-31 10:12 ` [PATCH v3 2/3] mac80211: pass all probe request IEs to driver Johannes Berg 2009-04-01 9:58 ` [PATCH v4 " Johannes Berg 2009-03-31 10:12 ` [PATCH v3 3/3] mac80211: include HT capabilities in probe request 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).