wifi: cfg80211: Handle specific BSSID in 6GHz scanning
authorIlan Peer <ilan.peer@intel.com>
Thu, 28 Sep 2023 14:35:30 +0000 (17:35 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 23 Oct 2023 09:43:28 +0000 (11:43 +0200)
When the scan parameters for a 6GHz scan specify a unicast
BSSID address, and the corresponding AP is found in the scan
list, add a corresponding entry in the collocated AP list,
so this AP would be directly probed even if it was not
advertised as a collocated AP.

This is needed for handling a scan request that is intended
for a ML probe flow, where user space can requests a scan
to retrieve information for other links in the AP MLD.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230928172905.54b954bc02ad.I1c072793d3d77a4c8fbbc64b4db5cce1bbb00382@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/scan.c

index 8d114faf48425b51d967cd7dbe7f02d7992b712a..6c2acd3fa36a234d3bb07a5188a34b22f63364ac 100644 (file)
@@ -830,10 +830,47 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
                list_for_each_entry(intbss, &rdev->bss_list, list) {
                        struct cfg80211_bss *res = &intbss->pub;
                        const struct cfg80211_bss_ies *ies;
+                       const struct element *ssid_elem;
+                       struct cfg80211_colocated_ap *entry;
+                       u32 s_ssid_tmp;
+                       int ret;
 
                        ies = rcu_access_pointer(res->ies);
                        count += cfg80211_parse_colocated_ap(ies,
                                                             &coloc_ap_list);
+
+                       /* In case the scan request specified a specific BSSID
+                        * and the BSS is found and operating on 6GHz band then
+                        * add this AP to the collocated APs list.
+                        * This is relevant for ML probe requests when the lower
+                        * band APs have not been discovered.
+                        */
+                       if (is_broadcast_ether_addr(rdev_req->bssid) ||
+                           !ether_addr_equal(rdev_req->bssid, res->bssid) ||
+                           res->channel->band != NL80211_BAND_6GHZ)
+                               continue;
+
+                       ret = cfg80211_calc_short_ssid(ies, &ssid_elem,
+                                                      &s_ssid_tmp);
+                       if (ret)
+                               continue;
+
+                       entry = kzalloc(sizeof(*entry) + IEEE80211_MAX_SSID_LEN,
+                                       GFP_ATOMIC);
+
+                       if (!entry)
+                               continue;
+
+                       memcpy(entry->bssid, res->bssid, ETH_ALEN);
+                       entry->short_ssid = s_ssid_tmp;
+                       memcpy(entry->ssid, ssid_elem->data,
+                              ssid_elem->datalen);
+                       entry->ssid_len = ssid_elem->datalen;
+                       entry->short_ssid_valid = true;
+                       entry->center_freq = res->channel->center_freq;
+
+                       list_add_tail(&entry->list, &coloc_ap_list);
+                       count++;
                }
                spin_unlock_bh(&rdev->bss_lock);
        }