]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
OCV: Add function to derive Tx parameters to a specific STA
authorMathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
Mon, 6 Aug 2018 19:46:30 +0000 (15:46 -0400)
committerJouni Malinen <j@w1.fi>
Mon, 17 Dec 2018 13:42:19 +0000 (15:42 +0200)
Use the information elements that were present in the (Re)Association
Request frame 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 for that.

Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
src/ap/ieee802_11.h
src/ap/ieee802_11_shared.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c

index 3d93be299d28a2a997e9ac8b8977443fec241064..848deaf4154c8b5ac7c03a4e84ea71104a30e4fe 100644 (file)
@@ -168,4 +168,7 @@ int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
                               char **identity, char **radius_cui,
                               int is_probe_req);
 
+int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
+                     int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+
 #endif /* IEEE802_11_H */
index 49e9bf8cc7c9c0c86f1f8de1c5a97bdcd4eb2457..0e41a498449a5dbce7435459fd4dd3015239942f 100644 (file)
@@ -752,3 +752,71 @@ u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid)
 
        return pos;
 }
+
+
+#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 = 0;
+       int vht_80p80 = 0;
+       int requested_bw;
+
+       if (sta->ht_capabilities)
+               ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
+                             HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
+
+       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 {
+                       int diff;
+
+                       requested_bw = 160;
+                       diff = abs((int)
+                                  oper->vht_op_info_chan_center_freq_seg0_idx -
+                                  (int)
+                                  oper->vht_op_info_chan_center_freq_seg1_idx);
+                       vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx
+                               != 0 && diff > 16;
+               }
+       } else if (sta->vht_capabilities) {
+               struct ieee80211_vht_capabilities *capab;
+               int vht_chanwidth;
+
+               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.
+                */
+               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;
+}
+#endif /* CONFIG_OCV */
index b67fd6c44cc48954df7ed4735f2d11b75a652a41..f6e600f5004fffbb1a777dc6f6e05ebea4595737 100644 (file)
@@ -2637,6 +2637,21 @@ u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
 #endif /* CONFIG_FILS */
 
 
+#ifdef CONFIG_OCV
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+                         int ap_seg1_idx, int *bandwidth, int *seg1_idx)
+{
+       struct wpa_authenticator *wpa_auth = sm->wpa_auth;
+
+       if (!wpa_auth->cb->get_sta_tx_params)
+               return -1;
+       return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
+                                              ap_max_chanwidth, ap_seg1_idx,
+                                              bandwidth, seg1_idx);
+}
+#endif /* CONFIG_OCV */
+
+
 SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
 {
        struct wpa_authenticator *wpa_auth = sm->wpa_auth;
index 58a3b1e9a035f7d1a6518350a48e00ab614c729c..71928450209a22e639f60c3a77fc7434b7b4a775 100644 (file)
@@ -270,6 +270,9 @@ struct wpa_auth_callbacks {
        int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data,
                        size_t data_len);
        int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
+       int (*get_sta_tx_params)(void *ctx, const u8 *addr,
+                                int ap_max_chanwidth, int ap_seg1_idx,
+                                int *bandwidth, int *seg1_idx);
 #ifdef CONFIG_IEEE80211R_AP
        struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
        int (*set_vlan)(void *ctx, const u8 *sta_addr,
@@ -456,6 +459,9 @@ 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);
 
+int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
+                         int ap_seg1_idx, int *bandwidth, int *seg1_idx);
+
 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,
index 7cf22eb25e235031ea627a2fb80506a7e5cb4086..5ba88d1fe7280fd5eed0773c9425556802a38175 100644 (file)
@@ -27,6 +27,7 @@
 #include "tkip_countermeasures.h"
 #include "ap_drv_ops.h"
 #include "ap_config.h"
+#include "ieee802_11.h"
 #include "pmksa_cache_auth.h"
 #include "wpa_auth.h"
 #include "wpa_auth_glue.h"
@@ -786,6 +787,28 @@ static int hostapd_channel_info(void *ctx, struct wpa_channel_info *ci)
        return hostapd_drv_channel_info(hapd, ci);
 }
 
+
+#ifdef CONFIG_OCV
+static int hostapd_get_sta_tx_params(void *ctx, const u8 *addr,
+                                    int ap_max_chanwidth, int ap_seg1_idx,
+                                    int *bandwidth, int *seg1_idx)
+{
+       struct hostapd_data *hapd = ctx;
+       struct sta_info *sta;
+
+       sta = ap_get_sta(hapd, addr);
+       if (!sta) {
+               hostapd_wpa_auth_logger(hapd, addr, LOGGER_INFO,
+                                       "Failed to get STA info to validate received OCI");
+               return -1;
+       }
+
+       return get_tx_parameters(sta, ap_max_chanwidth, ap_seg1_idx, bandwidth,
+                                seg1_idx);
+}
+#endif /* CONFIG_OCV */
+
+
 #ifdef CONFIG_IEEE80211R_AP
 
 static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
@@ -1200,6 +1223,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
                .send_ether = hostapd_wpa_auth_send_ether,
                .send_oui = hostapd_wpa_auth_send_oui,
                .channel_info = hostapd_channel_info,
+#ifdef CONFIG_OCV
+               .get_sta_tx_params = hostapd_get_sta_tx_params,
+#endif /* CONFIG_OCV */
 #ifdef CONFIG_IEEE80211R_AP
                .send_ft_action = hostapd_wpa_auth_send_ft_action,
                .add_sta = hostapd_wpa_auth_add_sta,