HE: Add support for MCS_FixedRate

This commit implements MCS_FixedRate params support for both DUT and
testbed roles.

Cache last set nss in sigma_dut and use the same value while sending
fixed rate in MCS_FixedRate implementation.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
diff --git a/sta.c b/sta.c
index 99a6474..d5745ee 100644
--- a/sta.c
+++ b/sta.c
@@ -3393,11 +3393,14 @@
 				 const char *val)
 {
 	char buf[60];
+	int sta_nss;
 
 	if (strcmp(val, "1SS") == 0 || strcmp(val, "1") == 0) {
 		snprintf(buf, sizeof(buf), "iwpriv %s nss 1", intf);
+		sta_nss = 1;
 	} else if (strcmp(val, "2SS") == 0 || strcmp(val, "2") == 0) {
 		snprintf(buf, sizeof(buf), "iwpriv %s nss 2", intf);
+		sta_nss = 2;
 	} else {
 		sigma_dut_print(dut, DUT_MSG_ERROR,
 				"SP_STREAM value not supported");
@@ -3410,6 +3413,8 @@
 		return -1;
 	}
 
+	dut->sta_nss = sta_nss;
+
 	return 0;
 }
 
@@ -5668,6 +5673,7 @@
 			sigma_dut_print(dut, DUT_MSG_ERROR,
 					"iwpriv %s nss 3 failed", intf);
 		}
+		dut->sta_nss = 3;
 
 		snprintf(buf, sizeof(buf), "iwpriv %s shortgi 1", intf);
 		if (system(buf) != 0) {
@@ -5941,6 +5947,7 @@
 				sigma_dut_print(dut, DUT_MSG_ERROR,
 						"iwpriv %s nss 2 failed", intf);
 			}
+			dut->sta_nss = 2;
 
 #ifdef NL80211_SUPPORT
 			/* Set HE_MCS to 0-11 */
@@ -6404,6 +6411,50 @@
 		}
 	}
 
+	val = get_param(cmd, "MCS_FixedRate");
+	if (val) {
+#ifdef NL80211_SUPPORT
+		int mcs, ratecode = 0;
+		enum he_mcs_config mcs_config;
+		int ret;
+
+		ratecode = (0x07 & dut->sta_nss) << 5;
+		mcs = atoi(val);
+		/* Add the MCS to the ratecode */
+		if (mcs >= 0 && mcs <= 11) {
+			ratecode += mcs;
+			if (dut->device_type == STA_testbed &&
+			    mcs > 7 && mcs <= 11) {
+				if (mcs <= 9)
+					mcs_config = HE_80_MCS0_9;
+				else
+					mcs_config = HE_80_MCS0_11;
+				ret = sta_set_he_mcs(dut, intf, mcs_config);
+				if (ret) {
+					sigma_dut_print(dut, DUT_MSG_ERROR,
+							"MCS_FixedRate: mcs setting failed, mcs:%d, mcs_config %d, ret:%d",
+							mcs, mcs_config, ret);
+				}
+			}
+			snprintf(buf, sizeof(buf),
+				 "iwpriv %s set_11ax_rate 0x%03x",
+				 intf, ratecode);
+			if (system(buf) != 0) {
+				sigma_dut_print(dut, DUT_MSG_ERROR,
+						"MCS_FixedRate: iwpriv setting of 11ax rates 0x%03x failed",
+						ratecode);
+			}
+		} else {
+			sigma_dut_print(dut, DUT_MSG_ERROR,
+					"MCS_FixedRate: HE MCS %d not supported",
+					mcs);
+		}
+#else /* NL80211_SUPPORT */
+		sigma_dut_print(dut, DUT_MSG_ERROR,
+				"MCS_FixedRate cannot be changed without NL80211_SUPPORT defined");
+#endif /* NL80211_SUPPORT */
+	}
+
 	val = get_param(cmd, "opt_md_notif_ie");
 	if (val) {
 		char *result = NULL;
@@ -6512,6 +6563,7 @@
 			sigma_dut_print(dut, DUT_MSG_ERROR,
 					"iwpriv nss failed");
 		}
+		dut->sta_nss = nss;
 
 		result = strtok_r(NULL, ";", &saveptr);
 		if (result == NULL) {
@@ -9031,6 +9083,7 @@
 					intf, nss);
 			goto failed;
 		}
+		dut->sta_nss = nss;
 
 		/* Add the MCS to the ratecode */
 		if (mcs >= 0 && mcs <= 11) {