]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Handle disassociation notification with SME offload to driver
authorChenming Huang <quic_chenhuan@quicinc.com>
Thu, 28 Sep 2023 07:37:01 +0000 (13:07 +0530)
committerJouni Malinen <j@w1.fi>
Wed, 28 Feb 2024 20:17:52 +0000 (22:17 +0200)
For non-AP MLDs, clear STA entry from all affiliated links.

For legacy non-MLO case, find association link to clear the STA entry.

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
src/ap/drv_callbacks.c

index 35522d2d1210dd21239b64c43067c959c933d59d..8149019770570e7520b4aaae886e1c29bd31c121 100644 (file)
@@ -910,6 +910,54 @@ fail:
 }
 
 
+static void hostapd_remove_sta(struct hostapd_data *hapd, struct sta_info *sta)
+{
+       ap_sta_set_authorized(hapd, sta, 0);
+       sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+       hostapd_set_sta_flags(hapd, sta);
+       wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+       sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+       ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+       ap_free_sta(hapd, sta);
+}
+
+
+#ifdef CONFIG_IEEE80211BE
+static void hostapd_notif_disassoc_mld(struct hostapd_data *assoc_hapd,
+                                      struct sta_info *sta,
+                                      const u8 *addr)
+{
+       unsigned int link_id, i;
+       struct hostapd_data *tmp_hapd;
+       struct hapd_interfaces *interfaces = assoc_hapd->iface->interfaces;
+
+       /* Remove STA entry in non-assoc links */
+       for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+               if (!sta->mld_info.links[link_id].valid)
+                       continue;
+
+               for (i = 0; i < interfaces->count; i++) {
+                       struct sta_info *tmp_sta;
+
+                       tmp_hapd = interfaces->iface[i]->bss[0];
+
+                       if (!tmp_hapd->conf->mld_ap ||
+                           assoc_hapd == tmp_hapd ||
+                           assoc_hapd->conf->mld_id != tmp_hapd->conf->mld_id)
+                               continue;
+
+                       tmp_sta = ap_get_sta(tmp_hapd, addr);
+                       if (tmp_sta)
+                               ap_free_sta(tmp_hapd, tmp_sta);
+               }
+       }
+
+       /* Remove STA in assoc link */
+       hostapd_remove_sta(assoc_hapd, sta);
+}
+#endif /* CONFIG_IEEE80211BE */
+
+
 void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
 {
        struct sta_info *sta;
@@ -931,6 +979,48 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
                       HOSTAPD_LEVEL_INFO, "disassociated");
 
        sta = ap_get_sta(hapd, addr);
+#ifdef CONFIG_IEEE80211BE
+       if (hostapd_is_mld_ap(hapd)) {
+               struct hostapd_data *assoc_hapd;
+               unsigned int i;
+
+               if (!sta) {
+                       /* Find non-MLO cases from any of the affiliated AP
+                        * links. */
+                       for (i = 0; i < hapd->iface->interfaces->count; ++i) {
+                               struct hostapd_iface *h =
+                                       hapd->iface->interfaces->iface[i];
+                               struct hostapd_data *h_hapd = h->bss[0];
+                               struct hostapd_bss_config *hconf = h_hapd->conf;
+
+                               if (!hconf->mld_ap ||
+                                   hconf->mld_id != hapd->conf->mld_id)
+                                       continue;
+
+                               sta = ap_get_sta(h_hapd, addr);
+                               if (sta) {
+                                       if (!sta->mld_info.mld_sta) {
+                                               hapd = h_hapd;
+                                               goto legacy;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+               if (!sta) {
+                       wpa_printf(MSG_DEBUG,
+                          "Disassociation notification for unknown STA "
+                          MACSTR, MAC2STR(addr));
+                       return;
+               }
+               sta = hostapd_ml_get_assoc_sta(hapd, sta, &assoc_hapd);
+               if (sta)
+                       hostapd_notif_disassoc_mld(assoc_hapd, sta, addr);
+               return;
+       }
+
+legacy:
+#endif /* CONFIG_IEEE80211BE */
        if (sta == NULL) {
                wpa_printf(MSG_DEBUG,
                           "Disassociation notification for unknown STA "
@@ -938,13 +1028,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
                return;
        }
 
-       ap_sta_set_authorized(hapd, sta, 0);
-       sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
-       hostapd_set_sta_flags(hapd, sta);
-       wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
-       sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
-       ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
-       ap_free_sta(hapd, sta);
+       hostapd_remove_sta(hapd, sta);
 }