]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Indicate link reconfiguration with QCA vendor interface
authorVeerendranath Jakkam <quic_vjakkam@quicinc.com>
Wed, 24 May 2023 19:49:52 +0000 (01:19 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 1 Jun 2023 15:21:13 +0000 (18:21 +0300)
Add support to indicate link reconfiguration event reported by the QCA
vendor interface to the wpa_supplicant control interface.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
src/common/wpa_ctrl.h
src/drivers/driver.h
src/drivers/driver_common.c
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_event.c
wpa_supplicant/events.c

index 57d69ae2eea487925b97e9810b9a2d938d91c1d6..06149ecc8a7abc4349c41ebf7ec383b5ab574c1c 100644 (file)
@@ -112,6 +112,8 @@ extern "C" {
 #define WPA_EVENT_SKIP_ROAM "CTRL-EVENT-SKIP-ROAM "
 /** TID-to-link mapping response event */
 #define WPA_EVENT_T2LM_UPDATE "CTRL-EVENT-T2LM-UPDATE "
+/** MLO link reconfiguration event */
+#define WPA_EVENT_LINK_RECONFIG "CTRL-EVENT-LINK-RECONFIG "
 
 /** IP subnet status change notification
  *
index c68cc415e665db7e7afb5b9fadfcafa93affeb9f..12371a7d81d5f79ec6ef1104d17fe893fd10dc12 100644 (file)
@@ -5664,6 +5664,11 @@ enum wpa_event_type {
         * Described in wpa_event_data.t2l_map_info.
         */
        EVENT_TID_LINK_MAP,
+
+       /**
+        * EVENT_LINK_RECONFIG - Notification that AP links removed
+        */
+       EVENT_LINK_RECONFIG,
 };
 
 
index 4dda51e7337b46a7ffcd6829c6a4548c9ad97e89..f3625e8c807a189043021429a35e642b33925751 100644 (file)
@@ -99,6 +99,7 @@ const char * event_to_string(enum wpa_event_type event)
        E2S(LINK_CH_SWITCH);
        E2S(LINK_CH_SWITCH_STARTED);
        E2S(TID_LINK_MAP);
+       E2S(LINK_RECONFIG);
        }
 
        return "UNKNOWN";
index d4353541c7c068d88d0e1a52aa9f29991d37e3eb..beba6741712c7f11d077fbbc70cc5a55a7670cde 100644 (file)
@@ -281,6 +281,8 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
        drv->pending_roam_data = NULL;
        os_free(drv->pending_t2lm_data);
        drv->pending_t2lm_data = NULL;
+       os_free(drv->pending_link_reconfig_data);
+       drv->pending_link_reconfig_data = NULL;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
        drv->auth_mld = false;
index 208c8b0434df8435fd97bc39674166cc9d4108f3..10a799e0d07702e04aa8229bbe3f8c8c0ec761b3 100644 (file)
@@ -257,6 +257,8 @@ struct wpa_driver_nl80211_data {
        size_t pending_roam_data_len;
        u8 *pending_t2lm_data;
        size_t pending_t2lm_data_len;
+       u8 *pending_link_reconfig_data;
+       size_t pending_link_reconfig_data_len;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 };
 
index bb3622970ee54241e5a2272fe80e46c9eaf217c3..bc1dd4371354835e0bb524cfe09d4b4858104802 100644 (file)
@@ -422,6 +422,78 @@ convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes
 }
 
 
+static void qca_nl80211_link_reconfig_event(struct wpa_driver_nl80211_data *drv,
+                                           u8 *data, size_t len)
+{
+       struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_MAX + 1];
+       u16 removed_links;
+       u8 *ap_mld;
+       int i;
+
+       if (!data)
+               return;
+
+       if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_MAX,
+                     (struct nlattr *) data, len, NULL) ||
+           !tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR])
+               return;
+
+       ap_mld = nla_data(tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR]);
+       wpa_printf(MSG_DEBUG, "nl80211: AP MLD address " MACSTR
+                  " received in link reconfig event", MAC2STR(ap_mld));
+       if (!drv->sta_mlo_info.valid_links ||
+           os_memcmp(drv->sta_mlo_info.ap_mld_addr, ap_mld, ETH_ALEN) != 0) {
+               if (drv->pending_link_reconfig_data == data) {
+                       wpa_printf(MSG_DEBUG,
+                                  "nl80211: Drop pending link reconfig event since AP MLD not matched even after new connect/roam event");
+                       os_free(drv->pending_link_reconfig_data);
+                       drv->pending_link_reconfig_data = NULL;
+                       return;
+               }
+
+               wpa_printf(MSG_DEBUG,
+                          "nl80211: Cache new link reconfig event till next connect/roam event");
+               if (drv->pending_link_reconfig_data) {
+                       wpa_printf(MSG_DEBUG, "nl80211: Override old link reconfig event data");
+                       os_free(drv->pending_link_reconfig_data);
+               }
+               drv->pending_link_reconfig_data = os_memdup(data, len);
+               if (!drv->pending_link_reconfig_data)
+                       return;
+               drv->pending_link_reconfig_data_len = len;
+               return;
+       }
+
+       if (!tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS])
+               return;
+       removed_links = nla_get_u16(
+               tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS]);
+
+       drv->sta_mlo_info.valid_links &= ~removed_links;
+
+       /*
+        * Set default BSSID to the BSSID of the lowest link ID of remaining
+        * links when the link used for (re)association is removed.
+        */
+       if (removed_links & BIT(drv->sta_mlo_info.assoc_link_id)) {
+               for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+                       if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+                               continue;
+
+                       os_memcpy(drv->bssid, drv->sta_mlo_info.links[i].bssid,
+                                 ETH_ALEN);
+                       drv->sta_mlo_info.assoc_link_id = i;
+                       break;
+               }
+       }
+
+       wpa_printf(MSG_DEBUG, "nl80211: Removed MLO links bitmap: 0x%x",
+                  removed_links);
+
+       wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
+}
+
+
 static void
 nl80211_parse_qca_vendor_mlo_link_info(struct driver_sta_mlo_info *mlo,
                                       struct nlattr *mlo_links)
@@ -1040,6 +1112,11 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                                                  drv->pending_t2lm_data_len);
        else
                drv->sta_mlo_info.default_map = true;
+
+       if (drv->pending_link_reconfig_data)
+               qca_nl80211_link_reconfig_event(
+                       drv, drv->pending_link_reconfig_data,
+                       drv->pending_link_reconfig_data_len);
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 }
 
@@ -2994,6 +3071,9 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
        case QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP:
                qca_nl80211_tid_to_link_map_event(drv, data, len);
                break;
+       case QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG:
+               qca_nl80211_link_reconfig_event(drv, data, len);
+               break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
        default:
                wpa_printf(MSG_DEBUG,
index 4af02c1ec0cd3511ebc6e07aa4705a54b5e6f9f9..e7aaa1a128423623cfa001dcbe57ab0bf61764ed 100644 (file)
@@ -5307,6 +5307,44 @@ static void wpas_tid_link_map(struct wpa_supplicant *wpa_s,
 }
 
 
+static void wpas_link_reconfig(struct wpa_supplicant *wpa_s)
+{
+       u8 bssid[ETH_ALEN];
+
+       if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+               wpa_printf(MSG_ERROR, "LINK_RECONFIG: Failed to get BSSID");
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+               return;
+       }
+
+       if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+               os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
+               wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
+               wpas_notify_bssid_changed(wpa_s);
+       }
+
+       if (wpa_drv_get_mlo_info(wpa_s) < 0) {
+               wpa_printf(MSG_ERROR,
+                          "LINK_RECONFIG: Failed to get MLO connection info");
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+               return;
+       }
+
+       if (wpa_sm_set_ml_info(wpa_s)) {
+               wpa_printf(MSG_ERROR,
+                          "LINK_RECONFIG: Failed to set MLO connection info to wpa_sm");
+               wpa_supplicant_deauthenticate(wpa_s,
+                                             WLAN_REASON_DEAUTH_LEAVING);
+               return;
+       }
+
+       wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_LINK_RECONFIG "valid_links=0x%x",
+               wpa_s->valid_links);
+}
+
+
 void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                          union wpa_event_data *data)
 {
@@ -5406,6 +5444,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpas_event_deauth(wpa_s,
                                  data ? &data->deauth_info : NULL);
                break;
+       case EVENT_LINK_RECONFIG:
+               wpas_link_reconfig(wpa_s);
+               break;
        case EVENT_MICHAEL_MIC_FAILURE:
                wpa_supplicant_event_michael_mic_failure(wpa_s, data);
                break;