From 6cc8e24fc8e8cca92a782c0c8d32058867fd4f1a Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran Date: Wed, 29 Nov 2023 22:26:55 +0530 Subject: [PATCH] hostapd: Modify EVENT_LOW_ACK event callback nl80211 event callback sends driver_data struct to hostapd event handler but for MLD stations, we might need to loop all the partner bss to find the link to which the station is connected to. For this, we need i802_bss struct context to be passed instead driver_data context. Modify this by sending the required struct context to the event callback. Also, to support sending disassoc to the station overriding the hostapd configured value for certain driver related handlings, make change to add the reason based on the number of packets is set to '0xFFFF' when EVENT_LOW_ACK is sent from driver. Signed-off-by: Manish Dharanenthiran --- src/ap/drv_callbacks.c | 23 ++++++++++++++++++----- src/ap/hostapd.h | 3 ++- src/drivers/driver_nl80211_event.c | 7 ++++--- wpa_supplicant/events.c | 3 ++- 4 files changed, 26 insertions(+), 10 deletions(-) --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -783,18 +783,75 @@ void hostapd_notif_disassoc(struct hosta } -void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) +static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface, + const u8 *src, struct sta_info **sta_ret) { - struct sta_info *sta = ap_get_sta(hapd, addr); + struct sta_info *sta; + struct hostapd_data *hapd, *p_hapd, *tmp_hapd; + unsigned int j; + + if (sta_ret) + *sta_ret = NULL; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, src); + if (sta && sta->flags & WLAN_STA_ASSOC) { + if (sta_ret) + *sta_ret = sta; + return hapd; + } +#ifdef CONFIG_IEEE80211BE + else if (hapd->conf->mld_ap) { + for_each_partner_bss(p_hapd, hapd) { + if (hapd == p_hapd) + continue; + + sta = ap_get_sta(p_hapd, src); + if (sta && sta->flags & WLAN_STA_ASSOC && sta->wpa_sm) { + if (sta_ret) + *sta_ret = sta; + return p_hapd; + } + } + } +#endif /* CONFIG_IEEE80211BE */ + } + + return NULL; +} + + +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr, u32 num_packets) +{ + struct hostapd_data *tmp_hapd; + struct sta_info *sta = ap_get_sta(hapd, addr), *tmp_sta = NULL; + u32 reason = WLAN_REASON_DISASSOC_LOW_ACK; + + if (!sta && hapd->conf->mld_ap) { + /* Check in link BSSes for MLD */ + tmp_hapd = hostapd_find_by_sta(hapd->iface, addr, &tmp_sta); + if (tmp_hapd) { + hapd = tmp_hapd; + sta = tmp_sta; + } else { + wpa_printf(MSG_DEBUG, + "No partner hapd found for the STA %pM - fall back to receivied context\n", + addr); + } + } - if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer) + if (!sta || (!hapd->conf->disassoc_low_ack && num_packets != 0xFFFF) || + sta->agreed_to_steer) return; + if (num_packets == 0xFFFF) + reason = WLAN_REASON_UNSPECIFIED; + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disconnected due to excessive missing ACKs"); - hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); - ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); + hostapd_drv_sta_disassoc(hapd, addr, reason); + ap_sta_disassociate(hapd, sta, reason); } @@ -1649,44 +1706,6 @@ static struct hostapd_data * hostapd_fin return NULL; } -static struct hostapd_data * hostapd_find_by_sta(struct hostapd_iface *iface, - const u8 *src, struct sta_info **sta_ret) -{ - struct sta_info *sta; - struct hostapd_data *hapd, *p_hapd, *tmp_hapd; - unsigned int j; - - if (sta_ret) - *sta_ret = NULL; - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - sta = ap_get_sta(hapd, src); - if (sta && sta->flags & WLAN_STA_ASSOC) { - if (sta_ret) - *sta_ret = sta; - return hapd; - } -#ifdef CONFIG_IEEE80211BE - else if (hapd->conf->mld_ap) { - for_each_partner_bss(p_hapd, hapd) { - if (p_hapd == hapd) - continue; - - sta = ap_get_sta(p_hapd, src); - if (sta && sta->flags & WLAN_STA_ASSOC && sta->wpa_sm) { - if (sta_ret) - *sta_ret = sta; - return p_hapd; - } - } - } -#endif /* CONFIG_IEEE80211BE */ - } - - return NULL; -} - - static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, const u8 *data, size_t data_len, enum frame_encryption encrypted, @@ -2303,7 +2322,8 @@ void hostapd_wpa_event(void *ctx, enum w case EVENT_STATION_LOW_ACK: if (!data) break; - hostapd_event_sta_low_ack(hapd, data->low_ack.addr); + hostapd_event_sta_low_ack(hapd, data->low_ack.addr, + data->low_ack.num_packets); break; case EVENT_AUTH: hostapd_notif_auth(hapd, &data->auth); --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -810,7 +810,8 @@ void hostapd_notify_assoc_fils_finish(st int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *ie, size_t ielen, int reassoc); void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); -void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr); +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr, + const u32 num_packets); void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, const u8 *addr, int reason_code); int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2067,7 +2067,7 @@ process_scan_event: } -static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, +static void nl80211_cqm_event(struct i802_bss *bss, struct nlattr *tb[]) { static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { @@ -2083,6 +2083,7 @@ static void nl80211_cqm_event(struct wpa struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; enum nl80211_cqm_rssi_threshold_event event; union wpa_event_data ed; + struct wpa_driver_nl80211_data *drv = bss->drv; int res; if (tb[NL80211_ATTR_CQM] == NULL || @@ -2104,7 +2105,7 @@ static void nl80211_cqm_event(struct wpa wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR " (num_packets %u)", MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets); - wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed); + wpa_supplicant_event(bss->ctx, EVENT_STATION_LOW_ACK, &ed); return; } @@ -4248,7 +4249,7 @@ static void do_process_drv_event(struct mlme_event_remain_on_channel(drv, 1, tb); break; case NL80211_CMD_NOTIFY_CQM: - nl80211_cqm_event(drv, tb); + nl80211_cqm_event(bss, tb); break; case NL80211_CMD_REG_CHANGE: case NL80211_CMD_WIPHY_REG_CHANGE: --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -6163,7 +6163,8 @@ void supplicant_event(void *ctx, enum wp #ifdef CONFIG_AP if (wpa_s->ap_iface && data) hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0], - data->low_ack.addr); + data->low_ack.addr, + data->low_ack.num_packets); #endif /* CONFIG_AP */ #ifdef CONFIG_TDLS if (data)