]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_supplicant: Support ML probe request
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Mon, 12 Jun 2023 19:59:49 +0000 (22:59 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 29 Oct 2023 13:48:53 +0000 (15:48 +0200)
Add support for building and sending ML probe requests. During connect,
try to send an ML probe request if we are going to connect to an MLD AP
and the BSS information for some of the links is missing.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/common/ieee802_11_defs.h
wpa_supplicant/bss.c
wpa_supplicant/bss.h
wpa_supplicant/events.c
wpa_supplicant/notify.c
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 1dafba93a24fa7bcedc06cd362d6e554b48c86ae..a24e61fbea990125373ebb2982debe70e3f5332d 100644 (file)
@@ -2452,8 +2452,12 @@ struct ieee80211_he_mu_edca_parameter_set {
  */
 #define RNR_HEADER_LEN                              2
 #define RNR_TBTT_HEADER_LEN                         4
+#define RNR_TBTT_INFO_HDR_TYPE_MSK                  0x03
+#define RNR_TBTT_INFO_HDR_FILTERED_AP               0x04
+#define RNR_TBTT_INFO_HDR_CNT_MSK                   0xf0
 #define RNR_TBTT_INFO_COUNT(x)                      (((x) & 0xf) << 4)
 #define RNR_TBTT_INFO_COUNT_MAX                     16
+#define RNR_TBTT_INFO_COUNT_VAL(x)                  (((x) & 0xf0) >> 4)
 #define RNR_TBTT_INFO_LEN                           13
 #define RNR_TBTT_INFO_MLD_LEN                       16
 #define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN              255
index 320441426b64cafbfc2456f5e8015962c347ad76..47c7094c8eded582ca320406e973ecd4d323f137 100644 (file)
@@ -385,6 +385,9 @@ static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
        if (bss == wpa_s->current_bss)
                return 1;
 
+       if (bss == wpa_s->ml_connect_probe_bss)
+               return 1;
+
        if (wpa_s->current_bss &&
            (bss->ssid_len != wpa_s->current_bss->ssid_len ||
             os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
@@ -736,8 +739,13 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                                        break;
                                }
                        }
+
                        if (wpa_s->current_bss == bss)
                                wpa_s->current_bss = nbss;
+
+                       if (wpa_s->ml_connect_probe_bss == bss)
+                               wpa_s->ml_connect_probe_bss = nbss;
+
                        wpa_bss_update_pending_connect(wpa_s, bss, nbss);
                        bss = nbss;
                        os_memcpy(bss->ies, res + 1,
@@ -1468,3 +1476,235 @@ struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type)
 
        return ieee802_11_defrag_mle(&elems, type);
 }
+
+
+static void
+wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
+                            struct wpa_bss *bss, u8 mbssid_idx,
+                            const struct ieee80211_neighbor_ap_info *ap_info,
+                            size_t len, u16 *seen, u16 *missing)
+{
+       const u8 *pos, *end;
+       const u8 *mld_params;
+       u8 count, mld_params_offset;
+       u8 i, type, link_id;
+
+       count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
+       type = ap_info->tbtt_info_hdr & RNR_TBTT_INFO_HDR_TYPE_MSK;
+
+       /* MLD information is at offset 13 or at start */
+       if (type == 0 && ap_info->tbtt_info_len >= RNR_TBTT_INFO_MLD_LEN) {
+               /* MLD info is appended */
+               mld_params_offset = RNR_TBTT_INFO_LEN;
+       } else {
+               /* TODO: Support NSTR AP */
+               return;
+       }
+
+       pos = (const u8 *) ap_info;
+       end = pos + len;
+       pos += sizeof(*ap_info);
+
+       for (i = 0; i < count; i++) {
+               if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
+                       return;
+
+               if (end - pos < ap_info->tbtt_info_len)
+                       break;
+
+               mld_params = pos + mld_params_offset;
+
+               link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
+
+               if (*mld_params != mbssid_idx) {
+                       wpa_printf(MSG_DEBUG,
+                                  "MLD: Reported link not part of MLD");
+               } else if (!(BIT(link_id) & *seen)) {
+                       struct wpa_bss *neigh_bss =
+                               wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
+
+                       *seen |= BIT(link_id);
+                       wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
+                                  *mld_params, link_id);
+
+                       if (neigh_bss) {
+                               struct mld_link *l;
+
+                               l = &bss->mld_links[bss->n_mld_links];
+                               l->link_id = link_id;
+                               os_memcpy(l->bssid, ap_info->data + 1,
+                                         ETH_ALEN);
+                               l->freq = neigh_bss->freq;
+                               bss->n_mld_links++;
+                       } else {
+                               *missing |= BIT(link_id);
+                       }
+               }
+
+               pos += ap_info->tbtt_info_len;
+       }
+}
+
+
+/**
+ * wpa_bss_parse_basic_ml_element - Parse the Basic Multi-Link element
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bss: BSS table entry
+ * @mld_addr: AP MLD address (or %NULL)
+ * @link_info: Array to store link information (or %NULL),
+ *   should be initialized and #MAX_NUM_MLD_LINKS elements long
+ * @missing_links: Result bitmask of links that were not discovered (or %NULL)
+ * Returns: 0 on success or -1 for non-MLD or parsing failures
+ *
+ * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
+ * information stored in the wpa_supplicant data to fill in information for
+ * links where possible. The @missing_links out parameter will contain any links
+ * for which no corresponding BSS was found.
+ */
+int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
+                                  struct wpa_bss *bss,
+                                  u8 *ap_mld_addr,
+                                  u16 *missing_links)
+{
+       struct ieee802_11_elems elems;
+       struct wpabuf *mlbuf;
+       const struct element *elem;
+       u8 mbssid_idx = 0;
+       u8 ml_ie_len;
+       const struct ieee80211_eht_ml *eht_ml;
+       const struct eht_ml_basic_common_info *ml_basic_common_info;
+       u8 i, link_id;
+       const u16 control_mask =
+               MULTI_LINK_CONTROL_TYPE_MASK |
+               BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
+               BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
+               BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
+       const u16 control =
+               MULTI_LINK_CONTROL_TYPE_BASIC |
+               BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
+               BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
+               BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
+       u16 missing = 0;
+       u16 seen;
+       const u8 *ies_pos = wpa_bss_ie_ptr(bss);
+       size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+       int ret = -1;
+       struct mld_link *l;
+
+       if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 1) ==
+           ParseFailed) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed to parse elements");
+               return ret;
+       }
+
+       mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
+       if (!mlbuf) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
+               return ret;
+       }
+
+       ml_ie_len = wpabuf_len(mlbuf);
+
+       /*
+        * for ext ID + 2 control + common info len + MLD address +
+        * link info
+        */
+       if (ml_ie_len < 2UL + 1UL + ETH_ALEN + 1UL)
+               goto out;
+
+       eht_ml = (const struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
+       if ((le_to_host16(eht_ml->ml_control) & control_mask) != control) {
+               wpa_printf(MSG_DEBUG,
+                          "MLD: Unexpected Multi-Link element control=0x%x (mask 0x%x expected 0x%x)",
+                          le_to_host16(eht_ml->ml_control), control_mask,
+                          control);
+               goto out;
+       }
+
+       ml_basic_common_info =
+               (const struct eht_ml_basic_common_info *) eht_ml->variable;
+
+       /* Common info length should be valid */
+       if (ml_basic_common_info->len < ETH_ALEN + 1UL)
+               goto out;
+
+       /* Get the MLD address and MLD link ID */
+       if (ap_mld_addr)
+               os_memcpy(ap_mld_addr, ml_basic_common_info->mld_addr,
+                         ETH_ALEN);
+
+       bss->n_mld_links = 0;
+       l = &bss->mld_links[bss->n_mld_links];
+       link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
+       l->link_id = link_id;
+       os_memcpy(l->bssid, bss->bssid, ETH_ALEN);
+       l->freq = bss->freq;
+
+       seen = BIT(link_id);
+       bss->n_mld_links++;
+
+       /*
+        * The AP MLD ID in the RNR corresponds to the MBSSID index, see
+        * IEEE P802.11be/D4.0, 9.4.2.169.2 (Neighbor AP Information field).
+        *
+        * For the transmitting BSSID it is clear that both the MBSSID index
+        * and the AP MLD ID in the RNR are zero.
+        *
+        * For nontransmitted BSSIDs we will have a BSS generated from the
+        * MBSSID element(s) using inheritance rules. Included in the elements
+        * is the MBSSID Index Element. The RNR is copied from the Beacon/Probe
+        * Response frame that was send by the transmitting BSSID. As such, the
+        * reported AP MLD ID in the RNR will match the value in the MBSSID
+        * Index Element.
+        */
+       elem = (const struct element *)
+               wpa_bss_get_ie(bss, WLAN_EID_MULTIPLE_BSSID_INDEX);
+       if (elem && elem->datalen >= 1)
+               mbssid_idx = elem->data[0];
+
+       for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT,
+                           wpa_bss_ie_ptr(bss),
+                           bss->ie_len ? bss->ie_len : bss->beacon_ie_len) {
+               const struct ieee80211_neighbor_ap_info *ap_info;
+               const u8 *pos = elem->data;
+               size_t len = elem->datalen;
+
+               /* RNR IE may contain more than one Neighbor AP Info */
+               while (sizeof(*ap_info) <= len) {
+                       size_t ap_info_len = sizeof(*ap_info);
+                       u8 count;
+
+                       ap_info = (const struct ieee80211_neighbor_ap_info *)
+                               pos;
+                       count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
+                       ap_info_len += count * ap_info->tbtt_info_len;
+
+                       if (ap_info_len > len)
+                               goto out;
+
+                       wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
+                                                    ap_info, len, &seen,
+                                                    &missing);
+
+                       pos += ap_info_len;
+                       len -= ap_info_len;
+               }
+       }
+
+       wpa_printf(MSG_DEBUG, "MLD: n_mld_links=%u (unresolved: 0x%04hx)",
+                  bss->n_mld_links, missing);
+
+       for (i = 0; i < bss->n_mld_links; i++) {
+               wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
+                          bss->mld_links[i].link_id,
+                          MAC2STR(bss->mld_links[i].bssid));
+       }
+
+       if (missing_links)
+               *missing_links = missing;
+
+       ret = 0;
+out:
+       wpabuf_free(mlbuf);
+       return ret;
+}
index 611da88444a6cd61855c4c30d359412c39382feb..8a45814e40771032fdae296923542565129b9f7c 100644 (file)
@@ -124,6 +124,15 @@ struct wpa_bss {
        size_t beacon_ie_len;
        /** MLD address of the AP */
        u8 mld_addr[ETH_ALEN];
+
+       /** An array of MLD links */
+       u8 n_mld_links;
+       struct mld_link {
+               u8 link_id;
+               u8 bssid[ETH_ALEN];
+               int freq;
+       } mld_links[MAX_NUM_MLD_LINKS];
+
        /* followed by ie_len octets of IEs */
        /* followed by beacon_ie_len octets of IEs */
        u8 ies[];
@@ -202,5 +211,9 @@ void calculate_update_time(const struct os_reltime *fetch_time,
                           struct os_reltime *update_time);
 
 struct wpabuf * wpa_bss_defrag_mle(const struct wpa_bss *bss, u8 type);
+int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
+                                  struct wpa_bss *bss,
+                                  u8 *ap_mld_addr,
+                                  u16 *missing_links);
 
 #endif /* BSS_H */
index 9c308a5a34638c1e4bea6b303215b313cee23554..ccdb63598876b8691282e7d73ba6ff856c108c3e 100644 (file)
@@ -1832,6 +1832,76 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
 }
 
 
+static bool ml_link_probe_scan(struct wpa_supplicant *wpa_s)
+{
+       if (!wpa_s->ml_connect_probe_ssid || !wpa_s->ml_connect_probe_bss)
+               return false;
+
+       wpa_msg(wpa_s, MSG_DEBUG,
+               "Request association with " MACSTR " after ML probe",
+               MAC2STR(wpa_s->ml_connect_probe_bss->bssid));
+
+       wpa_supplicant_associate(wpa_s, wpa_s->ml_connect_probe_bss,
+                                wpa_s->ml_connect_probe_ssid);
+
+       wpa_s->ml_connect_probe_ssid = NULL;
+       wpa_s->ml_connect_probe_bss = NULL;
+
+       return true;
+}
+
+
+static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s,
+                                            struct wpa_bss *selected,
+                                            struct wpa_ssid *ssid)
+{
+       int *freqs;
+       u16 missing_links = 0;
+
+       if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
+             (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)))
+               return 0;
+
+       /* Try to resolve any missing link information */
+       if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
+                                          &missing_links) || !missing_links)
+               return 0;
+
+       wpa_dbg(wpa_s, MSG_DEBUG,
+               "MLD: Doing an ML probe for missing links 0x%04x",
+               missing_links);
+
+       freqs = os_malloc(sizeof(int) * 2);
+       if (!freqs)
+               return 0;
+
+       wpa_s->ml_connect_probe_ssid = ssid;
+       wpa_s->ml_connect_probe_bss = selected;
+
+       freqs[0] = selected->freq;
+       freqs[1] = 0;
+
+       wpa_s->manual_scan_passive = 0;
+       wpa_s->manual_scan_use_id = 0;
+       wpa_s->manual_scan_only_new = 0;
+       wpa_s->scan_id_count = 0;
+       os_free(wpa_s->manual_scan_freqs);
+       wpa_s->manual_scan_freqs = freqs;
+
+       os_memcpy(wpa_s->ml_probe_bssid, selected->bssid, ETH_ALEN);
+       wpa_s->ml_probe_mld_id = -1;
+       wpa_s->ml_probe_links = missing_links;
+
+       wpa_s->normal_scans = 0;
+       wpa_s->scan_req = MANUAL_SCAN_REQ;
+       wpa_s->after_wps = 0;
+       wpa_s->known_wps_freq = 0;
+       wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+       return 1;
+}
+
+
 int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
                           struct wpa_bss *selected,
                           struct wpa_ssid *ssid)
@@ -1888,6 +1958,10 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
                        wpa_supplicant_req_new_scan(wpa_s, 10, 0);
                        return 0;
                }
+
+               if (wpa_supplicant_connect_ml_missing(wpa_s, selected, ssid))
+                       return 0;
+
                wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR,
                        MAC2STR(selected->bssid));
                wpa_supplicant_associate(wpa_s, selected, ssid);
@@ -2315,6 +2389,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
            wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0)
                goto scan_work_done;
 
+       if (ml_link_probe_scan(wpa_s))
+               goto scan_work_done;
+
        if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
                goto scan_work_done;
 
index a2693587193229f3fbd4c196ab2c8a7204808f5a..0f9616d386221d495a46535d9e6fc8cd1332bdc1 100644 (file)
@@ -396,6 +396,10 @@ void wpas_notify_network_removed(struct wpa_supplicant *wpa_s,
                wpa_s->last_ssid = NULL;
        if (wpa_s->current_ssid == ssid)
                wpa_s->current_ssid = NULL;
+       if (wpa_s->ml_connect_probe_ssid == ssid) {
+               wpa_s->ml_connect_probe_ssid = NULL;
+               wpa_s->ml_connect_probe_bss = NULL;
+       }
 #if defined(CONFIG_SME) && defined(CONFIG_SAE)
        if (wpa_s->sme.ext_auth_wpa_ssid == ssid)
                wpa_s->sme.ext_auth_wpa_ssid = NULL;
index 166751a1f2a1a651bdf92bdc4c9e9877870bdc70..0212aab3fd4d064e78f902ef164ee8a347bb7e61 100644 (file)
@@ -649,6 +649,67 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
 }
 
 
+static struct wpabuf * wpa_supplicant_ml_probe_ie(int mld_id, u16 links)
+{
+       struct wpabuf *extra_ie;
+       u16 control = MULTI_LINK_CONTROL_TYPE_PROBE_REQ;
+       size_t len = 3 + 4 + 4 * MAX_NUM_MLD_LINKS;
+       u8 link_id;
+       u8 *len_pos;
+
+       if (mld_id >= 0) {
+               control |= EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID;
+               len++;
+       }
+
+       extra_ie = wpabuf_alloc(len);
+       if (!extra_ie)
+               return NULL;
+
+       wpabuf_put_u8(extra_ie, WLAN_EID_EXTENSION);
+       len_pos = wpabuf_put(extra_ie, 1);
+       wpabuf_put_u8(extra_ie, WLAN_EID_EXT_MULTI_LINK);
+
+       wpabuf_put_le16(extra_ie, control);
+
+       /* common info length and MLD ID (if requested) */
+       if (mld_id >= 0) {
+               wpabuf_put_u8(extra_ie, 2);
+               wpabuf_put_u8(extra_ie, mld_id);
+
+               wpa_printf(MSG_DEBUG, "MLD: ML probe targeted at MLD ID %d",
+                          mld_id);
+       } else {
+               wpabuf_put_u8(extra_ie, 1);
+
+               wpa_printf(MSG_DEBUG, "MLD: ML probe targeted at receiving AP");
+       }
+
+       if (!links)
+               wpa_printf(MSG_DEBUG, "MLD: Probing all links");
+       else
+               wpa_printf(MSG_DEBUG, "MLD: Probing links 0x%04x", links);
+
+       for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+               if (!(links & BIT(link_id)))
+                       continue;
+
+               wpabuf_put_u8(extra_ie, EHT_ML_SUB_ELEM_PER_STA_PROFILE);
+
+               /* Subelement length includes only the control */
+               wpabuf_put_u8(extra_ie, 2);
+
+               control = link_id | EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK;
+
+               wpabuf_put_le16(extra_ie, control);
+       }
+
+       *len_pos = (u8 *) wpabuf_put(extra_ie, 0) - len_pos - 1;
+
+       return extra_ie;
+}
+
+
 static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
 {
        struct wpabuf *extra_ie = NULL;
@@ -659,6 +720,15 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
        enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
 #endif /* CONFIG_WPS */
 
+       if (!is_zero_ether_addr(wpa_s->ml_probe_bssid)) {
+               extra_ie = wpa_supplicant_ml_probe_ie(wpa_s->ml_probe_mld_id,
+                                                     wpa_s->ml_probe_links);
+
+               /* No other elements should be included in the probe request */
+               wpa_printf(MSG_DEBUG, "MLD: Scan including only ML element");
+               return extra_ie;
+       }
+
 #ifdef CONFIG_P2P
        if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
                wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
@@ -1397,8 +1467,13 @@ ssid_list_set:
                                "Scan a previously specified BSSID " MACSTR,
                                MAC2STR(params.bssid));
                }
+       } else if (!is_zero_ether_addr(wpa_s->ml_probe_bssid)) {
+               wpa_printf(MSG_DEBUG, "Scanning for ML probe request");
+               params.bssid = wpa_s->ml_probe_bssid;
+               params.min_probe_req_content = true;
        }
 
+
        if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
            wpa_s->manual_non_coloc_6ghz) {
                wpa_dbg(wpa_s, MSG_DEBUG, "Collocated 6 GHz logic is disabled");
@@ -1480,6 +1555,10 @@ scan:
                if (params.bssid)
                        os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
        }
+
+       wpa_s->ml_probe_mld_id = -1;
+       wpa_s->ml_probe_links = 0;
+       os_memset(wpa_s->ml_probe_bssid, 0, sizeof(wpa_s->ml_probe_bssid));
 }
 
 
index 5faf58aa35a2acc64ccbe921ca14bbc0458789a5..d769dbd09e58e73ea8e7b28510d1f22617e5f6ae 100644 (file)
@@ -4456,6 +4456,8 @@ static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
 {
        struct wpa_ssid *old_ssid;
 
+       wpa_s->ml_connect_probe_ssid = NULL;
+       wpa_s->ml_connect_probe_bss = NULL;
        wpas_connect_work_done(wpa_s);
        wpa_clear_keys(wpa_s, addr);
        old_ssid = wpa_s->current_ssid;
@@ -5768,6 +5770,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
        dl_list_init(&wpa_s->drv_signal_override);
 #endif /* CONFIG_TESTING_OPTIONS */
        dl_list_init(&wpa_s->active_scs_ids);
+       wpa_s->ml_probe_mld_id = -1;
 
        return wpa_s;
 }
index c44413e4ebf228f7e074f232fd299947daeeb50d..a7d748ca948a4920c0899521de05f24d67c2059a 100644 (file)
@@ -904,6 +904,10 @@ struct wpa_supplicant {
        unsigned int suitable_network;
        unsigned int no_suitable_network;
 
+       u8 ml_probe_bssid[ETH_ALEN];
+       int ml_probe_mld_id;
+       u16 ml_probe_links;
+
        u64 drv_flags;
        u64 drv_flags2;
        unsigned int drv_enc;
@@ -1564,6 +1568,9 @@ struct wpa_supplicant {
        unsigned int wait_for_dscp_req:1;
 
        struct wpa_signal_info last_signal_info;
+
+       struct wpa_ssid *ml_connect_probe_ssid;
+       struct wpa_bss *ml_connect_probe_bss;
 };