diff mbox series

hostapd: Set Basic/Supported rates per BSS

Message ID 20200628155716.28880-1-shay.bar@celeno.com
State New
Headers show
Series hostapd: Set Basic/Supported rates per BSS | expand

Commit Message

Shay Bar June 28, 2020, 3:57 p.m. UTC
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@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(-)

--
2.17.1
diff mbox series

Patch

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)) {