Indicate link reconfiguration with QCA vendor interface

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>
This commit is contained in:
Veerendranath Jakkam 2023-05-25 01:19:52 +05:30 committed by Jouni Malinen
parent 7b9070229d
commit 8e16372cff
7 changed files with 133 additions and 0 deletions

View 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
*

View 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,
};

View 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";

View 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;

View 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 */
};

View 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,

View 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;