hostapd: Add Operating Mode Notification support
Handle Operating Mode Notification received in (Re)Association Request frames. Signed-hostap: Marek Kwaczynski <marek.kwaczynski@tieto.com>
This commit is contained in:
parent
d9dd86be1d
commit
8a45811638
11 changed files with 64 additions and 3 deletions
|
@ -346,7 +346,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
u32 flags, u8 qosinfo)
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
|
@ -364,6 +364,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
params.listen_interval = listen_interval;
|
||||
params.ht_capabilities = ht_capab;
|
||||
params.vht_capabilities = vht_capab;
|
||||
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
|
||||
params.vht_opmode = vht_opmode;
|
||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||
params.qosinfo = qosinfo;
|
||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||
|
|
|
@ -40,7 +40,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
|||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
u32 flags, u8 qosinfo);
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode);
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
|
||||
size_t elem_len);
|
||||
|
|
|
@ -895,6 +895,11 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
elems.vht_capabilities_len);
|
||||
if (resp != WLAN_STATUS_SUCCESS)
|
||||
return resp;
|
||||
|
||||
resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
|
||||
if (resp != WLAN_STATUS_SUCCESS)
|
||||
return resp;
|
||||
|
||||
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
|
||||
!(sta->flags & WLAN_STA_VHT)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
|
@ -1937,7 +1942,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
sta->listen_interval,
|
||||
sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
|
||||
sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
|
||||
sta->flags, sta->qosinfo)) {
|
||||
sta->flags, sta->qosinfo, sta->vht_opmode)) {
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_NOTICE,
|
||||
"Could not add STA to kernel driver");
|
||||
|
|
|
@ -61,6 +61,8 @@ u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_capab, size_t vht_capab_len);
|
||||
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_opmode);
|
||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *buf, size_t len, int ack);
|
||||
void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
||||
|
|
|
@ -108,6 +108,35 @@ u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *vht_oper_notif)
|
||||
{
|
||||
u8 channel_width;
|
||||
|
||||
if (!vht_oper_notif) {
|
||||
sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
channel_width = *vht_oper_notif & VHT_OPMODE_CHANNEL_WIDTH_MASK;
|
||||
|
||||
if (channel_width != VHT_CHANWIDTH_USE_HT &&
|
||||
channel_width != VHT_CHANWIDTH_80MHZ &&
|
||||
channel_width != VHT_CHANWIDTH_160MHZ &&
|
||||
channel_width != VHT_CHANWIDTH_80P80MHZ &&
|
||||
((*vht_oper_notif & VHT_OPMODE_CHANNEL_RxNSS_MASK) >>
|
||||
VHT_OPMODE_NOTIF_RX_NSS_SHIFT) > VHT_RX_NSS_MAX_STREAMS - 1) {
|
||||
sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED;
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
sta->flags |= WLAN_STA_VHT_OPMODE_ENABLED;
|
||||
sta->vht_opmode = *vht_oper_notif;
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void hostapd_get_vht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_vht_capabilities *vht_cap,
|
||||
struct ieee80211_vht_capabilities *neg_vht_cap)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define WLAN_STA_GAS BIT(17)
|
||||
#define WLAN_STA_VHT BIT(18)
|
||||
#define WLAN_STA_WNM_SLEEP_MODE BIT(19)
|
||||
#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20)
|
||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
@ -103,6 +104,7 @@ struct sta_info {
|
|||
|
||||
struct ieee80211_ht_capabilities *ht_capabilities;
|
||||
struct ieee80211_vht_capabilities *vht_capabilities;
|
||||
u8 vht_opmode;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
|
|
|
@ -252,6 +252,11 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
|||
elems->vht_operation = pos;
|
||||
elems->vht_operation_len = elen;
|
||||
break;
|
||||
case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
|
||||
if (elen != 1)
|
||||
break;
|
||||
elems->vht_opmode_notif = pos;
|
||||
break;
|
||||
case WLAN_EID_LINK_ID:
|
||||
if (elen < 18)
|
||||
break;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct ieee802_11_elems {
|
|||
const u8 *ht_operation;
|
||||
const u8 *vht_capabilities;
|
||||
const u8 *vht_operation;
|
||||
const u8 *vht_opmode_notif;
|
||||
const u8 *vendor_ht_cap;
|
||||
const u8 *p2p;
|
||||
const u8 *wfd;
|
||||
|
|
|
@ -764,6 +764,13 @@ struct ieee80211_vht_operation {
|
|||
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
|
||||
#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
|
||||
|
||||
#define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1))
|
||||
#define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \
|
||||
BIT(6))
|
||||
#define VHT_OPMODE_NOTIF_RX_NSS_SHIFT 4
|
||||
|
||||
#define VHT_RX_NSS_MAX_STREAMS 8
|
||||
|
||||
/* VHT channel widths */
|
||||
#define VHT_CHANWIDTH_USE_HT 0
|
||||
#define VHT_CHANWIDTH_80MHZ 1
|
||||
|
|
|
@ -1028,6 +1028,8 @@ struct hostapd_sta_add_params {
|
|||
u16 listen_interval;
|
||||
const struct ieee80211_ht_capabilities *ht_capabilities;
|
||||
const struct ieee80211_vht_capabilities *vht_capabilities;
|
||||
int vht_opmode_enabled;
|
||||
u8 vht_opmode;
|
||||
u32 flags; /* bitmask of WPA_STA_* flags */
|
||||
int set; /* Set STA parameters instead of add */
|
||||
u8 qosinfo;
|
||||
|
|
|
@ -7351,6 +7351,12 @@ static int wpa_driver_nl80211_sta_add(void *priv,
|
|||
params->vht_capabilities);
|
||||
}
|
||||
|
||||
if (params->vht_opmode_enabled) {
|
||||
wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode);
|
||||
NLA_PUT_U8(msg, NL80211_ATTR_OPMODE_NOTIF,
|
||||
params->vht_opmode);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability);
|
||||
NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);
|
||||
|
||||
|
|
Loading…
Reference in a new issue