]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Configure Beacon frame TX rate if driver advertises support
authorPurushottam Kushwaha <pkushwah@qti.qualcomm.com>
Thu, 24 Nov 2016 15:09:47 +0000 (20:39 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 25 Nov 2016 22:36:27 +0000 (00:36 +0200)
If the driver advertises support for setting Beacon frame data rate,
allow the user to configure this rate as part of starting the AP. Only
one Beacon frame TX rate is allowed.

Drivers advertising such support should set corresponding flag via the
NL80211_ATTR_EXT_FEATURES attribute.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211_capa.c

index 1cd9f3959a0f8f1570547a7cf9793b16c6c00944..4f7069bf28c89d0e91230b74c773a6bbf9fb4613 100644 (file)
@@ -3517,6 +3517,101 @@ static int nl80211_set_mesh_config(void *priv,
 #endif /* CONFIG_MESH */
 
 
+static int nl80211_put_beacon_rate(struct nl_msg *msg, const u64 flags,
+                                  struct wpa_driver_ap_params *params)
+{
+       struct nlattr *bands, *band;
+       struct nl80211_txrate_vht vht_rate;
+
+       if (!params->freq ||
+           (params->beacon_rate == 0 &&
+            params->rate_type == BEACON_RATE_LEGACY))
+               return 0;
+
+       bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
+       if (!bands)
+               return -1;
+
+       switch (params->freq->mode) {
+       case HOSTAPD_MODE_IEEE80211B:
+       case HOSTAPD_MODE_IEEE80211G:
+               band = nla_nest_start(msg, NL80211_BAND_2GHZ);
+               break;
+       case HOSTAPD_MODE_IEEE80211A:
+               band = nla_nest_start(msg, NL80211_BAND_5GHZ);
+               break;
+       case HOSTAPD_MODE_IEEE80211AD:
+               band = nla_nest_start(msg, NL80211_BAND_60GHZ);
+               break;
+       default:
+               return 0;
+       }
+
+       if (!band)
+               return -1;
+
+       os_memset(&vht_rate, 0, sizeof(vht_rate));
+
+       switch (params->rate_type) {
+       case BEACON_RATE_LEGACY:
+               if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY)) {
+                       wpa_printf(MSG_INFO,
+                                  "nl80211: Driver does not support setting Beacon frame rate (legacy)");
+                       return -1;
+               }
+
+               if (nla_put_u8(msg, NL80211_TXRATE_LEGACY,
+                              (u8) params->beacon_rate / 5) ||
+                   nla_put(msg, NL80211_TXRATE_HT, 0, NULL) ||
+                   (params->freq->vht_enabled &&
+                    nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
+                            &vht_rate)))
+                       return -1;
+
+               wpa_printf(MSG_DEBUG, " * beacon_rate = legacy:%u (* 100 kbps)",
+                          params->beacon_rate);
+               break;
+       case BEACON_RATE_HT:
+               if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_HT)) {
+                       wpa_printf(MSG_INFO,
+                                  "nl80211: Driver does not support setting Beacon frame rate (HT)");
+                       return -1;
+               }
+               if (nla_put(msg, NL80211_TXRATE_LEGACY, 0, NULL) ||
+                   nla_put_u8(msg, NL80211_TXRATE_HT, params->beacon_rate) ||
+                   (params->freq->vht_enabled &&
+                    nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
+                            &vht_rate)))
+                       return -1;
+               wpa_printf(MSG_DEBUG, " * beacon_rate = HT-MCS %u",
+                          params->beacon_rate);
+               break;
+       case BEACON_RATE_VHT:
+               if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_VHT)) {
+                       wpa_printf(MSG_INFO,
+                                  "nl80211: Driver does not support setting Beacon frame rate (VHT)");
+                       return -1;
+               }
+               vht_rate.mcs[0] = BIT(params->beacon_rate);
+               if (nla_put(msg, NL80211_TXRATE_LEGACY, 0, NULL))
+                       return -1;
+               if (nla_put(msg, NL80211_TXRATE_HT, 0, NULL))
+                       return -1;
+               if (nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
+                           &vht_rate))
+                       return -1;
+               wpa_printf(MSG_DEBUG, " * beacon_rate = VHT-MCS %u",
+                          params->beacon_rate);
+               break;
+       }
+
+       nla_nest_end(msg, band);
+       nla_nest_end(msg, bands);
+
+       return 0;
+}
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
                                     struct wpa_driver_ap_params *params)
 {
@@ -3547,6 +3642,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
                    params->tail, params->tail_len);
        wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", bss->ifindex);
        wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
+       wpa_printf(MSG_DEBUG, "nl80211: beacon_rate=%u", params->beacon_rate);
+       wpa_printf(MSG_DEBUG, "nl80211: rate_type=%d", params->rate_type);
        wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
        wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
                          params->ssid, params->ssid_len);
@@ -3556,6 +3653,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
            nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
                    params->tail) ||
            nl80211_put_beacon_int(msg, params->beacon_int) ||
+           nl80211_put_beacon_rate(msg, drv->capa.flags, params) ||
            nl80211_put_dtim_period(msg, params->dtim_period) ||
            nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
                goto fail;
index 2507a43eabbb861317b6988daf869dc49b3d2490..85706efe415ca97c52816346241094f6f4d5f174 100644 (file)
@@ -365,6 +365,18 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 
        if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_FILS_STA))
                capa->flags |= WPA_DRIVER_FLAGS_SUPPORT_FILS;
+
+       if (ext_feature_isset(ext_features, len,
+                             NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
+               capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY;
+
+       if (ext_feature_isset(ext_features, len,
+                             NL80211_EXT_FEATURE_BEACON_RATE_HT))
+               capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_HT;
+
+       if (ext_feature_isset(ext_features, len,
+                             NL80211_EXT_FEATURE_BEACON_RATE_VHT))
+               capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_VHT;
 }