[RFC 2/4] nl80211: Allow disabling ht and vht rates before scanning.

greearb at candelatech.com greearb
Thu Oct 15 10:08:03 PDT 2015


From: Ben Greear <greearb at candelatech.com>

This is similar to the work for legacy rates.  The idea is to
notify the kernel of the available rates before the probe
request is sent.  This can let the driver/firmware do
a better job of building a proper probe request.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 src/drivers/driver_nl80211.c | 102 +++++++++++++++++++++++++++++++++----------
 src/drivers/driver_nl80211.h |   4 ++
 2 files changed, 84 insertions(+), 22 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 7b774a7..3610b53 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -190,7 +190,8 @@ static int nl80211_set_legacy_rates(struct i802_bss *bss,
 				    struct wpa_driver_nl80211_data *drv,
 				    int ifindex, int b_disabled,
 				    unsigned int cfg_legacy_mask,
-				    int is_advert_mask);
+				    int is_advert_mask,
+				    int disable_ht, int disable_vht);
 
 static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
 			      int reset_mode);
@@ -2343,8 +2344,8 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
 	if (drv->if_indices != drv->default_if_indices)
 		os_free(drv->if_indices);
 
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF, 0);
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF, 1);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF, 0, 0, 0);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF, 1, 0, 0);
 
 	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
 			       IF_OPER_UP);
@@ -2878,8 +2879,10 @@ static int wpa_driver_nl80211_authenticate(
 	int count = 0;
 	int is_retry;
 
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0);
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0,
+				 bss->tx_disable_ht, bss->tx_disable_vht);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1,
+				 bss->adv_disable_ht, bss->adv_disable_vht);
 
 	is_retry = drv->retry_auth;
 	drv->retry_auth = 0;
@@ -4103,8 +4106,10 @@ int nl80211_create_iface(struct i802_bss *bss, struct wpa_driver_nl80211_data *d
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s created for P2P - disable 11b rates",
 			   ifname);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->tx_legacy_rates, 0);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->adv_legacy_rates, 1);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->tx_legacy_rates, 0,
+					 bss->tx_disable_ht, bss->tx_disable_vht);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->adv_legacy_rates, 1,
+					 bss->adv_disable_ht, bss->adv_disable_vht);
 	}
 
 	return ret;
@@ -4796,8 +4801,10 @@ static int wpa_driver_nl80211_associate(
 	int ret = -1;
 	struct nl_msg *msg;
 
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0);
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0,
+				 bss->tx_disable_ht, bss->tx_disable_vht);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1,
+				 bss->adv_disable_ht, bss->adv_disable_vht);
 
 	if (params->mode == IEEE80211_MODE_AP)
 		return wpa_driver_nl80211_ap(drv, params);
@@ -4976,14 +4983,18 @@ done:
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s mode change to P2P - disable 11b rates",
 			   bss->ifname);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->tx_legacy_rates, 0);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->adv_legacy_rates, 1);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->tx_legacy_rates, 0,
+					 bss->tx_disable_ht, bss->tx_disable_vht);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->adv_legacy_rates, 1,
+					 bss->adv_disable_ht, bss->adv_disable_vht);
 	} else {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates",
 			   bss->ifname);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0);
-		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->tx_legacy_rates, 0,
+					  bss->tx_disable_ht, bss->tx_disable_vht);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->adv_legacy_rates, 1,
+					 bss->adv_disable_ht, bss->adv_disable_vht);
 	}
 
 	if (is_ap_interface(nlmode)) {
@@ -6366,11 +6377,14 @@ static int nl80211_set_legacy_rates(struct i802_bss *bss,
 				    struct wpa_driver_nl80211_data *drv,
 				    int ifindex, int b_disabled,
 				    unsigned int legacy_rates,
-				    int is_advert_mask)
+				    int is_advert_mask,
+				    int disable_ht, int disable_vht)
 {
 	struct nl_msg *msg;
 	struct nlattr *bands, *band;
 	int ret;
+	uint8_t ht_mcs[77];
+	struct nl80211_txrate_vht txrate_vht = {};
 
 	wpa_printf(MSG_DEBUG,
 		   "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s cfg-legacy-mask: 0x%x is-advert: %d)",
@@ -6462,18 +6476,27 @@ static int nl80211_set_legacy_rates(struct i802_bss *bss,
 			if (nla_put(msg, NL80211_TXRATE_LEGACY, i, rates))
 				goto fail;
 		}
-	}/* if we might need to disable some rates */
+	}/* if we might need to disable some legacy rates */
+
+	if (disable_ht) {
+		if (nla_put(msg, NL80211_TXRATE_HT, 0, ht_mcs))
+			goto fail;
+	}
+	if (disable_vht) {
+		if (nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht), &txrate_vht))
+			goto fail;
+	}
 
 	nla_nest_end(msg, band);
 
+	band = nla_nest_start(msg, NL80211_BAND_5GHZ);
+	if (!band)
+		goto fail;
+
 	if (legacy_rates & (1<<31)) {
 		unsigned char rates[8];
 		int i = 0;
 
-		band = nla_nest_start(msg, NL80211_BAND_5GHZ);
-		if (!band)
-			goto fail;
-
 		if (legacy_rates & 0x10) { // 6Mbps
 			rates[i] = 12;
 			i++;
@@ -6507,11 +6530,29 @@ static int nl80211_set_legacy_rates(struct i802_bss *bss,
 			i++;
 		}
 
+		/* If we have no rates at all, then set one minimum rate so that
+		 * the kernel doesn't reject the setting entirely.
+		 */
+		if ((i == 0) && disable_ht && disable_vht) {
+			rates[i] = 12;
+			i++;
+		}
+
+		wpa_printf(MSG_DEBUG, "nl80211: Set TX Rates 5Ghz, i: %d", i);
 		if (nla_put(msg, NL80211_TXRATE_LEGACY, i, rates))
 			goto fail;
+	}
 
-		nla_nest_end(msg, band);
+	if (disable_ht) {
+		if (nla_put(msg, NL80211_TXRATE_HT, 0, ht_mcs))
+			goto fail;
 	}
+	if (disable_vht) {
+		if (nla_put(msg, NL80211_TXRATE_VHT, sizeof(txrate_vht), &txrate_vht))
+			goto fail;
+	}
+
+	nla_nest_end(msg, band);
 
 	nla_nest_end(msg, bands);
 
@@ -6531,8 +6572,10 @@ fail:
 int wpa_driver_nl80211_set_legacy_rates(void *priv)
 {
 	struct i802_bss *bss = priv;
-	nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->tx_legacy_rates, 0);
-	return nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->adv_legacy_rates, 1);
+	nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->tx_legacy_rates, 0,
+				 bss->tx_disable_ht, bss->tx_disable_vht);
+	return nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->adv_legacy_rates, 1,
+					bss->adv_disable_ht, bss->adv_disable_vht);
 }
 
 static int wpa_driver_nl80211_deinit_ap(void *priv)
@@ -6725,6 +6768,21 @@ static int nl80211_set_param(void *priv, const char *param)
 		bss->adv_legacy_rates |= (1<<31); /* so we know user actually configured something */
 	}
 
+	if (os_strstr(param, "tx_disable_ht=1")) {
+		bss->tx_disable_ht = 1;
+	}
+
+	if (os_strstr(param, "tx_disable_vht=1")) {
+		bss->tx_disable_vht = 1;
+	}
+	if (os_strstr(param, "adv_disable_ht=1")) {
+		bss->adv_disable_ht = 1;
+	}
+
+	if (os_strstr(param, "adv_disable_vht=1")) {
+		bss->adv_disable_vht = 1;
+	}
+
 	return 0;
 }
 
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index a21f0cd..8eaaeb1 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -64,6 +64,10 @@ struct i802_bss {
 	unsigned int wdev_id_set:1;
 	unsigned int added_if:1;
 	unsigned int static_ap:1;
+	unsigned int tx_disable_ht:1; /* Disable Using HT rates? */
+	unsigned int tx_disable_vht:1; /* Disable Using VHT Rates? */
+	unsigned int adv_disable_ht:1; /* Disable Advertised HT rates? */
+	unsigned int adv_disable_vht:1; /* Disable Advertised VHT Rates? */
 
 	u8 addr[ETH_ALEN];
 
-- 
1.9.3




More information about the Hostap mailing list