[PATCH 1/3] nl80211: Allow disabling ht and vht rates before scanning.

greearb at candelatech.com greearb at candelatech.com
Fri Sep 18 17:06:33 EDT 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 | 75 +++++++++++++++++++++++++++++++++++---------
 src/drivers/driver_nl80211.h |  2 ++
 2 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 3fbf0f4..d0592c2 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -189,7 +189,8 @@ static int nl80211_set_channel(struct i802_bss *bss,
 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);
+				    unsigned int cfg_legacy_mask, int disable_ht,
+				    int disable_vht);
 
 static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
 			      int reset_mode);
@@ -2342,7 +2343,7 @@ 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);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF, 0, 0);
 
 	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
 			       IF_OPER_UP);
@@ -2876,7 +2877,8 @@ static int wpa_driver_nl80211_authenticate(
 	int count = 0;
 	int is_retry;
 
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates,
+				 bss->disable_ht, bss->disable_vht);
 
 	is_retry = drv->retry_auth;
 	drv->retry_auth = 0;
@@ -4100,7 +4102,8 @@ 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->legacy_rates);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->legacy_rates,
+					 bss->disable_ht, bss->disable_vht);
 	}
 
 	return ret;
@@ -4792,7 +4795,8 @@ static int wpa_driver_nl80211_associate(
 	int ret = -1;
 	struct nl_msg *msg;
 
-	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates,
+				 bss->disable_ht, bss->disable_vht);
 
 	if (params->mode == IEEE80211_MODE_AP)
 		return wpa_driver_nl80211_ap(drv, params);
@@ -4971,12 +4975,14 @@ 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->legacy_rates);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->legacy_rates,
+					 bss->disable_ht, bss->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->legacy_rates);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates,
+					 bss->disable_ht, bss->disable_vht);
 	}
 
 	if (is_ap_interface(nlmode)) {
@@ -6358,11 +6364,14 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
 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)
+				    unsigned int legacy_rates, 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)",
@@ -6450,18 +6459,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++;
@@ -6495,12 +6513,30 @@ 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);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -6519,7 +6555,8 @@ fail:
 int wpa_driver_nl80211_set_legacy_rates(void *priv)
 {
 	struct i802_bss *bss = priv;
-	return nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->legacy_rates);
+	return nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->legacy_rates,
+					bss->disable_ht, bss->disable_vht);
 }
 
 static int wpa_driver_nl80211_deinit_ap(void *priv)
@@ -6708,6 +6745,14 @@ static int nl80211_set_param(void *priv, const char *param)
 		bss->legacy_rates |= (1<<31); /* so we know user actually configured something */
 	}
 
+	if (os_strstr(param, "disable_ht=1")) {
+		bss->disable_ht = 1;
+	}
+
+	if (os_strstr(param, "disable_vht=1")) {
+		bss->disable_vht = 1;
+	}
+
 	return 0;
 }
 
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index bc64e5c..3eecc9a 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -64,6 +64,8 @@ struct i802_bss {
 	unsigned int wdev_id_set:1;
 	unsigned int added_if:1;
 	unsigned int static_ap:1;
+	unsigned int disable_ht:1; /* Disable HT rates? */
+	unsigned int disable_vht:1; /* Disable VHT Rates? */
 
 	u8 addr[ETH_ALEN];
 
-- 
1.9.3



More information about the HostAP mailing list