]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WNM: Follow BTM procedure if the last link is dropped
authorBenjamin Berg <benjamin.berg@intel.com>
Tue, 20 Feb 2024 13:18:26 +0000 (14:18 +0100)
committerJouni Malinen <j@w1.fi>
Sat, 2 Mar 2024 18:52:17 +0000 (20:52 +0200)
If the last link is dropped, it makes sense to follow the BTM procedure.
However, in that case we need to prevent reconnection to this link
specifically, while if the AP MLD is terminating we need to forbid
connecting to the AP MLD.

As such, add a new variable to track the BSSID or AP MLD MAC address.
Which one it refers to depends on whether wnm_link_removal is set.

This also simplifies the check in wnm_is_bss_excluded() and untangles it
from wpa_s->current_bss.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
wpa_supplicant/wnm_sta.c
wpa_supplicant/wpa_supplicant_i.h

index 8a14566a8d6926a084d80cc61bac743edfd971ce..bd4c1317dcbb533559874b3a7c68febab978d116 100644 (file)
@@ -1071,7 +1071,7 @@ static int wnm_send_bss_transition_mgmt_resp(
                wpabuf_put_data(buf, "\0\0\0\0\0\0", ETH_ALEN);
        }
 
-       if (status == WNM_BSS_TM_ACCEPT && !wpa_s->wnm_link_removal)
+       if (status == WNM_BSS_TM_ACCEPT && target_bssid)
                wnm_add_cand_list(wpa_s, &buf);
 
 #ifdef CONFIG_MBO
@@ -1467,15 +1467,34 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
         * set to 1, and the BSS Termination Included field is set to 1, only
         * one of the links is removed and the other links remain associated.
         * Ignore the Disassociation Imminent field in such a case.
+        *
+        * TODO: We should check if the AP has more than one link.
+        * TODO: We should pass the RX link and use that
         */
-       if (disassoc_imminent &&
-           (wpa_s->valid_links & (wpa_s->valid_links - 1)) != 0 &&
+       if (disassoc_imminent && wpa_s->valid_links &&
            (wpa_s->wnm_mode & WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT) &&
            (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED)) {
-               wpa_printf(MSG_INFO,
-                          "WNM: BTM request for a single MLO link - ignore disassociation imminent since other links remain associated");
-               disassoc_imminent = false;
+               /* If we still have a link, then just accept the request */
+               if (wpa_s->valid_links & (wpa_s->valid_links - 1)) {
+                       wpa_printf(MSG_INFO,
+                                  "WNM: BTM request for a single MLO link - ignore disassociation imminent since other links remain associated");
+                       disassoc_imminent = false;
+
+                       wnm_send_bss_transition_mgmt_resp(
+                               wpa_s, WNM_BSS_TM_ACCEPT, 0, 0, NULL);
+
+                       return;
+               }
+
+               /* The last link is being removed (which must be the assoc link)
+                */
                wpa_s->wnm_link_removal = true;
+               os_memcpy(wpa_s->wnm_dissoc_addr,
+                         wpa_s->links[wpa_s->mlo_assoc_link_id].bssid,
+                         ETH_ALEN);
+       } else {
+               os_memcpy(wpa_s->wnm_dissoc_addr, wpa_s->valid_links ?
+                         wpa_s->ap_mld_addr : wpa_s->bssid, ETH_ALEN);
        }
 
        if (disassoc_imminent) {
@@ -2034,8 +2053,6 @@ void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
 
 bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
-       unsigned int i;
-
        if (!(wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))
                return false;
 
@@ -2043,23 +2060,14 @@ bool wnm_is_bss_excluded(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
         * In case disassociation imminent is set, do no try to use a BSS to
         * which we are connected.
         */
-
-       if (wpa_s->current_bss &&
-           ether_addr_equal(wpa_s->current_bss->bssid, bss->bssid)) {
-               wpa_dbg(wpa_s, MSG_DEBUG,
-                       "WNM: Disassociation imminent: current BSS");
-               return true;
-       }
-
-       if (!wpa_s->valid_links)
-               return false;
-
-       for_each_link(wpa_s->valid_links, i) {
-               if (ether_addr_equal(wpa_s->links[i].bssid, bss->bssid)) {
-                       wpa_dbg(wpa_s, MSG_DEBUG,
-                               "WNM: MLD: Disassociation imminent: current link");
+       if (wpa_s->wnm_link_removal ||
+           !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) ||
+           is_zero_ether_addr(bss->mld_addr)) {
+               if (ether_addr_equal(bss->bssid, wpa_s->wnm_dissoc_addr))
+                       return true;
+       } else {
+               if (ether_addr_equal(bss->mld_addr, wpa_s->wnm_dissoc_addr))
                        return true;
-               }
        }
 
        return false;
index 80ea515aadfd7731d228b86195f0f8d685c84e93..97aa86279da8ba1acc9446796adc2695d6782268 100644 (file)
@@ -1305,6 +1305,7 @@ struct wpa_supplicant {
        u8 wnm_num_neighbor_report;
        u8 wnm_mode;
        bool wnm_link_removal;
+       u8 wnm_dissoc_addr[ETH_ALEN];
        u16 wnm_dissoc_timer;
        u8 wnm_bss_termination_duration[12];
        struct neighbor_report *wnm_neighbor_report_elements;