From b094ea07e7a862b37d0b8de93be473d5825a9f1c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Feb 2016 22:12:47 +0200 Subject: [PATCH 1/6] cfg80211: Allow a scan request for a specific BSSID This allows scans for a specific BSSID to be optimized by the user space application by requesting the driver to set the Probe Request frame BSSID field (Address 3) to the specified BSSID instead of the wildcard BSSID. This prevents other APs from replying which reduces airtime need and latency in getting the response from the target AP through. This is an optimization and as such, it is acceptable for some of the drivers not to support the mechanism. If not supported, the wildcard BSSID will be used and more responses may be received. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Git-commit: 0889675a9503f48d1ad01b4eaa202f89469b2b62 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Change-Id: I20cf654661c11880055d022e0c9ec77beab659e8 CRs-fixed: 996660 Signed-off-by: Vidyullatha Kanchanapally --- include/net/cfg80211.h | 3 +++ include/uapi/linux/nl80211.h | 4 +++- net/wireless/nl80211.c | 6 ++++++ net/wireless/scan.c | 2 ++ net/wireless/sme.c | 2 ++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index eea536d2c2a4..77d139c9c2ba 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1281,6 +1281,7 @@ struct cfg80211_ssid { * @wdev: the wireless device to scan for * @aborted: (internal) scan request was notified as aborted * @no_cck: used to send probe requests at non CCK rate in 2GHz band + * @bssid: BSSID to scan for (most commonly, the wildcard BSSID) */ struct cfg80211_scan_request { struct cfg80211_ssid *ssids; @@ -1294,6 +1295,8 @@ struct cfg80211_scan_request { struct wireless_dev *wdev; + u8 bssid[ETH_ALEN] __aligned(2); + /* internal */ struct wiphy *wiphy; unsigned long scan_start; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 4f34f01170a5..db9d49db05cc 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -263,7 +263,9 @@ * @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the - * probe requests at CCK rate or not. + * probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to + * specify a BSSID to scan for; if not included, the wildcard BSSID will + * be used. * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to * NL80211_CMD_GET_SCAN and on the "scan" multicast group) * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a3186bd25e4e..c6d42b71c975 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5426,6 +5426,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) request->no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); + if (info->attrs[NL80211_ATTR_MAC]) + memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]), + ETH_ALEN); + else + eth_broadcast_addr(request->bssid); + request->wdev = wdev; request->wiphy = &rdev->wiphy; request->scan_start = jiffies; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e7f01206c721..c126f5b4f953 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1159,6 +1159,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, if (wiphy->bands[i]) creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; + eth_broadcast_addr(creq->bssid); + rdev->scan_req = creq; err = rdev_scan(rdev, creq); if (err) { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 581bb8ca4c39..0028a052f6c3 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -172,6 +172,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) wdev->conn->params.ssid_len); request->ssids[0].ssid_len = wdev->conn->params.ssid_len; + eth_broadcast_addr(request->bssid); + request->wdev = wdev; request->wiphy = &rdev->wiphy; request->scan_start = jiffies; From b6379505bf7f212fe9b76ff9390abd047bf39405 Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Tue, 19 Apr 2016 15:11:26 +0530 Subject: [PATCH 2/6] cfg80211: Define macro to indicate bssid based scan support Define macro to indicate backport support for bssid parameter in scan request. Change-Id: I542b0de66948610135cf69a3d24c1561017fe7a8 CRs-Fixed: 996660 Signed-off-by: Vidyullatha Kanchanapally --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 77d139c9c2ba..55ac3a8370a2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -64,6 +64,7 @@ struct wiphy; #define TDLS_MGMT_VERSION2 1 #define CFG80211_DEL_STA_V2 1 #define CFG80211_BSSID_HINT_BACKPORT 1 +#define CFG80211_SCAN_BSSID 1 /* * wireless hardware capability structures From 0543777ac6bf37ded235d86fd50ea3076dcf7832 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Mar 2016 13:53:27 +0300 Subject: [PATCH 3/6] cfg80211: Add option to specify previous BSSID for Connect command This extends NL80211_CMD_CONNECT to allow the NL80211_ATTR_PREV_BSSID attribute to be used similarly to way this was already allowed with NL80211_CMD_ASSOCIATE. This allows user space to request reassociation (instead of association) when already connected to an AP. This provides an option to reassociate within an ESS without having to disconnect and associate with the AP. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Git-commit: ba6fbacf9c073effaedf0c52fe7e52e2baf67725 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git Change-Id: Idfd211db838cdde40ecc02a1803eac5c1ebfbc77 CRs-fixed: 1004073 Signed-off-by: Vidyullatha Kanchanapally --- include/net/cfg80211.h | 2 ++ net/wireless/nl80211.c | 4 ++++ net/wireless/trace.h | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 55ac3a8370a2..9505be2f6f2e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1638,6 +1638,7 @@ struct cfg80211_ibss_params { * @ht_capa_mask: The bits of ht_capa which are to be used. * @vht_capa: VHT Capability overrides * @vht_capa_mask: The bits of vht_capa which are to be used. + * @prev_bssid: previous BSSID, if not %NULL use reassociate frame */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -1660,6 +1661,7 @@ struct cfg80211_connect_params { struct ieee80211_ht_cap ht_capa_mask; struct ieee80211_vht_cap vht_capa; struct ieee80211_vht_cap vht_capa_mask; + const u8 *prev_bssid; }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c6d42b71c975..b499fc115f2b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6949,6 +6949,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) connect.mfp = NL80211_MFP_NO; } + if (info->attrs[NL80211_ATTR_PREV_BSSID]) + connect.prev_bssid = + nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { connect.channel = ieee80211_get_channel(wiphy, diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ab452b0ed717..7260be99a8d3 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1176,6 +1176,7 @@ TRACE_EVENT(rdev_connect, __field(bool, privacy) __field(u32, wpa_versions) __field(u32, flags) + MAC_ENTRY(prev_bssid) ), TP_fast_assign( WIPHY_ASSIGN; @@ -1187,13 +1188,14 @@ TRACE_EVENT(rdev_connect, __entry->privacy = sme->privacy; __entry->wpa_versions = sme->crypto.wpa_versions; __entry->flags = sme->flags; + MAC_ASSIGN(prev_bssid, sme->prev_bssid); ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", ssid: %s, auth type: %d, privacy: %s, wpa versions: %u, " - "flags: %u", + "flags: %u, previous bssid: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid, __entry->auth_type, BOOL_TO_STR(__entry->privacy), - __entry->wpa_versions, __entry->flags) + __entry->wpa_versions, __entry->flags, MAC_PR_ARG(prev_bssid)) ); TRACE_EVENT(rdev_set_cqm_rssi_config, From 1bb5f2e905f614fc9125e47f97f35a5ccdb413c1 Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Wed, 27 Apr 2016 11:58:08 +0530 Subject: [PATCH 4/6] cfg80211: Define macro to indicate prev_bssid connect support Define macro to indicate backport support for prev_bssid parameter in connect request. This parameter allows the driver to decide whether to do a new association or a re-association on a cfg80211 connect request. Change-Id: I760e2999ec56c9aa0c44ac7b062ee1755192299f CRs-Fixed: 1004073 Signed-off-by: Vidyullatha Kanchanapally --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9505be2f6f2e..1d0a445d84bb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -65,6 +65,7 @@ struct wiphy; #define CFG80211_DEL_STA_V2 1 #define CFG80211_BSSID_HINT_BACKPORT 1 #define CFG80211_SCAN_BSSID 1 +#define CFG80211_CONNECT_PREV_BSSID 1 /* * wireless hardware capability structures From b2270d9ce1437ebb9a8972f14191245c005e756f Mon Sep 17 00:00:00 2001 From: "Kanchanapally, Vidyullatha" Date: Mon, 11 Apr 2016 15:16:01 +0530 Subject: [PATCH 5/6] cfg80211: Add option to report the bss entry in connect result Since cfg80211 maintains separate BSS table entries for APs if the same BSSID, SSID pair is seen on multiple channels, it is possible that it can map the current_bss to a BSS entry on the wrong channel. This current_bss will not get flushed unless disconnected and cfg80211 reports a wrong channel as the associated channel. Fix this by introducing a new cfg80211_connect_bss() function which is similar to cfg80211_connect_result(), but it includes an additional parameter: the bss the STA is connected to. This allows drivers to provide the exact bss entry that matches the BSS to which the connection was completed. Reviewed-by: Jouni Malinen Signed-off-by: Vidyullatha Kanchanapally Signed-off-by: Sunil Dutt Signed-off-by: Johannes Berg Git-commit: 81948527fce52c73c9a0742b8ec8d26b97f6c3c0 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git Change-Id: I5dc58b360b2bbce53493466a0bcd5363276c302a CRs-fixed: 1008791 Signed-off-by: Vidyullatha Kanchanapally --- Documentation/DocBook/80211.tmpl | 1 + include/net/cfg80211.h | 39 ++++++++++++++++++++++++++++---- net/wireless/core.h | 1 + net/wireless/sme.c | 27 +++++++++++++++++----- net/wireless/util.c | 2 +- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 0f6a3edcd44b..423c1bcec8b8 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -137,6 +137,7 @@ !Finclude/net/cfg80211.h __cfg80211_send_disassoc !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result +!Finclude/net/cfg80211.h cfg80211_connect_bss !Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_disconnected !Finclude/net/cfg80211.h cfg80211_ready_on_channel diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1d0a445d84bb..36a169f6d1d8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4019,6 +4019,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) #define CFG80211_TESTMODE_DUMP(cmd) #endif +/** + * cfg80211_connect_bss - notify cfg80211 of connection result + * + * @dev: network device + * @bssid: the BSSID of the AP + * @bss: entry of bss to which STA got connected to, can be obtained + * through cfg80211_get_bss (may be %NULL) + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @resp_ie: association response IEs (may be %NULL) + * @resp_ie_len: assoc response IEs length + * @status: status code, 0 for successful connection, use + * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you + * the real status code for failures. + * @gfp: allocation flags + * + * It should be called by the underlying driver whenever connect() has + * succeeded. This is similar to cfg80211_connect_result(), but with the + * option of identifying the exact bss entry for the connection. Only one of + * these functions should be called. + */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp); + /** * cfg80211_connect_result - notify cfg80211 of connection result * @@ -4036,10 +4062,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) * It should be called by the underlying driver whenever connect() has * succeeded. */ -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp); +static inline void +cfg80211_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, + u16 status, gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie, + resp_ie_len, status, gfp); +} /** * cfg80211_roamed - notify cfg80211 of roaming diff --git a/net/wireless/core.h b/net/wireless/core.h index 36d2d64a401d..589135c37756 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -223,6 +223,7 @@ struct cfg80211_event { const u8 *resp_ie; size_t req_ie_len; size_t resp_ie_len; + struct cfg80211_bss *bss; u16 status; } cr; struct { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 0028a052f6c3..0f928c3c8d8f 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -569,10 +569,11 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(country_ie); } -void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp) +/* Consumes bss object one way or another */ +void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, + struct cfg80211_bss *bss, const u8 *req_ie, + size_t req_ie_len, const u8 *resp_ie, + size_t resp_ie_len, u16 status, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -580,10 +581,21 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, unsigned long flags; CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); + if (bss) { + /* Make sure the bss entry provided by the driver is valid. */ + struct cfg80211_internal_bss *ibss = bss_from_pub(bss); + + if (WARN_ON(list_empty(&ibss->list))) { + cfg80211_put_bss(wdev->wiphy, bss); + return; + } + } ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); - if (!ev) + if (!ev) { + cfg80211_put_bss(wdev->wiphy, bss); return; + } ev->type = EVENT_CONNECT_RESULT; if (bssid) @@ -598,6 +610,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ev->cr.resp_ie_len = resp_ie_len; memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); } + if (bss) + cfg80211_hold_bss(bss_from_pub(bss)); + ev->cr.bss = bss; ev->cr.status = status; spin_lock_irqsave(&wdev->event_lock, flags); @@ -605,7 +620,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, spin_unlock_irqrestore(&wdev->event_lock, flags); queue_work(cfg80211_wq, &rdev->event_work); } -EXPORT_SYMBOL(cfg80211_connect_result); +EXPORT_SYMBOL(cfg80211_connect_bss); void __cfg80211_roamed(struct wireless_dev *wdev, struct cfg80211_bss *bss, diff --git a/net/wireless/util.c b/net/wireless/util.c index 6f093e4da8d8..7e34368114ec 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -775,7 +775,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.status, ev->cr.status == WLAN_STATUS_SUCCESS, - NULL); + ev->cr.bss); break; case EVENT_ROAMED: __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, From 66eac7fdbfc587240e0034d643b577c8b07d7e16 Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Wed, 27 Apr 2016 13:22:55 +0530 Subject: [PATCH 6/6] cfg80211: Define macro to indicate support for new cfg80211 connect api Define macro to indicate backport support for the new cfg80211 connect api. Change-Id: If77035ca928bf5bc5a27230d9b3f6d56ea6c8b99 CRs-Fixed: 1008791 Signed-off-by: Vidyullatha Kanchanapally --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 36a169f6d1d8..dcdb18f0225c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -66,6 +66,7 @@ struct wiphy; #define CFG80211_BSSID_HINT_BACKPORT 1 #define CFG80211_SCAN_BSSID 1 #define CFG80211_CONNECT_PREV_BSSID 1 +#define CFG80211_CONNECT_BSS 1 /* * wireless hardware capability structures