Browse Source

mac80211: parse VHT info in injected frames

Add VHT radiotap parsing support to ieee80211_parse_tx_radiotap().
That capability has been tested using a d-link dir-860l rev b1 running
OpenWrt trunk and mt76 driver

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Lorenzo Bianconi 9 năm trước cách đây
mục cha
commit
646e76bb5d

+ 13 - 0
Documentation/networking/mac80211-injection.txt

@@ -45,6 +45,19 @@ radiotap headers and used to control injection:
    number of retries when either IEEE80211_RADIOTAP_RATE or
    number of retries when either IEEE80211_RADIOTAP_RATE or
    IEEE80211_RADIOTAP_MCS was used
    IEEE80211_RADIOTAP_MCS was used
 
 
+ * IEEE80211_RADIOTAP_VHT
+
+   VHT mcs and number of streams used in the transmission (only for devices
+   without own rate control). Also other fields are parsed
+
+   flags field
+   IEEE80211_RADIOTAP_VHT_FLAG_SGI: use short guard interval
+
+   bandwidth field
+   1: send using 40MHz channel width
+   4: send using 80MHz channel width
+   11: send using 160MHz channel width
+
 The injection code can also skip all other currently defined radiotap fields
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
 facilitating replay of captured radiotap headers directly.
 
 

+ 31 - 0
net/mac80211/tx.c

@@ -1692,6 +1692,8 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
 	u8 rate_retries = 0;
 	u8 rate_retries = 0;
 	u16 rate_flags = 0;
 	u16 rate_flags = 0;
 	u8 mcs_known, mcs_flags;
 	u8 mcs_known, mcs_flags;
+	u16 vht_known;
+	u8 vht_mcs = 0, vht_nss = 0;
 	int i;
 	int i;
 
 
 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
 	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
@@ -1772,6 +1774,32 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
 				rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 				rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 			break;
 			break;
 
 
+		case IEEE80211_RADIOTAP_VHT:
+			vht_known = get_unaligned_le16(iterator.this_arg);
+			rate_found = true;
+
+			rate_flags = IEEE80211_TX_RC_VHT_MCS;
+			if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) &&
+			    (iterator.this_arg[2] &
+			     IEEE80211_RADIOTAP_VHT_FLAG_SGI))
+				rate_flags |= IEEE80211_TX_RC_SHORT_GI;
+			if (vht_known &
+			    IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) {
+				if (iterator.this_arg[3] == 1)
+					rate_flags |=
+						IEEE80211_TX_RC_40_MHZ_WIDTH;
+				else if (iterator.this_arg[3] == 4)
+					rate_flags |=
+						IEEE80211_TX_RC_80_MHZ_WIDTH;
+				else if (iterator.this_arg[3] == 11)
+					rate_flags |=
+						IEEE80211_TX_RC_160_MHZ_WIDTH;
+			}
+
+			vht_mcs = iterator.this_arg[4] >> 4;
+			vht_nss = iterator.this_arg[4] & 0xF;
+			break;
+
 		/*
 		/*
 		 * Please update the file
 		 * Please update the file
 		 * Documentation/networking/mac80211-injection.txt
 		 * Documentation/networking/mac80211-injection.txt
@@ -1797,6 +1825,9 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
 
 
 		if (rate_flags & IEEE80211_TX_RC_MCS) {
 		if (rate_flags & IEEE80211_TX_RC_MCS) {
 			info->control.rates[0].idx = rate;
 			info->control.rates[0].idx = rate;
+		} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
+			ieee80211_rate_set_vht(info->control.rates, vht_mcs,
+					       vht_nss);
 		} else {
 		} else {
 			for (i = 0; i < sband->n_bitrates; i++) {
 			for (i = 0; i < sband->n_bitrates; i++) {
 				if (rate * 5 != sband->bitrates[i].bitrate)
 				if (rate * 5 != sband->bitrates[i].bitrate)