OCV: Add function to derive Tx parameters to a specific STA
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>
This commit is contained in:
parent
697652085f
commit
1034f67bf1
5 changed files with 118 additions and 0 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue