Optimize p2p client scan
Search for the GO BSS in scan cache
by iterating over all the interfaces and if found,
fetch the operating frequency and scan the operating frequency
alone in the first scan attempt.
Bug: 202751801
Test: Manual - 1. Start Auto GO on DUT1
2. Issue Scan on DUT2 and immediatly trigger p2p connect(through
NearbyShare)
3. Confirmed from the logs that supplicant HIDL is able to get the
GO BSS from wlan0 scan cache and able to connect by scanning only
GO operating frequency.
Change-Id: I24705d139bd7e6a075a4b0031aac8b29e572a6f0
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index b9882b2..6b554f1 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -141,12 +141,60 @@
return 0;
}
-static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params, int freq)
+static int setScanFreq(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params,
+ int freq, int operating_freq)
{
- if (freq == 2 || freq == 5) {
+ int frequency = operating_freq ? operating_freq : freq;
+ if (disabled_freq(wpa_s, frequency)) {
+ wpa_printf(MSG_ERROR,
+ "P2P: freq %d is not supported for a client.", frequency);
+ return -1;
+ }
+ /*
+ * Allocate memory for frequency array, allocate one extra
+ * slot for the zero-terminator.
+ */
+ params->freqs = (int *) os_calloc(2, sizeof(int));
+ if (params->freqs) {
+ params->freqs[0] = frequency;
+ } else {
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * setP2pCliOptimizedScanFreqsList - Fill the frequencies to scan in Scan
+ * parameters.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @params: Pointer to Scan parameters.
+ * @freq: Frequency/Band requested to scan by the application, possible values are,
+ * 0 - All the frequencies - full scan
+ * 2 - Frequencies in 2.4GHz
+ * 5 - Frequencies in 5GHz
+ * - Valid frequency
+ * @operating_freq: Frequency of BSS if found in scan cache
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params, int freq, int operating_freq)
+{
+ int ret;
+ /* If BSS is found in scan cache, first scan its operating frequency */
+ if (!wpa_s->p2p_join_scan_count && operating_freq) {
+ ret = setScanFreq(wpa_s, params, freq, operating_freq);
+ if (!ret) {
+ return ret;
+ }
+ }
+
+ /* Empty freq params means scan all the frequencies */
+ if (freq == 0) {
+ return 0;
+ }
+ else if (freq == 2 || freq == 5) {
+ /* Scan the frequencies in the band */
enum hostapd_hw_mode mode;
- int ret;
if (wpa_s->hw.modes == NULL) {
wpa_printf(MSG_DEBUG,
"P2P: Unknown what %dG channels the driver supports.", freq);
@@ -166,21 +214,9 @@
}
return ret;
} else {
- if (disabled_freq(wpa_s, freq)) {
- wpa_printf(MSG_ERROR,
- "P2P: freq %d is not supported for a client.", freq);
- return -1;
- }
- /*
- * Allocate memory for frequency array, allocate one extra
- * slot for the zero-terminator.
- */
- params->freqs = (int *) os_calloc(2, sizeof(int));
- if (params->freqs) {
- params->freqs[0] = freq;
- } else {
- return -ENOMEM;
- }
+ /* Scan the frequency requested by the application */
+ ret = setScanFreq(wpa_s, params, freq, 0);
+ return ret;
}
return 0;
}
@@ -231,6 +267,30 @@
return NULL;
}
+/**
+ * findBssBySsidFromAnyInterface - Fetch a BSS table entry based on SSID and optional BSSID
+ * by iterating through all the interfaces.
+ * @head: Head of Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsidFromAnyInterface(
+ struct wpa_supplicant *head, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_supplicant *wpa_s;
+ struct wpa_bss *bss = NULL;
+ for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
+ bss = findBssBySsid(wpa_s, bssid, ssid, ssid_len);
+ if (bss != NULL) {
+ return bss;
+ }
+ }
+ return bss;
+}
+
struct wpa_ssid* addGroupClientNetwork(
struct wpa_supplicant* wpa_s,
uint8_t *group_owner_bssid,
@@ -306,7 +366,7 @@
int joinScanReq(
struct wpa_supplicant* wpa_s,
const std::vector<uint8_t>& ssid,
- int freq)
+ int freq, int operating_freq)
{
int ret;
struct wpa_driver_scan_params params;
@@ -328,17 +388,16 @@
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
}
- wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d (reinvoke)",
- wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq);
+ wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d"
+ "BSS operating_freq from scan cache %d",
+ wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq, operating_freq);
/* Construct an optimized p2p scan channel list */
- if (freq > 0) {
- ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq);
- if (ret < 0) {
- wpa_printf(MSG_ERROR,
- "Failed to set frequency in p2p scan params, error = %d", ret);
- return -1;
- }
+ ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq, operating_freq);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "Failed to set frequency in p2p scan params, error = %d", ret);
+ return -1;
}
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
@@ -1774,40 +1833,32 @@
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND before group join.");
wpas_p2p_stop_find(wpa_s);
- struct wpa_bss *bss = findBssBySsid(
- wpa_s, peer_address.data(),
- ssid.data(), ssid.size());
- if (bss != NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Join group with Group Owner " MACSTR,
- MAC2STR(bss->bssid));
- if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
- // no need to notify group join failure here,
- // it will be handled by wpas_p2p_group_add_persistent
- // called in joinGroup.
- return {SupplicantStatusCode::FAILURE_UNKNOWN, "Failed to join a group."};
- }
- return {SupplicantStatusCode::SUCCESS, ""};
- }
-
- wpa_printf(MSG_INFO, "No matched BSS exists, try to find it by scan");
-
if (pending_scan_res_join_callback != NULL) {
wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
}
pending_join_scan_callback =
- [wpa_s, ssid, freq]() {
+ [wpa_s, ssid, peer_address, freq]() {
if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
return;
}
- int ret = joinScanReq(wpa_s, ssid, freq);
+ int operating_freq = 0;
+ struct wpa_bss *bss = findBssBySsidFromAnyInterface(
+ wpa_s->global->ifaces, peer_address.data(), ssid.data(), ssid.size());
+ if (bss != NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: Found Group owner " MACSTR "in scan cache",
+ MAC2STR(bss->bssid));
+ operating_freq = bss->freq;
+ }
+
+ int ret = joinScanReq(wpa_s, ssid, freq, operating_freq);
// for BUSY case, the scan might be occupied by WiFi.
// Do not give up immediately, but try again later.
if (-EBUSY == ret) {
- // re-schedule this join scan and don't consume retry count.
- if (pending_scan_res_join_callback) {
- pending_scan_res_join_callback();
- }
+ // re-schedule this join scan
+ eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+ eloop_register_timeout(0, P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS,
+ joinScanWrapper, wpa_s, NULL);
} else if (0 != ret) {
notifyGroupJoinFailure(wpa_s);
pending_scan_res_join_callback = NULL;