[12/25] OCV: Add function to derive Tx parameters to a specific STA

Message ID 20180806194643.1328-13-Mathy.Vanhoef@cs.kuleuven.be
State New
Headers show
Series
  • Add support for Operating Channel Validation (OCV)
Related show

Commit Message

Mathy Vanhoef Aug. 6, 2018, 7:46 p.m.
Use the information elements that were present in the association
request to derive the maximum bandwidth the AP will use to transmit
frames to a specific STA. By using this approach, we don't need to query
the kernel for this information, and avoid having to add a driver API to
query the kernel for this information.

Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
---
 src/ap/wpa_auth.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
 src/ap/wpa_auth.h |  7 +++++
 2 files changed, 81 insertions(+)

Comments

Mathy Vanhoef Aug. 8, 2018, 12:34 p.m. | #1
On Mon,  6 Aug 2018 15:46:30 -0400
Maty Vanhoef <Mathy.Vanhoef@cs.kuleuven.be> wrote:

> +int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
> +			  int ap_seg1_idx, int *bandwidth, int *seg1_idx)
> +{
> +	struct sta_info *sta;
> +
> +	sta = wpa_get_sta(sm->wpa_auth, sm->addr);
> +	if (sta == NULL) {
> +		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "Failed to get "
> +				"STA info to validate received OCI in EAPOL-Key 2/4");

Found a typo: the debug output string here should not include " in
EAPOL-Key 2/4".

Patch

diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index ea966474f..23ca2c1a9 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -2633,6 +2633,80 @@  u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
 
 #endif /* CONFIG_FILS */
 
+#ifdef CONFIG_OCV
+
+int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
+		      int ap_seg1_idx, int *bandwidth, int *seg1_idx)
+{
+	int ht_40mhz;
+	int vht_80p80;
+	int requested_bw;
+
+
+	ht_40mhz = 0;
+	if (sta->ht_capabilities)
+		ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
+			      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
+
+	vht_80p80 = 0;
+	if (sta->vht_operation) {
+		struct ieee80211_vht_operation *oper = sta->vht_operation;
+
+		/**
+		 * If a VHT Operation element was present, use it to determine the
+		 * supported channel bandwidth.
+		 */
+		if (oper->vht_op_info_chwidth == 0)
+			requested_bw = ht_40mhz ? 40 : 20;
+		else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0)
+			requested_bw = 80;
+		else {
+			requested_bw = 160;
+			vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx != 0 &&
+				    abs((int)oper->vht_op_info_chan_center_freq_seg0_idx -
+					(int)oper->vht_op_info_chan_center_freq_seg1_idx) > 16;
+		}
+	} else if (sta->vht_capabilities) {
+		struct ieee80211_vht_capabilities *capab = sta->vht_capabilities;
+
+		/**
+		 * If only the VHT Capabilities element is present (e.g. for normal
+		 * clients), use it to determine the supported channel bandwidth.
+		 */
+		int vht_chanwidth = capab->vht_capabilities_info & VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+		vht_80p80 = capab->vht_capabilities_info & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+
+		/** TODO: Also take into account Extended NSS BW Support field */
+		requested_bw = vht_chanwidth ? 160 : 80;
+	} else {
+		requested_bw = ht_40mhz ? 40 : 20;
+	}
+
+	*bandwidth = requested_bw < ap_max_chanwidth ? requested_bw : ap_max_chanwidth;
+
+	*seg1_idx = 0;
+	if (ap_seg1_idx && vht_80p80)
+		*seg1_idx = ap_seg1_idx;
+
+	return 0;
+}
+
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+			  int ap_seg1_idx, int *bandwidth, int *seg1_idx)
+{
+	struct sta_info *sta;
+
+	sta = wpa_get_sta(sm->wpa_auth, sm->addr);
+	if (sta == NULL) {
+		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "Failed to get "
+				"STA info to validate received OCI in EAPOL-Key 2/4");
+		return -1;
+	}
+
+	return get_tx_parameters(sta, ap_max_chanwidth, ap_seg1_idx, bandwidth, seg1_idx);
+}
+
+#endif /* CONFIG_OCV */
 
 SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
 {
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 2762044ff..edd7beebe 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -457,6 +457,13 @@  const u8 *  wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
 int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
 				  size_t ies_len);
 
+#ifdef CONFIG_OCV
+int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
+		      int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+			  int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+#endif /* CONFIG_OCV */
+
 int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
 		       u8 *buf, size_t len);
 void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,