AP NLD: Extend support for cohosted ML BSS
Modify necessary helper functions to support multiple BSS support for MLO to make the changes scalable. Signed-off-by: Sriram R <quic_srirrama@quicinc.com> Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
This commit is contained in:
parent
3d0cc612fc
commit
d9c5d601f1
3 changed files with 83 additions and 111 deletions
|
@ -4556,7 +4556,7 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
|
||||||
bool offload)
|
bool offload)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
unsigned int i, j;
|
unsigned int i;
|
||||||
|
|
||||||
if (!hostapd_is_mld_ap(hapd))
|
if (!hostapd_is_mld_ap(hapd))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4571,25 +4571,25 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
|
||||||
hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
|
hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
|
||||||
|
|
||||||
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
struct hostapd_iface *iface = NULL;
|
struct hostapd_data *bss = NULL;
|
||||||
struct mld_link_info *link = &sta->mld_info.links[i];
|
struct mld_link_info *link = &sta->mld_info.links[i];
|
||||||
|
bool link_bss_found = false;
|
||||||
|
|
||||||
if (!link->valid)
|
if (!link->valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < hapd->iface->interfaces->count; j++) {
|
for_each_mld_link(bss, hapd) {
|
||||||
iface = hapd->iface->interfaces->iface[j];
|
if (bss == hapd)
|
||||||
|
|
||||||
if (hapd->iface == iface)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (hostapd_is_ml_partner(hapd, iface->bss[0]) &&
|
if (bss->mld_link_id != i)
|
||||||
i == iface->bss[0]->mld_link_id)
|
continue;
|
||||||
break;
|
|
||||||
|
link_bss_found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iface || j == hapd->iface->interfaces->count ||
|
if (!link_bss_found || TEST_FAIL()) {
|
||||||
TEST_FAIL()) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"MLD: No link match for link_id=%u", i);
|
"MLD: No link match for link_id=%u", i);
|
||||||
|
|
||||||
|
@ -4602,7 +4602,7 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
|
||||||
if (!offload)
|
if (!offload)
|
||||||
ieee80211_ml_build_assoc_resp(hapd, link);
|
ieee80211_ml_build_assoc_resp(hapd, link);
|
||||||
} else {
|
} else {
|
||||||
if (ieee80211_ml_process_link(iface->bss[0], sta, link,
|
if (ieee80211_ml_process_link(bss, sta, link,
|
||||||
ies, ies_len, reassoc,
|
ies, ies_len, reassoc,
|
||||||
offload))
|
offload))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -5765,7 +5765,7 @@ static bool hostapd_ml_handle_disconnect(struct hostapd_data *hapd,
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
struct hostapd_data *assoc_hapd, *tmp_hapd;
|
struct hostapd_data *assoc_hapd, *tmp_hapd;
|
||||||
struct sta_info *assoc_sta;
|
struct sta_info *assoc_sta;
|
||||||
unsigned int i, link_id;
|
struct sta_info *tmp_sta;
|
||||||
|
|
||||||
if (!hostapd_is_mld_ap(hapd))
|
if (!hostapd_is_mld_ap(hapd))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5778,45 +5778,25 @@ static bool hostapd_ml_handle_disconnect(struct hostapd_data *hapd,
|
||||||
if (!assoc_sta)
|
if (!assoc_sta)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for_each_mld_link(tmp_hapd, assoc_hapd) {
|
||||||
for (i = 0; i < assoc_hapd->iface->interfaces->count; i++) {
|
if (tmp_hapd == assoc_hapd)
|
||||||
struct sta_info *tmp_sta;
|
continue;
|
||||||
|
|
||||||
if (!assoc_sta->mld_info.links[link_id].valid)
|
if (!assoc_sta->mld_info.links[tmp_hapd->mld_link_id].valid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
||||||
|
tmp_sta = tmp_sta->next) {
|
||||||
|
if (tmp_sta->mld_assoc_link_id !=
|
||||||
|
assoc_sta->mld_assoc_link_id ||
|
||||||
|
tmp_sta->aid != assoc_sta->aid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp_hapd =
|
if (!disassoc)
|
||||||
assoc_hapd->iface->interfaces->iface[i]->bss[0];
|
hostapd_deauth_sta(tmp_hapd, tmp_sta, mgmt);
|
||||||
|
else
|
||||||
if (!hostapd_is_ml_partner(assoc_hapd, tmp_hapd))
|
hostapd_disassoc_sta(tmp_hapd, tmp_sta, mgmt);
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
|
||||||
tmp_sta = tmp_sta->next) {
|
|
||||||
/*
|
|
||||||
* Remove the station on which the association
|
|
||||||
* was done only after all other link stations
|
|
||||||
* are removed. Since there is only a single
|
|
||||||
* station per struct hostapd_hapd with the
|
|
||||||
* same association link simply break out from
|
|
||||||
* the loop.
|
|
||||||
*/
|
|
||||||
if (tmp_sta == assoc_sta)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (tmp_sta->mld_assoc_link_id !=
|
|
||||||
assoc_sta->mld_assoc_link_id ||
|
|
||||||
tmp_sta->aid != assoc_sta->aid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!disassoc)
|
|
||||||
hostapd_deauth_sta(tmp_hapd, tmp_sta,
|
|
||||||
mgmt);
|
|
||||||
else
|
|
||||||
hostapd_disassoc_sta(tmp_hapd, tmp_sta,
|
|
||||||
mgmt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6439,38 +6419,33 @@ static void hostapd_ml_handle_assoc_cb(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta, bool ok)
|
struct sta_info *sta, bool ok)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
unsigned int i, link_id;
|
struct hostapd_data *tmp_hapd;
|
||||||
|
|
||||||
if (!hostapd_is_mld_ap(hapd))
|
if (!hostapd_is_mld_ap(hapd))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for_each_mld_link(tmp_hapd, hapd) {
|
||||||
struct mld_link_info *link = &sta->mld_info.links[link_id];
|
struct mld_link_info *link;
|
||||||
|
struct sta_info *tmp_sta;
|
||||||
|
|
||||||
|
if (tmp_hapd == hapd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
link = &sta->mld_info.links[tmp_hapd->mld_link_id];
|
||||||
if (!link->valid)
|
if (!link->valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
||||||
struct sta_info *tmp_sta;
|
tmp_sta = tmp_sta->next) {
|
||||||
struct hostapd_data *tmp_hapd =
|
if (tmp_sta == sta ||
|
||||||
hapd->iface->interfaces->iface[i]->bss[0];
|
tmp_sta->mld_assoc_link_id !=
|
||||||
|
sta->mld_assoc_link_id ||
|
||||||
if (!hostapd_is_ml_partner(tmp_hapd, hapd))
|
tmp_sta->aid != sta->aid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (tmp_sta = tmp_hapd->sta_list; tmp_sta;
|
ieee80211_ml_link_sta_assoc_cb(tmp_hapd, tmp_sta, link,
|
||||||
tmp_sta = tmp_sta->next) {
|
ok);
|
||||||
if (tmp_sta == sta ||
|
break;
|
||||||
tmp_sta->mld_assoc_link_id !=
|
|
||||||
sta->mld_assoc_link_id ||
|
|
||||||
tmp_sta->aid != sta->aid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ieee80211_ml_link_sta_assoc_cb(tmp_hapd,
|
|
||||||
tmp_sta, link,
|
|
||||||
ok);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
|
@ -1030,7 +1030,7 @@ const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd,
|
||||||
static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta)
|
struct sta_info *sta)
|
||||||
{
|
{
|
||||||
u8 i, link_id;
|
u8 link_id;
|
||||||
struct mld_info *info = &sta->mld_info;
|
struct mld_info *info = &sta->mld_info;
|
||||||
|
|
||||||
if (!ap_sta_is_mld(hapd, sta)) {
|
if (!ap_sta_is_mld(hapd, sta)) {
|
||||||
|
@ -1050,31 +1050,18 @@ static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
struct hostapd_data *other_hapd;
|
struct hostapd_data *other_hapd;
|
||||||
|
|
||||||
if (!info->links[link_id].valid)
|
if (!info->links[link_id].valid || link_id == hapd->mld_link_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < hapd->iface->interfaces->count; i++) {
|
other_hapd = hostapd_mld_get_link_bss(hapd, link_id);
|
||||||
other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
|
if (!other_hapd) {
|
||||||
|
|
||||||
if (hapd == other_hapd)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (hostapd_is_ml_partner(hapd, other_hapd) &&
|
|
||||||
link_id == other_hapd->mld_link_id)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == hapd->iface->interfaces->count &&
|
|
||||||
link_id != hapd->mld_link_id) {
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: Invalid link ID=%u",
|
wpa_printf(MSG_DEBUG, "MLD: Invalid link ID=%u",
|
||||||
link_id);
|
link_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < hapd->iface->interfaces->count)
|
os_memcpy(info->links[link_id].local_addr, other_hapd->own_addr,
|
||||||
os_memcpy(info->links[link_id].local_addr,
|
ETH_ALEN);
|
||||||
other_hapd->own_addr,
|
|
||||||
ETH_ALEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1537,7 +1537,7 @@ static int hostapd_wpa_auth_get_ml_rsn_info(void *ctx,
|
||||||
struct wpa_auth_ml_rsn_info *info)
|
struct wpa_auth_ml_rsn_info *info)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
unsigned int i, j;
|
unsigned int i;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get RSN info CB: n_mld_links=%u",
|
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get RSN info CB: n_mld_links=%u",
|
||||||
info->n_mld_links);
|
info->n_mld_links);
|
||||||
|
@ -1547,26 +1547,30 @@ static int hostapd_wpa_auth_get_ml_rsn_info(void *ctx,
|
||||||
|
|
||||||
for (i = 0; i < info->n_mld_links; i++) {
|
for (i = 0; i < info->n_mld_links; i++) {
|
||||||
unsigned int link_id = info->links[i].link_id;
|
unsigned int link_id = info->links[i].link_id;
|
||||||
|
struct hostapd_data *bss;
|
||||||
|
bool link_bss_found = false;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"WPA_AUTH: MLD: Get link RSN CB: link_id=%u",
|
"WPA_AUTH: MLD: Get link RSN CB: link_id=%u",
|
||||||
link_id);
|
link_id);
|
||||||
|
|
||||||
for (j = 0; j < hapd->iface->interfaces->count; j++) {
|
if (hapd->mld_link_id == link_id) {
|
||||||
struct hostapd_iface *iface =
|
wpa_auth_ml_get_rsn_info(hapd->wpa_auth,
|
||||||
hapd->iface->interfaces->iface[j];
|
&info->links[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hostapd_is_ml_partner(hapd, iface->bss[0]) ||
|
for_each_mld_link(bss, hapd) {
|
||||||
link_id != iface->bss[0]->mld_link_id ||
|
if (bss == hapd || bss->mld_link_id != link_id)
|
||||||
!iface->bss[0]->wpa_auth)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wpa_auth_ml_get_rsn_info(iface->bss[0]->wpa_auth,
|
wpa_auth_ml_get_rsn_info(bss->wpa_auth,
|
||||||
&info->links[i]);
|
&info->links[i]);
|
||||||
|
link_bss_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == hapd->iface->interfaces->count)
|
if (!link_bss_found)
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"WPA_AUTH: MLD: link=%u not found", link_id);
|
"WPA_AUTH: MLD: link=%u not found", link_id);
|
||||||
}
|
}
|
||||||
|
@ -1579,7 +1583,7 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||||
struct wpa_auth_ml_key_info *info)
|
struct wpa_auth_ml_key_info *info)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
unsigned int i, j;
|
unsigned int i;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get key info CB: n_mld_links=%u",
|
wpa_printf(MSG_DEBUG, "WPA_AUTH: MLD: Get key info CB: n_mld_links=%u",
|
||||||
info->n_mld_links);
|
info->n_mld_links);
|
||||||
|
@ -1588,29 +1592,35 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < info->n_mld_links; i++) {
|
for (i = 0; i < info->n_mld_links; i++) {
|
||||||
|
struct hostapd_data *bss;
|
||||||
u8 link_id = info->links[i].link_id;
|
u8 link_id = info->links[i].link_id;
|
||||||
|
bool link_bss_found = false;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"WPA_AUTH: MLD: Get link info CB: link_id=%u",
|
"WPA_AUTH: MLD: Get link info CB: link_id=%u",
|
||||||
link_id);
|
link_id);
|
||||||
|
|
||||||
for (j = 0; j < hapd->iface->interfaces->count; j++) {
|
if (hapd->mld_link_id == link_id) {
|
||||||
struct hostapd_iface *iface =
|
wpa_auth_ml_get_key_info(hapd->wpa_auth,
|
||||||
hapd->iface->interfaces->iface[j];
|
|
||||||
|
|
||||||
if (!hostapd_is_ml_partner(hapd, iface->bss[0]) ||
|
|
||||||
link_id != iface->bss[0]->mld_link_id ||
|
|
||||||
!iface->bss[0]->wpa_auth)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
wpa_auth_ml_get_key_info(iface->bss[0]->wpa_auth,
|
|
||||||
&info->links[i],
|
&info->links[i],
|
||||||
info->mgmt_frame_prot,
|
info->mgmt_frame_prot,
|
||||||
info->beacon_prot);
|
info->beacon_prot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_mld_link(bss, hapd) {
|
||||||
|
if (bss == hapd || bss->mld_link_id != link_id)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wpa_auth_ml_get_key_info(bss->wpa_auth,
|
||||||
|
&info->links[i],
|
||||||
|
info->mgmt_frame_prot,
|
||||||
|
info->beacon_prot);
|
||||||
|
link_bss_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == hapd->iface->interfaces->count)
|
if (!link_bss_found)
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"WPA_AUTH: MLD: link=%u not found", link_id);
|
"WPA_AUTH: MLD: link=%u not found", link_id);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue