mesh: Make BSSBasicRateSet configurable
authorMasashi Honma <masashi.honma@gmail.com>
Mon, 1 Sep 2014 04:23:38 +0000 (00:23 -0400)
committerJouni Malinen <j@w1.fi>
Sun, 16 Nov 2014 17:43:11 +0000 (19:43 +0200)
STAs that have different BSSBasicRateSet cannot connect to each other
as per IEEE 802.11s-2011 9.6.0c1:

"A mesh STA shall not establish a mesh peering with a mesh STA using a
different BSSBasicRateSet."

Make BSSBasicRateSet configurable to improve interoperability with other
stations.

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/mesh.c

index 9e261ba..c948c5f 100644 (file)
@@ -1617,7 +1617,31 @@ static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data,
 }
 
 
+static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data,
+                                            struct wpa_ssid *ssid, int line,
+                                            const char *value)
+{
+       int *rates = wpa_config_parse_int_array(value);
+
+       if (rates == NULL) {
+               wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'",
+                          line, value);
+               return -1;
+       }
+       if (rates[0] == 0) {
+               os_free(rates);
+               rates = NULL;
+       }
+
+       os_free(ssid->mesh_basic_rates);
+       ssid->mesh_basic_rates = rates;
+
+       return 0;
+}
+
+
 #ifndef NO_CONFIG_WRITE
+
 static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
                                            struct wpa_ssid *ssid)
 {
@@ -1643,6 +1667,13 @@ static char * wpa_config_write_mesh_ht_mode(const struct parse_data *data,
        return val ? os_strdup(val) : NULL;
 }
 
+
+static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
+                                               struct wpa_ssid *ssid)
+{
+       return wpa_config_write_freqs(data, ssid->mesh_basic_rates);
+}
+
 #endif /* NO_CONFIG_WRITE */
 
 #endif /* CONFIG_MESH */
@@ -1819,6 +1850,7 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(frequency, 0, 65000) },
 #ifdef CONFIG_MESH
        { FUNC(mesh_ht_mode) },
+       { FUNC(mesh_basic_rates) },
 #endif /* CONFIG_MESH */
        { INT(wpa_ptk_rekey) },
        { STR(bgscan) },
@@ -2049,6 +2081,9 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
 #ifdef CONFIG_HT_OVERRIDES
        os_free(ssid->ht_mcs);
 #endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_MESH
+       os_free(ssid->mesh_basic_rates);
+#endif /* CONFIG_MESH */
        while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
                                    list))) {
                dl_list_del(&psk->list);
index 852140f..6c55cfc 100644 (file)
@@ -743,7 +743,10 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT(update_identifier);
 #endif /* CONFIG_HS20 */
        write_int(f, "mac_addr", ssid->mac_addr, -1);
+#ifdef CONFIG_MESH
        STR(mesh_ht_mode);
+       STR(mesh_basic_rates);
+#endif /* CONFIG_MESH */
 
 #undef STR
 #undef INT
index 85d976c..b1c2fd8 100644 (file)
@@ -413,6 +413,12 @@ struct wpa_ssid {
         */
        int mesh_ht_mode;
 
+       /**
+        * mesh_basic_rates - BSS Basic rate set for mesh network
+        *
+        */
+       int *mesh_basic_rates;
+
        int ht40;
 
        int vht;
index 3ebf058..1ff8dac 100644 (file)
@@ -122,6 +122,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
        int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
        static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
        size_t len;
+       int rate_len;
 
        if (!wpa_s->conf->user_mpm) {
                /* not much for us to do here */
@@ -186,19 +187,34 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
                goto out_free;
        }
 
-       /*
-        * XXX: Hack! This is so an MPM which correctly sets the ERP mandatory
-        * rates as BSSBasicRateSet doesn't reject us. We could add a new
-        * hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but this is way easier. This
-        * also makes our BSSBasicRateSet advertised in Beacon frames match the
-        * one in peering frames, sigh.
-        */
-       if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
-               conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
-               if (!conf->basic_rates)
+       if (ssid->mesh_basic_rates == NULL) {
+               /*
+                * XXX: Hack! This is so an MPM which correctly sets the ERP
+                * mandatory rates as BSSBasicRateSet doesn't reject us. We
+                * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
+                * this is way easier. This also makes our BSSBasicRateSet
+                * advertised in beacons match the one in peering frames, sigh.
+                */
+               if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+                       conf->basic_rates = os_malloc(sizeof(basic_rates_erp));
+                       if (!conf->basic_rates)
+                               goto out_free;
+                       os_memcpy(conf->basic_rates, basic_rates_erp,
+                                 sizeof(basic_rates_erp));
+               }
+       } else {
+               rate_len = 0;
+               while (1) {
+                       if (ssid->mesh_basic_rates[rate_len] < 1)
+                               break;
+                       rate_len++;
+               }
+               conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
+               if (conf->basic_rates == NULL)
                        goto out_free;
-               os_memcpy(conf->basic_rates, basic_rates_erp,
-                         sizeof(basic_rates_erp));
+               os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
+                         rate_len * sizeof(int));
+               conf->basic_rates[rate_len] = -1;
        }
 
        if (hostapd_setup_interface(ifmsh)) {