--- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1359,6 +1359,11 @@ static int hostapd_ctrl_iface_set(struct } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 || os_strncmp(cmd, "wmm_ac_", 7) == 0) { hapd->parameter_set_count++; + /* Incrementing MU-EDCA Parameter Set Update Count*/ + hapd->iface->conf->he_mu_edca.he_qos_info = + (hapd->iface->conf->he_mu_edca.he_qos_info & 0xf0) | + ((hapd->iface->conf->he_mu_edca.he_qos_info + 1) & + 0xf); if (ieee802_11_update_beacons(hapd->iface)) wpa_printf(MSG_DEBUG, "Failed to update beacons with WMM parameters"); --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1937,6 +1937,39 @@ static void hostapd_event_wds_sta_interf ifname, MAC2STR(addr)); } +static void hostapd_event_update_muedca_params(struct hostapd_data *hapd, + struct update_muedca *params) +{ + int i; + u8 updated_count; + + /* Update current MU-EDCA parameters */ + for (i = 0; i < 3; i++) { + hapd->iface->conf->he_mu_edca.he_mu_ac_be_param[i] = + params->he_mu_ac_be_param[i]; + hapd->iface->conf->he_mu_edca.he_mu_ac_bk_param[i] = + params->he_mu_ac_bk_param[i]; + hapd->iface->conf->he_mu_edca.he_mu_ac_vo_param[i] = + params->he_mu_ac_vo_param[i]; + hapd->iface->conf->he_mu_edca.he_mu_ac_vi_param[i] = + params->he_mu_ac_vi_param[i]; + } + + /* Increment Parameter Set Update Count for MU-EDCA and WME EDCA only + * if any STA is connected + */ + if (hapd->num_sta) { + updated_count = (hapd->iface->conf->he_mu_edca.he_qos_info + 1) & 0xf; + hapd->iface->conf->he_mu_edca.he_qos_info &= 0xf0; + hapd->iface->conf->he_mu_edca.he_qos_info |= updated_count; + hapd->parameter_set_count++; + } + + /* Update beacon with updated MU-EDCA parameters */ + if (ieee802_11_update_beacons(hapd->iface)) + wpa_printf(MSG_DEBUG, + "Failed to update beacons with MU-EDCA parameters"); +} #ifdef CONFIG_OWE static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, @@ -2276,6 +2309,9 @@ void hostapd_wpa_event(void *ctx, enum w hostapd_cleanup_cca_params(hapd); break; #endif /* CONFIG_IEEE80211AX */ + case EVENT_UPDATE_MUEDCA_PARAMS: + hostapd_event_update_muedca_params(hapd, &data->update_muedca); + break; default: wpa_printf(MSG_DEBUG, "Unknown event %d", event); break; --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -2774,6 +2774,9 @@ hostapd_alloc_bss_data(struct hostapd_if dl_list_init(&hapd->sae_commit_queue); #endif /* CONFIG_SAE */ + if (conf && conf->ieee80211ax && hapd->iface) + hapd->parameter_set_count = hapd->iface->conf->he_mu_edca.he_qos_info & 0xf; + return hapd; } @@ -4026,6 +4029,10 @@ static int hostapd_fill_csa_settings(str hapd->cs_count = settings->cs_count; hapd->cs_block_tx = settings->block_tx; + /* reset MU-EDCA and WME EDCA parameter set count */ + hapd->iface->conf->he_mu_edca.he_qos_info &= 0xfff0; + hapd->parameter_set_count = 0; + ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa); if (ret) { free_beacon_data(&settings->beacon_after); --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -18,6 +18,7 @@ #include "sta_info.h" #include "ieee802_11.h" #include "dfs.h" +#include "wmm.h" static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) { @@ -290,9 +291,16 @@ u8 * hostapd_eid_he_operation(struct hos u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid) { struct ieee80211_he_mu_edca_parameter_set *edca; + struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM]; u8 *pos; size_t i; + /* Updating WME Parameter Set Count to avoid mismatch */ + os_memset(wmmp, 0, sizeof(wmmp)); + + if (hapd->conf->wmm_enabled) + wmm_calc_regulatory_limit(hapd, wmmp); + pos = (u8 *) &hapd->iface->conf->he_mu_edca; for (i = 0; i < sizeof(*edca); i++) { if (pos[i]) --- a/src/ap/wmm.c +++ b/src/ap/wmm.c @@ -68,8 +68,8 @@ wmm_set_regulatory_limit(const struct ho /* * Calculate WMM regulatory limit if any. */ -static void wmm_calc_regulatory_limit(struct hostapd_data *hapd, - struct hostapd_wmm_ac_params *acp) +void wmm_calc_regulatory_limit(struct hostapd_data *hapd, + struct hostapd_wmm_ac_params *acp) { struct hostapd_hw_modes *mode = hapd->iface->current_mode; int c; @@ -98,6 +98,10 @@ static void wmm_calc_regulatory_limit(st os_memcpy(hapd->iface->prev_wmm, acp, sizeof(hapd->iconf->wmm_ac_params)); hapd->parameter_set_count++; + /* Incrementing MU-EDCA Parameter Set Update Count*/ + hapd->iface->conf->he_mu_edca.he_qos_info = + (hapd->iface->conf->he_mu_edca.he_qos_info & 0xf0) | + ((hapd->iface->conf->he_mu_edca.he_qos_info + 1) & 0xf); } } --- a/src/ap/wmm.h +++ b/src/ap/wmm.h @@ -13,6 +13,8 @@ struct ieee80211_mgmt; struct wmm_tspec_element; +void wmm_calc_regulatory_limit(struct hostapd_data *hapd, + struct hostapd_wmm_ac_params *acp); u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len); --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -5694,6 +5694,16 @@ enum wpa_event_type { EVENT_LINK_CH_SWITCH_STARTED, /** + * EVENT_UPDATE_MUEDCA_PARAMS - Updated MU-EDCA parameters received + * + * this event is emitted when updated MU-EDCA parameters from driver + * are received. updated MU-EDCA parameters need to be updated in + * beacon. + */ + EVENT_UPDATE_MUEDCA_PARAMS, + + + /** * EVENT_TID_LINK_MAP - MLD event to set TID-to-link mapping * * This event is used by the driver to indicate the received TID-to-link @@ -6631,6 +6641,16 @@ union wpa_event_data { struct pasn_auth pasn_auth; /** + * struct update_muedca - Data for EVENT_UPDATE_MU_EDCA_PARAMS + */ + struct update_muedca { + u8 he_mu_ac_be_param[3]; + u8 he_mu_ac_bk_param[3]; + u8 he_mu_ac_vi_param[3]; + u8 he_mu_ac_vo_param[3]; + } update_muedca; + + /** * struct port_authorized - Data for EVENT_PORT_AUTHORIZED */ struct port_authorized { --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -98,6 +98,7 @@ const char * event_to_string(enum wpa_ev E2S(PASN_AUTH); E2S(LINK_CH_SWITCH); E2S(LINK_CH_SWITCH_STARTED); + E2S(UPDATE_MUEDCA_PARAMS); E2S(TID_LINK_MAP); E2S(LINK_RECONFIG); } --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -184,6 +184,7 @@ static const char * nl80211_command_to_s C2S(NL80211_CMD_ADD_LINK_STA) C2S(NL80211_CMD_MODIFY_LINK_STA) C2S(NL80211_CMD_REMOVE_LINK_STA) + C2S(NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS) C2S(NL80211_CMD_SET_HW_TIMESTAMP) C2S(__NL80211_CMD_AFTER_LAST) } @@ -3533,6 +3534,35 @@ static void nl80211_sta_opmode_change_ev wpa_supplicant_event(drv->ctx, EVENT_STATION_OPMODE_CHANGED, &ed); } +static void nl80211_update_muedca_params_event(struct wpa_driver_nl80211_data *drv, + struct nlattr **tb) +{ + struct host_update_muedca { + u8 mu_qos_info; + u8 ac_be[3]; + u8 ac_bk[3]; + u8 ac_vi[3]; + u8 ac_vo[3]; + }; + + struct host_update_muedca *rx_muedca_params; + union wpa_event_data ed; + int i; + + if (!tb[NL80211_ATTR_HE_MUEDCA_PARAMS]) + return; + + rx_muedca_params = nla_data(tb[NL80211_ATTR_HE_MUEDCA_PARAMS]); + + for (i = 0; i< 3; i++) { + ed.update_muedca.he_mu_ac_be_param[i] = rx_muedca_params->ac_be[i]; + ed.update_muedca.he_mu_ac_bk_param[i] = rx_muedca_params->ac_bk[i]; + ed.update_muedca.he_mu_ac_vi_param[i] = rx_muedca_params->ac_vi[i]; + ed.update_muedca.he_mu_ac_vo_param[i] = rx_muedca_params->ac_vo[i]; + } + + wpa_supplicant_event(drv->ctx, EVENT_UPDATE_MUEDCA_PARAMS, &ed); +} static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, struct nlattr **tb) @@ -3974,6 +4004,9 @@ static void do_process_drv_event(struct nl80211_color_change_announcement_completed(drv); break; #endif /* CONFIG_IEEE80211AX */ + case NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: + nl80211_update_muedca_params_event(drv, tb); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -1309,6 +1309,11 @@ * The number of peers that HW timestamping can be enabled for concurrently * is indicated by %NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS. * + * @NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS: Updated MU-EDCA parameters from driver. + * This event is used to update MU-EDCA parameters in Beacon frame, which + * were indicated by driver and now need to be reflected in + * Beacon frame. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1562,6 +1567,7 @@ enum nl80211_commands { NL80211_CMD_SET_HW_TIMESTAMP, + NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS, /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2781,6 +2787,9 @@ enum nl80211_commands { * the incoming frame RX timestamp. * @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent * (re)associations. + * @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the + * NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command. + * * * @NL80211_ATTR_PUNCT_BITMAP: (u32) Preamble puncturing bitmap, lowest * bit corresponds to the lowest 20 MHz channel. Each bit set to 1 @@ -3341,6 +3350,7 @@ enum nl80211_attrs { NL80211_ATTR_EMA_RNR_ELEMS, + NL80211_ATTR_HE_MUEDCA_PARAMS, /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST,