AP: Consider regulatory limitation when filling WMM element
In case the current channel has regulatory WMM limitations, take them into account when filling the WMM element. Also check if the new WMM element is different from the previous one and if so change the parameter_set_count to imply stations to look into it. Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
This commit is contained in:
parent
636c02c6e9
commit
de6aafaa63
2 changed files with 69 additions and 2 deletions
|
@ -551,6 +551,9 @@ struct hostapd_iface {
|
||||||
#ifdef CONFIG_AIRTIME_POLICY
|
#ifdef CONFIG_AIRTIME_POLICY
|
||||||
unsigned int airtime_quantum;
|
unsigned int airtime_quantum;
|
||||||
#endif /* CONFIG_AIRTIME_POLICY */
|
#endif /* CONFIG_AIRTIME_POLICY */
|
||||||
|
|
||||||
|
/* Previous WMM element information */
|
||||||
|
struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* hostapd.c */
|
/* hostapd.c */
|
||||||
|
|
68
src/ap/wmm.c
68
src/ap/wmm.c
|
@ -20,6 +20,13 @@
|
||||||
#include "ap_drv_ops.h"
|
#include "ap_drv_ops.h"
|
||||||
#include "wmm.h"
|
#include "wmm.h"
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
|
static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +46,62 @@ static inline u8 wmm_ecw(int ecwmin, int ecwmax)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
wmm_set_regulatory_limit(const struct hostapd_wmm_ac_params *wmm_conf,
|
||||||
|
struct hostapd_wmm_ac_params *wmm,
|
||||||
|
const struct hostapd_wmm_rule *wmm_reg)
|
||||||
|
{
|
||||||
|
int ac;
|
||||||
|
|
||||||
|
for (ac = 0; ac < WMM_AC_NUM; ac++) {
|
||||||
|
wmm[ac].cwmin = MAX(wmm_conf[ac].cwmin, wmm_reg[ac].min_cwmin);
|
||||||
|
wmm[ac].cwmax = MAX(wmm_conf[ac].cwmax, wmm_reg[ac].min_cwmax);
|
||||||
|
wmm[ac].aifs = MAX(wmm_conf[ac].aifs, wmm_reg[ac].min_aifs);
|
||||||
|
wmm[ac].txop_limit =
|
||||||
|
MIN(wmm_conf[ac].txop_limit, wmm_reg[ac].max_txop);
|
||||||
|
wmm[ac].admission_control_mandatory =
|
||||||
|
wmm_conf[ac].admission_control_mandatory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate WMM regulatory limit if any.
|
||||||
|
*/
|
||||||
|
static 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;
|
||||||
|
|
||||||
|
os_memcpy(acp, hapd->iconf->wmm_ac_params,
|
||||||
|
sizeof(hapd->iconf->wmm_ac_params));
|
||||||
|
|
||||||
|
for (c = 0; mode && c < mode->num_channels; c++) {
|
||||||
|
struct hostapd_channel_data *chan = &mode->channels[c];
|
||||||
|
|
||||||
|
if (chan->freq != hapd->iface->freq)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (chan->wmm_rules_valid)
|
||||||
|
wmm_set_regulatory_limit(hapd->iconf->wmm_ac_params,
|
||||||
|
acp, chan->wmm_rules);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we need to update set count. Since both were initialized to
|
||||||
|
* zero we can compare the whole array in one shot.
|
||||||
|
*/
|
||||||
|
if (os_memcmp(acp, hapd->iface->prev_wmm,
|
||||||
|
sizeof(hapd->iconf->wmm_ac_params)) != 0) {
|
||||||
|
os_memcpy(hapd->iface->prev_wmm, acp,
|
||||||
|
sizeof(hapd->iconf->wmm_ac_params));
|
||||||
|
hapd->parameter_set_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association
|
* Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association
|
||||||
* Response frames.
|
* Response frames.
|
||||||
|
@ -48,10 +111,12 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||||
u8 *pos = eid;
|
u8 *pos = eid;
|
||||||
struct wmm_parameter_element *wmm =
|
struct wmm_parameter_element *wmm =
|
||||||
(struct wmm_parameter_element *) (pos + 2);
|
(struct wmm_parameter_element *) (pos + 2);
|
||||||
|
struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 };
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
if (!hapd->conf->wmm_enabled)
|
if (!hapd->conf->wmm_enabled)
|
||||||
return eid;
|
return eid;
|
||||||
|
wmm_calc_regulatory_limit(hapd, wmmp);
|
||||||
eid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
eid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
wmm->oui[0] = 0x00;
|
wmm->oui[0] = 0x00;
|
||||||
wmm->oui[1] = 0x50;
|
wmm->oui[1] = 0x50;
|
||||||
|
@ -70,8 +135,7 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
|
||||||
/* fill in a parameter set record for each AC */
|
/* fill in a parameter set record for each AC */
|
||||||
for (e = 0; e < 4; e++) {
|
for (e = 0; e < 4; e++) {
|
||||||
struct wmm_ac_parameter *ac = &wmm->ac[e];
|
struct wmm_ac_parameter *ac = &wmm->ac[e];
|
||||||
struct hostapd_wmm_ac_params *acp =
|
struct hostapd_wmm_ac_params *acp = &wmmp[e];
|
||||||
&hapd->iconf->wmm_ac_params[e];
|
|
||||||
|
|
||||||
ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
|
ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
|
||||||
acp->admission_control_mandatory,
|
acp->admission_control_mandatory,
|
||||||
|
|
Loading…
Reference in a new issue