[PATCH] hostapd: Set Basic/Supported rates per BSS

Shay Bar shay.bar at celeno.com
Sun Jun 28 11:57:16 EDT 2020


In case of MBSS, there is a need to be able to
control the Basic/Supported rates per BSS.

This patch adds that support.

Signed-off-by: Shay Bar <shay.bar at celeno.com>
---
 hostapd/config_file.c  |   4 +-
 src/ap/ap_config.c     |   4 +-
 src/ap/ap_config.h     |   5 +-
 src/ap/beacon.c        |   2 +-
 src/ap/ctrl_iface_ap.c |   6 +--
 src/ap/hostapd.c       | 109 +++++++++++++++++++++++++++++++++++------
 src/ap/hostapd.h       |   9 ++--
 src/ap/hw_features.c   |  79 -----------------------------
 src/ap/hw_features.h   |   8 ---
 src/ap/ieee802_11.c    |  20 ++++----
 src/ap/sta_info.c      |   6 +--
 wpa_supplicant/ap.c    |   4 +-
 wpa_supplicant/mesh.c  |  14 +++---
 13 files changed, 131 insertions(+), 139 deletions(-)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 1c72e5578..0be63941b 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3280,13 +3280,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                }
                bss->send_probe_response = val;
        } else if (os_strcmp(buf, "supported_rates") == 0) {
-               if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
+               if (hostapd_parse_intlist(&bss->supported_rates, pos)) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
                                   line);
                        return 1;
                }
        } else if (os_strcmp(buf, "basic_rates") == 0) {
-               if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
+               if (hostapd_parse_intlist(&bss->basic_rates, pos)) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
                                   line);
                        return 1;
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 35a32a130..9b5ff82f4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -794,6 +794,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->radius_das_shared_secret);
        hostapd_config_free_vlan(conf);
        os_free(conf->time_zone);
+       os_free(conf->supported_rates);
+       os_free(conf->basic_rates);

 #ifdef CONFIG_IEEE80211R_AP
        {
@@ -965,8 +967,6 @@ void hostapd_config_free(struct hostapd_config *conf)
        for (i = 0; i < conf->num_bss; i++)
                hostapd_config_free_bss(conf->bss[i]);
        os_free(conf->bss);
-       os_free(conf->supported_rates);
-       os_free(conf->basic_rates);
        os_free(conf->acs_ch_list.range);
        os_free(conf->acs_freq_list.range);
        os_free(conf->driver_params);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index cffa636cc..41ea47f26 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -322,6 +322,9 @@ struct hostapd_bss_config {

        struct hostapd_ssid ssid;

+       int *supported_rates;
+       int *basic_rates;
+
        char *eap_req_id_text; /* optional displayable message sent with
                                * EAP Request-Identity */
        size_t eap_req_id_text_len;
@@ -921,8 +924,6 @@ struct hostapd_config {
                SHORT_PREAMBLE = 1
        } preamble;

-       int *supported_rates;
-       int *basic_rates;
        unsigned int beacon_rate;
        enum beacon_rate_type rate_type;

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 22e672c8d..63521d543 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1361,7 +1361,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
        params->proberesp_len = resp_len;
        params->dtim_period = hapd->conf->dtim_period;
        params->beacon_int = hapd->iconf->beacon_int;
-       params->basic_rates = hapd->iface->basic_rates;
+       params->basic_rates = hapd->basic_rates;
        params->beacon_rate = hapd->iconf->beacon_rate;
        params->rate_type = hapd->iconf->rate_type;
        params->ssid = hapd->conf->ssid.ssid;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index ef53a8254..bebb75784 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -812,16 +812,16 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
                                                   mode->mcs_set);
        }

-       if (iface->current_rates && iface->num_rates) {
+       if (hapd->current_rates && hapd->num_rates) {
                ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
                if (os_snprintf_error(buflen - len, ret))
                        return len;
                len += ret;

-               for (j = 0; j < iface->num_rates; j++) {
+               for (j = 0; j < hapd->num_rates; j++) {
                        ret = os_snprintf(buf + len, buflen - len, "%s%02x",
                                          j > 0 ? " " : "",
-                                         iface->current_rates[j].rate / 5);
+                                         hapd->current_rates[j].rate / 5);
                        if (os_snprintf_error(buflen - len, ret))
                                return len;
                        len += ret;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f9af038be..793666451 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -360,6 +360,10 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
        hapd->probereq_cb = NULL;
        hapd->num_probereq_cb = 0;

+       os_free(hapd->current_rates);
+       hapd->current_rates = NULL;
+       os_free(hapd->basic_rates);
+       hapd->basic_rates = NULL;
 #ifdef CONFIG_P2P
        wpabuf_free(hapd->p2p_beacon_ie);
        hapd->p2p_beacon_ie = NULL;
@@ -503,10 +507,6 @@ static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
        hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
        iface->hw_features = NULL;
        iface->current_mode = NULL;
-       os_free(iface->current_rates);
-       iface->current_rates = NULL;
-       os_free(iface->basic_rates);
-       iface->basic_rates = NULL;
        ap_list_deinit(iface);
        sta_track_deinit(iface);
        airtime_policy_update_deinit(iface);
@@ -1085,6 +1085,85 @@ static int db_table_create_radius_attributes(sqlite3 *db)

 #endif /* CONFIG_NO_RADIUS */

+static int hostapd_prepare_rates(struct hostapd_data *hapd,
+                                struct hostapd_hw_modes *mode)
+{
+       struct hostapd_bss_config *conf = hapd->conf;
+       int i, num_basic_rates = 0;
+       int basic_rates_a[] = { 60, 120, 240, -1 };
+       int basic_rates_b[] = { 10, 20, -1 };
+       int basic_rates_g[] = { 10, 20, 55, 110, -1 };
+       int *basic_rates;
+
+       if (conf->basic_rates)
+               basic_rates = conf->basic_rates;
+       else switch (mode->mode) {
+       case HOSTAPD_MODE_IEEE80211A:
+               basic_rates = basic_rates_a;
+               break;
+       case HOSTAPD_MODE_IEEE80211B:
+               basic_rates = basic_rates_b;
+               break;
+       case HOSTAPD_MODE_IEEE80211G:
+               basic_rates = basic_rates_g;
+               break;
+       case HOSTAPD_MODE_IEEE80211AD:
+               return 0; /* No basic rates for 11ad */
+       default:
+               return -1;
+       }
+
+       i = 0;
+       while (basic_rates[i] >= 0)
+               i++;
+       if (i)
+               i++; /* -1 termination */
+       os_free(hapd->basic_rates);
+       hapd->basic_rates = os_malloc(i * sizeof(int));
+       if (hapd->basic_rates)
+               os_memcpy(hapd->basic_rates, basic_rates, i * sizeof(int));
+
+       os_free(hapd->current_rates);
+       hapd->num_rates = 0;
+
+       hapd->current_rates =
+               os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
+       if (!hapd->current_rates) {
+               wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
+                          "table.");
+               return -1;
+       }
+
+       for (i = 0; i < mode->num_rates; i++) {
+               struct hostapd_rate_data *rate;
+
+               if (conf->supported_rates &&
+                   !hostapd_rate_found(conf->supported_rates,
+                                       mode->rates[i]))
+                       continue;
+
+               rate = &hapd->current_rates[hapd->num_rates];
+               rate->rate = mode->rates[i];
+               if (hostapd_rate_found(basic_rates, rate->rate)) {
+                       rate->flags |= HOSTAPD_RATE_BASIC;
+                       num_basic_rates++;
+               }
+               wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
+                          hapd->num_rates, rate->rate, rate->flags);
+               hapd->num_rates++;
+       }
+
+       if ((hapd->num_rates == 0 || num_basic_rates == 0) &&
+           (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) {
+               wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
+                          "rate sets (%d,%d).",
+                          hapd->num_rates, num_basic_rates);
+               return -1;
+       }
+
+       return 0;
+}
+

 /**
  * hostapd_setup_bss - Per-BSS setup (initialization)
@@ -1109,6 +1188,17 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
        wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
                   __func__, hapd, conf->iface, first);

+       if (hapd->iface->current_mode) {
+               if (hostapd_prepare_rates(hapd, hapd->iface->current_mode)) {
+                       wpa_printf(MSG_ERROR, "Failed to prepare rates "
+                                  "table.");
+                       hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+                                      HOSTAPD_LEVEL_WARNING,
+                                      "Failed to prepare rates table.");
+                       return -1;
+               }
+       }
+
 #ifdef EAP_SERVER_TNC
        if (conf->tnc && tncs_global_init() < 0) {
                wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
@@ -2037,17 +2127,6 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
                }
        }

-       if (iface->current_mode) {
-               if (hostapd_prepare_rates(iface, iface->current_mode)) {
-                       wpa_printf(MSG_ERROR, "Failed to prepare rates "
-                                  "table.");
-                       hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-                                      HOSTAPD_LEVEL_WARNING,
-                                      "Failed to prepare rates table.");
-                       goto fail;
-               }
-       }
-
        if (hapd->iconf->rts_threshold >= -1 &&
            hostapd_set_rts(hapd, hapd->iconf->rts_threshold) &&
            hapd->iconf->rts_threshold >= -1) {
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 609c84b22..b62256487 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -184,6 +184,10 @@ struct hostapd_data {
        void *msg_ctx; /* ctx for wpa_msg() calls */
        void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */

+       int num_rates;
+       struct hostapd_rate_data *current_rates;
+       int *basic_rates;
+
        struct radius_client_data *radius;
        u64 acct_session_id;
        struct radius_das_data *radius_das;
@@ -507,11 +511,6 @@ struct hostapd_iface {
        struct hostapd_hw_modes *hw_features;
        int num_hw_features;
        struct hostapd_hw_modes *current_mode;
-       /* Rates that are currently used (i.e., filtered copy of
-        * current_mode->channels */
-       int num_rates;
-       struct hostapd_rate_data *current_rates;
-       int *basic_rates;
        int freq;

        u16 hw_flags;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index f6e69030d..9992a0478 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -145,85 +145,6 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
 }


-int hostapd_prepare_rates(struct hostapd_iface *iface,
-                         struct hostapd_hw_modes *mode)
-{
-       int i, num_basic_rates = 0;
-       int basic_rates_a[] = { 60, 120, 240, -1 };
-       int basic_rates_b[] = { 10, 20, -1 };
-       int basic_rates_g[] = { 10, 20, 55, 110, -1 };
-       int *basic_rates;
-
-       if (iface->conf->basic_rates)
-               basic_rates = iface->conf->basic_rates;
-       else switch (mode->mode) {
-       case HOSTAPD_MODE_IEEE80211A:
-               basic_rates = basic_rates_a;
-               break;
-       case HOSTAPD_MODE_IEEE80211B:
-               basic_rates = basic_rates_b;
-               break;
-       case HOSTAPD_MODE_IEEE80211G:
-               basic_rates = basic_rates_g;
-               break;
-       case HOSTAPD_MODE_IEEE80211AD:
-               return 0; /* No basic rates for 11ad */
-       default:
-               return -1;
-       }
-
-       i = 0;
-       while (basic_rates[i] >= 0)
-               i++;
-       if (i)
-               i++; /* -1 termination */
-       os_free(iface->basic_rates);
-       iface->basic_rates = os_malloc(i * sizeof(int));
-       if (iface->basic_rates)
-               os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
-
-       os_free(iface->current_rates);
-       iface->num_rates = 0;
-
-       iface->current_rates =
-               os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
-       if (!iface->current_rates) {
-               wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
-                          "table.");
-               return -1;
-       }
-
-       for (i = 0; i < mode->num_rates; i++) {
-               struct hostapd_rate_data *rate;
-
-               if (iface->conf->supported_rates &&
-                   !hostapd_rate_found(iface->conf->supported_rates,
-                                       mode->rates[i]))
-                       continue;
-
-               rate = &iface->current_rates[iface->num_rates];
-               rate->rate = mode->rates[i];
-               if (hostapd_rate_found(basic_rates, rate->rate)) {
-                       rate->flags |= HOSTAPD_RATE_BASIC;
-                       num_basic_rates++;
-               }
-               wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
-                          iface->num_rates, rate->rate, rate->flags);
-               iface->num_rates++;
-       }
-
-       if ((iface->num_rates == 0 || num_basic_rates == 0) &&
-           (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
-               wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
-                          "rate sets (%d,%d).",
-                          iface->num_rates, num_basic_rates);
-               return -1;
-       }
-
-       return 0;
-}
-
-
 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
 {
        int pri_freq, sec_freq;
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index dd24f95b2..fda9a242f 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -22,8 +22,6 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
 int hostapd_check_ht_capab(struct hostapd_iface *iface);
 int hostapd_check_edmg_capab(struct hostapd_iface *iface);
-int hostapd_prepare_rates(struct hostapd_iface *iface,
-                         struct hostapd_hw_modes *mode);
 void hostapd_stop_setup_timers(struct hostapd_iface *iface);
 int hostapd_hw_skip_mode(struct hostapd_iface *iface,
                         struct hostapd_hw_modes *mode);
@@ -69,12 +67,6 @@ static inline int hostapd_check_edmg_capab(struct hostapd_iface *iface)
        return 0;
 }

-static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
-                                       struct hostapd_hw_modes *mode)
-{
-       return 0;
-}
-
 static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface)
 {
 }
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index f1f37027b..e1c32cc68 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -90,11 +90,11 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
        int i, num, count;
        int h2e_required;

-       if (hapd->iface->current_rates == NULL)
+       if (hapd->current_rates == NULL)
                return eid;

        *pos++ = WLAN_EID_SUPP_RATES;
-       num = hapd->iface->num_rates;
+       num = hapd->num_rates;
        if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
                num++;
        if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
@@ -112,11 +112,11 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
        }

        *pos++ = num;
-       for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
+       for (i = 0, count = 0; i < hapd->num_rates && count < num;
             i++) {
                count++;
-               *pos = hapd->iface->current_rates[i].rate / 5;
-               if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
+               *pos = hapd->current_rates[i].rate / 5;
+               if (hapd->current_rates[i].flags & HOSTAPD_RATE_BASIC)
                        *pos |= 0x80;
                pos++;
        }
@@ -146,10 +146,10 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
        int i, num, count;
        int h2e_required;

-       if (hapd->iface->current_rates == NULL)
+       if (hapd->current_rates == NULL)
                return eid;

-       num = hapd->iface->num_rates;
+       num = hapd->num_rates;
        if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
                num++;
        if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
@@ -166,13 +166,13 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)

        *pos++ = WLAN_EID_EXT_SUPP_RATES;
        *pos++ = num;
-       for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
+       for (i = 0, count = 0; i < hapd->num_rates && count < num + 8;
             i++) {
                count++;
                if (count <= 8)
                        continue; /* already in SuppRates IE */
-               *pos = hapd->iface->current_rates[i].rate / 5;
-               if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
+               *pos = hapd->current_rates[i].rate / 5;
+               if (hapd->current_rates[i].flags & HOSTAPD_RATE_BASIC)
                        *pos |= 0x80;
                pos++;
        }
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 67b5e9885..fd6392aca 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -699,11 +699,11 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
        }

        for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) {
-               if (!hapd->iface->basic_rates)
+               if (!hapd->basic_rates)
                        break;
-               if (hapd->iface->basic_rates[i] < 0)
+               if (hapd->basic_rates[i] < 0)
                        break;
-               sta->supported_rates[i] = hapd->iface->basic_rates[i] / 5;
+               sta->supported_rates[i] = hapd->basic_rates[i] / 5;
        }
        sta->supported_rates_len = i;

diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 624168205..65c6d96a6 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -320,7 +320,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                        list[2] = 240;
                        list[3] = -1;
                }
-               conf->basic_rates = list;
+               bss->basic_rates = list;

                list = os_malloc(9 * sizeof(int));
                if (list) {
@@ -334,7 +334,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
                        list[7] = 540;
                        list[8] = -1;
                }
-               conf->supported_rates = list;
+               bss->supported_rates = list;
        }

 #ifdef CONFIG_IEEE80211AX
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index c085466b1..acdce610c 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -224,7 +224,7 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)

        params->ies = ifmsh->mconf->rsn_ie;
        params->ie_len = ifmsh->mconf->rsn_ie_len;
-       params->basic_rates = ifmsh->basic_rates;
+       params->basic_rates = ifmsh->bss[0]->basic_rates;
        params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
        params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;

@@ -367,9 +367,9 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
                 * advertised in beacons match the one in peering frames, sigh.
                 */
                if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
-                       conf->basic_rates = os_memdup(basic_rates_erp,
+                       bss->conf->basic_rates = os_memdup(basic_rates_erp,
                                                      sizeof(basic_rates_erp));
-                       if (!conf->basic_rates)
+                       if (!bss->conf->basic_rates)
                                goto out_free;
                }
        } else {
@@ -379,12 +379,12 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
                                break;
                        rate_len++;
                }
-               conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
-               if (conf->basic_rates == NULL)
+               bss->conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
+               if (bss->conf->basic_rates == NULL)
                        goto out_free;
-               os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
+               os_memcpy(bss->conf->basic_rates, ssid->mesh_basic_rates,
                          rate_len * sizeof(int));
-               conf->basic_rates[rate_len] = -1;
+               bss->conf->basic_rates[rate_len] = -1;
        }

        if (wpa_drv_init_mesh(wpa_s)) {
--
2.17.1

________________________________
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Nothing contained herein shall be deemed as a representation, warranty or a commitment by Celeno. No warranties are expressed or implied, including, but not limited to, any implied warranties of non-infringement, merchantability and fitness for a particular purpose.
________________________________




More information about the Hostap mailing list