]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Consider regulatory limitation when filling WMM element
authorHaim Dreyfuss <haim.dreyfuss@intel.com>
Wed, 3 Apr 2019 16:07:53 +0000 (19:07 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 28 May 2019 20:37:25 +0000 (23:37 +0300)
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>
src/ap/hostapd.h
src/ap/wmm.c

index f573717d1ef7503e471f5932902b6562dd6133c5..52b5dbc6912108717c412150e23a31e04e977a8f 100644 (file)
@@ -551,6 +551,9 @@ struct hostapd_iface {
 #ifdef CONFIG_AIRTIME_POLICY
        unsigned int airtime_quantum;
 #endif /* CONFIG_AIRTIME_POLICY */
+
+       /* Previous WMM element information */
+       struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
 };
 
 /* hostapd.c */
index 8054c5d2f2433777f1c86caf638f8da3c7be88d0..dc734933738d3a83b83bac04b329783ef06bad38 100644 (file)
 #include "ap_drv_ops.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)
 {
@@ -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
  * Response frames.
@@ -48,10 +111,12 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
        u8 *pos = eid;
        struct wmm_parameter_element *wmm =
                (struct wmm_parameter_element *) (pos + 2);
+       struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 };
        int e;
 
        if (!hapd->conf->wmm_enabled)
                return eid;
+       wmm_calc_regulatory_limit(hapd, wmmp);
        eid[0] = WLAN_EID_VENDOR_SPECIFIC;
        wmm->oui[0] = 0x00;
        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 */
        for (e = 0; e < 4; e++) {
                struct wmm_ac_parameter *ac = &wmm->ac[e];
-               struct hostapd_wmm_ac_params *acp =
-                       &hapd->iconf->wmm_ac_params[e];
+               struct hostapd_wmm_ac_params *acp = &wmmp[e];
 
                ac->aci_aifsn = wmm_aci_aifsn(acp->aifs,
                                              acp->admission_control_mandatory,