]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MLD STA: Fetch MLO connection info into core wpa_supplicant
authorShivani Baranwal <quic_shivbara@quicinc.com>
Thu, 8 Sep 2022 14:44:11 +0000 (20:14 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 15 Sep 2022 02:55:40 +0000 (05:55 +0300)
Add support to fetch MLO connection info from the driver to the
wpa_supplicant instance of corresponding MLD STA interface. In addition,
return true for BSSs associated with MLO links from wpa_bss_in_use() to
avoid getting them cleared from scan results.

Co-authored-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/bss.c
wpa_supplicant/driver_i.h
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant_i.h

index 42be1bc6f80e3e05ca2a039a01a93f3950f0cc59..0852e1082c1bda27b9d01a7f35ecbe95b2092c8e 100644 (file)
@@ -4803,6 +4803,17 @@ struct wpa_driver_ops {
         */
        int (*send_pasn_resp)(void *priv, struct pasn_auth *params);
 
+       /**
+        * get_sta_mlo_info - Get the current multi-link association info
+        * @priv: Private driver interface data
+        * @mlo: Pointer to fill multi-link association info
+        * Returns: 0 on success, -1 on failure
+        *
+        * This callback is used to fetch multi-link of the current association.
+        */
+       int (*get_sta_mlo_info)(void *priv,
+                               struct driver_sta_mlo_info *mlo_info);
+
 #ifdef CONFIG_TESTING_OPTIONS
        int (*register_frame)(void *priv, u16 type,
                              const u8 *match, size_t match_len,
index c5daef49e78ef6dc99035e60ee2dd5320f257d83..4e216d83975e8814b42855f8d5215292c4b5cf6e 100644 (file)
@@ -1020,6 +1020,20 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
 }
 
 
+static int nl80211_get_sta_mlo_info(void *priv,
+                                   struct driver_sta_mlo_info *mlo_info)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+
+       if (!drv->associated)
+               return -1;
+
+       os_memcpy(mlo_info, &drv->sta_mlo_info, sizeof(*mlo_info));
+       return 0;
+}
+
+
 static void wpa_driver_nl80211_event_newlink(
        struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
        int ifindex, const char *ifname)
@@ -12777,6 +12791,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 #ifdef CONFIG_DPP
        .dpp_listen = nl80211_dpp_listen,
 #endif /* CONFIG_DPP */
+       .get_sta_mlo_info = nl80211_get_sta_mlo_info,
 #ifdef CONFIG_TESTING_OPTIONS
        .register_frame = testing_nl80211_register_frame,
        .radio_disable = testing_nl80211_radio_disable,
index eb97a618d043adc3bf00666e14b065a8ca2b6bec..7dcdb99694b3328d1e1fb31c06728d516036e20d 100644 (file)
@@ -379,6 +379,8 @@ static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 
 static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
+       int i;
+
        if (bss == wpa_s->current_bss)
                return 1;
 
@@ -388,9 +390,23 @@ static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
                       bss->ssid_len) != 0))
                return 0; /* SSID has changed */
 
-       return !is_zero_ether_addr(bss->bssid) &&
-               (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
-                os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0);
+       if (!is_zero_ether_addr(bss->bssid) &&
+           (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
+            os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0))
+               return 1;
+
+       if (!wpa_s->valid_links)
+               return 0;
+
+       for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+               if (!(wpa_s->valid_links & BIT(i)))
+                       continue;
+
+               if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0)
+                       return 1;
+       }
+
+       return 0;
 }
 
 
index d20e06136d2356c6a87250890a7d3d772b796441..41d353f911a5bf3b809e6bd800dc34e6fb14f847 100644 (file)
@@ -1152,4 +1152,14 @@ static inline int wpa_drv_set_secure_ranging_ctx(struct wpa_supplicant *wpa_s,
        return wpa_s->driver->set_secure_ranging_ctx(wpa_s->drv_priv, &params);
 }
 
+static inline int
+wpas_drv_get_sta_mlo_info(struct wpa_supplicant *wpa_s,
+                         struct driver_sta_mlo_info *mlo_info)
+{
+       if (!wpa_s->driver->get_sta_mlo_info)
+               return 0;
+
+       return wpa_s->driver->get_sta_mlo_info(wpa_s->drv_priv, mlo_info);
+}
+
 #endif /* DRIVER_I_H */
index b3b2c49329bb72fa5ff69ec7ee8def9d56d2ce1b..a9447c59bd5f74e478ce0588e12cd94852df8de4 100644 (file)
@@ -167,6 +167,21 @@ wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid)
 }
 
 
+static void wpa_supplicant_update_link_bss(struct wpa_supplicant *wpa_s,
+                                          u8 link_id, const u8 *bssid)
+{
+       struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+
+       if (!bss) {
+               wpa_supplicant_update_scan_results(wpa_s);
+               bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+       }
+
+       if (bss)
+               wpa_s->links[link_id].bss = bss;
+}
+
+
 static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
 {
        struct wpa_ssid *ssid, *old_ssid;
@@ -285,6 +300,19 @@ void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx)
 }
 
 
+static void wpas_reset_mlo_info(struct wpa_supplicant *wpa_s)
+{
+       int i;
+
+       if (!wpa_s->valid_links)
+               return;
+
+       wpa_s->valid_links = 0;
+       for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
+               wpa_s->links[i].bss = NULL;
+}
+
+
 void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
 {
        int bssid_changed;
@@ -352,6 +380,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
 
        if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
                wpa_s->enabled_4addr_mode = 0;
+
+       wpas_reset_mlo_info(wpa_s);
 }
 
 
@@ -3325,6 +3355,60 @@ static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s,
 }
 
 
+static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s)
+{
+       struct driver_sta_mlo_info mlo;
+       int i;
+
+       mlo.valid_links = 0;
+       if (wpas_drv_get_sta_mlo_info(wpa_s, &mlo)) {
+               wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO link info");
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+               return -1;
+       }
+
+       if (wpa_s->valid_links == mlo.valid_links) {
+               bool match = true;
+
+               if (!mlo.valid_links)
+                       return 0;
+
+               for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+                       if (!(mlo.valid_links & BIT(i)))
+                               continue;
+
+                       if (os_memcmp(wpa_s->links[i].addr, mlo.links[i].addr,
+                                     ETH_ALEN) != 0 ||
+                           os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid,
+                                     ETH_ALEN) != 0) {
+                               match = false;
+                               break;
+                       }
+               }
+
+               if (match &&
+                   os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr,
+                             ETH_ALEN) == 0)
+                       return 0;
+       }
+
+       wpa_s->valid_links = mlo.valid_links;
+       os_memcpy(wpa_s->ap_mld_addr, mlo.ap_mld_addr, ETH_ALEN);
+       for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+               if (!(wpa_s->valid_links & BIT(i)))
+                       continue;
+
+               os_memcpy(wpa_s->links[i].addr, mlo.links[i].addr, ETH_ALEN);
+               os_memcpy(wpa_s->links[i].bssid, mlo.links[i].bssid, ETH_ALEN);
+               wpa_s->links[i].freq = mlo.links[i].freq;
+               wpa_supplicant_update_link_bss(wpa_s, i, mlo.links[i].bssid);
+       }
+
+       return 0;
+}
+
+
 static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                                       union wpa_event_data *data)
 {
@@ -3360,6 +3444,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                return;
        }
 
+       if (wpa_drv_get_mlo_info(wpa_s) < 0) {
+               wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO connection info");
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+               return;
+       }
+
        if (ft_completed &&
            (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION)) {
                wpa_msg(wpa_s, MSG_INFO, "Attempt to roam to " MACSTR,
index 84a22a296964c336fc37d0b5bc015021c8d11bb9..813e5ac1b80cd9912f0fc044eee0394c594be3e6 100644 (file)
@@ -739,6 +739,14 @@ struct wpa_supplicant {
        struct wpa_bss *current_bss;
        int ap_ies_from_associnfo;
        unsigned int assoc_freq;
+       u8 ap_mld_addr[ETH_ALEN];
+       u8 valid_links; /* bitmap of valid MLO link IDs */
+       struct {
+               u8 addr[ETH_ALEN];
+               u8 bssid[ETH_ALEN];
+               unsigned int freq;
+               struct wpa_bss *bss;
+       } links[MAX_NUM_MLD_LINKS];
        u8 *last_con_fail_realm;
        size_t last_con_fail_realm_len;