int center_segment0, int center_segment1)
{
struct hostapd_freq_params data;
+ struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
vht_enabled, he_enabled, sec_channel_offset,
oper_chwidth,
center_segment0, center_segment1,
- hapd->iface->current_mode ?
- hapd->iface->current_mode->vht_capab : 0,
- &hapd->iface->current_mode->he_capab))
+ cmode ? cmode->vht_capab : 0,
+ cmode ?
+ &cmode->he_capab[IEEE80211_MODE_AP] : NULL))
return -1;
if (hapd->driver == NULL)
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_freq_params data;
int res;
+ struct hostapd_hw_modes *cmode = iface->current_mode;
- if (!hapd->driver || !hapd->driver->start_dfs_cac)
+ if (!hapd->driver || !hapd->driver->start_dfs_cac || !cmode)
return 0;
if (!iface->conf->ieee80211h) {
vht_enabled, he_enabled, sec_channel_offset,
oper_chwidth, center_segment0,
center_segment1,
- iface->current_mode->vht_capab,
- &iface->current_mode->he_capab)) {
+ cmode->vht_capab,
+ &cmode->he_capab[IEEE80211_MODE_AP])) {
wpa_printf(MSG_ERROR, "Can't set freq params");
return -1;
}
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
- pos = hostapd_eid_he_capab(hapd, pos);
+ pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP);
pos = hostapd_eid_he_operation(hapd, pos);
pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
pos = hostapd_eid_spatial_reuse(hapd, pos);
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
- tailpos = hostapd_eid_he_capab(hapd, tailpos);
+ tailpos = hostapd_eid_he_capab(hapd, tailpos,
+ IEEE80211_MODE_AP);
tailpos = hostapd_eid_he_operation(hapd, tailpos);
tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
tailpos = hostapd_eid_spatial_reuse(hapd, tailpos);
struct hostapd_freq_params freq;
struct hostapd_iface *iface = hapd->iface;
struct hostapd_config *iconf = iface->conf;
+ struct hostapd_hw_modes *cmode = iface->current_mode;
struct wpabuf *beacon, *proberesp, *assocresp;
int res, ret = -1;
params.reenable = hapd->reenable_beacon;
hapd->reenable_beacon = 0;
- if (iface->current_mode &&
+ if (cmode &&
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
iconf->channel, iconf->ieee80211n,
iconf->ieee80211ac, iconf->ieee80211ax,
hostapd_get_oper_chwidth(iconf),
hostapd_get_oper_centr_freq_seg0_idx(iconf),
hostapd_get_oper_centr_freq_seg1_idx(iconf),
- iface->current_mode->vht_capab,
- &iface->current_mode->he_capab) == 0)
+ cmode->vht_capab,
+ &cmode->he_capab[IEEE80211_MODE_AP]) == 0)
params.freq = &freq;
res = hostapd_drv_set_ap(hapd, ¶ms);
struct csa_settings csa_settings;
unsigned int i;
int err = 1;
+ struct hostapd_hw_modes *cmode = iface->current_mode;
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
__func__, iface->cac_started ? "yes" : "no",
hostapd_get_oper_chwidth(iface->conf),
oper_centr_freq_seg0_idx,
oper_centr_freq_seg1_idx,
- iface->current_mode->vht_capab,
- &iface->current_mode->he_capab);
+ cmode->vht_capab,
+ &cmode->he_capab[IEEE80211_MODE_AP]);
if (err) {
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
hostapd_get_oper_centr_freq_seg0_idx(conf),
hostapd_get_oper_centr_freq_seg1_idx(conf),
conf->vht_capab,
- mode ? &mode->he_capab : NULL))
+ mode ? &mode->he_capab[IEEE80211_MODE_AP] :
+ NULL))
return -1;
switch (params->bandwidth) {
#endif /* CONFIG_IEEE80211AC */
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
- resp = copy_sta_he_capab(hapd, sta, elems.he_capabilities,
+ resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
+ elems.he_capabilities,
elems.he_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax) {
- p = hostapd_eid_he_capab(hapd, p);
+ p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
p = hostapd_eid_he_operation(hapd, p);
p = hostapd_eid_spatial_reuse(hapd, p);
p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
struct ieee80211_mgmt;
struct vlan_description;
struct hostapd_sta_wpa_psk_short;
+enum ieee80211_op_mode;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
+ enum ieee80211_op_mode opmode);
u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid);
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_opmode);
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *he_capab, size_t he_capab_len);
+ enum ieee80211_op_mode opmode, const u8 *he_capab,
+ size_t he_capab_len);
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,
}
-u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid)
+u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
+ enum ieee80211_op_mode opmode)
{
struct ieee80211_he_capabilities *cap;
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
return eid;
ie_size = sizeof(struct ieee80211_he_capabilities);
- ppet_size = ieee80211_he_ppet_size(mode->he_capab.ppet[0],
- mode->he_capab.phy_cap);
+ ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0],
+ mode->he_capab[opmode].phy_cap);
switch (hapd->iface->conf->he_oper_chwidth) {
case CHANWIDTH_80P80MHZ:
cap = (struct ieee80211_he_capabilities *) pos;
os_memset(cap, 0, sizeof(*cap));
- os_memcpy(cap->he_mac_capab_info, mode->he_capab.mac_cap,
+ os_memcpy(cap->he_mac_capab_info, mode->he_capab[opmode].mac_cap,
HE_MAX_MAC_CAPAB_SIZE);
- os_memcpy(cap->he_phy_capab_info, mode->he_capab.phy_cap,
+ os_memcpy(cap->he_phy_capab_info, mode->he_capab[opmode].phy_cap,
HE_MAX_PHY_CAPAB_SIZE);
- os_memcpy(cap->optional, mode->he_capab.mcs, mcs_nss_size);
+ os_memcpy(cap->optional, mode->he_capab[opmode].mcs, mcs_nss_size);
if (ppet_size)
- os_memcpy(&cap->optional[mcs_nss_size], mode->he_capab.ppet,
- ppet_size);
+ os_memcpy(&cap->optional[mcs_nss_size],
+ mode->he_capab[opmode].ppet, ppet_size);
if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
}
-static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab)
+static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab,
+ enum ieee80211_op_mode opmode)
{
u16 sta_rx_mcs_set, ap_tx_mcs_set;
u8 mcs_count = 0;
if (!hapd->iface->current_mode)
return 1;
- ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab.mcs;
+ ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab[opmode].mcs;
sta_mcs_set = (u16 *) ((const struct ieee80211_he_capabilities *)
sta_he_capab)->optional;
u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *he_capab, size_t he_capab_len)
+ enum ieee80211_op_mode opmode, const u8 *he_capab,
+ size_t he_capab_len)
{
if (!he_capab || !hapd->iconf->ieee80211ax ||
- !check_valid_he_mcs(hapd, he_capab) ||
+ !check_valid_he_mcs(hapd, he_capab, opmode) ||
he_capab_len > sizeof(struct ieee80211_he_capabilities)) {
sta->flags &= ~WLAN_STA_HE;
os_free(sta->he_capab);
#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
#define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1)
+
+enum ieee80211_op_mode {
+ IEEE80211_MODE_INFRA = 0,
+ IEEE80211_MODE_IBSS = 1,
+ IEEE80211_MODE_AP = 2,
+ IEEE80211_MODE_MESH = 5,
+
+ /* only add new entries before IEEE80211_MODE_NUM */
+ IEEE80211_MODE_NUM
+};
+
/**
* struct hostapd_hw_modes - Supported hardware mode information
*/
/**
* he_capab - HE (IEEE 802.11ax) capabilities
*/
- struct he_capabilities he_capab;
+ struct he_capabilities he_capab[IEEE80211_MODE_NUM];
};
-#define IEEE80211_MODE_INFRA 0
-#define IEEE80211_MODE_IBSS 1
-#define IEEE80211_MODE_AP 2
-#define IEEE80211_MODE_MESH 5
-
#define IEEE80211_CAP_ESS 0x0001
#define IEEE80211_CAP_IBSS 0x0002
#define IEEE80211_CAP_PRIVACY 0x0010
}
-static int phy_info_iftype(struct hostapd_hw_modes *mode,
- struct nlattr *nl_iftype)
+static void phy_info_iftype_copy(struct he_capabilities *he_capab,
+ enum ieee80211_op_mode opmode,
+ struct nlattr **tb, struct nlattr **tb_flags)
{
- struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
- struct he_capabilities *he_capab = &mode->he_capab;
- struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1];
+ enum nl80211_iftype iftype;
size_t len;
- nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
- nla_data(nl_iftype), nla_len(nl_iftype), NULL);
-
- if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
- return NL_STOP;
-
- if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX,
- tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL))
- return NL_STOP;
+ switch (opmode) {
+ case IEEE80211_MODE_INFRA:
+ iftype = NL80211_IFTYPE_STATION;
+ break;
+ case IEEE80211_MODE_IBSS:
+ iftype = NL80211_IFTYPE_ADHOC;
+ break;
+ case IEEE80211_MODE_AP:
+ iftype = NL80211_IFTYPE_AP;
+ break;
+ case IEEE80211_MODE_MESH:
+ iftype = NL80211_IFTYPE_MESH_POINT;
+ break;
+ default:
+ return;
+ }
- if (!nla_get_flag(tb_flags[NL80211_IFTYPE_AP]))
- return NL_OK;
+ if (!nla_get_flag(tb_flags[iftype]))
+ return;
he_capab->he_supported = 1;
nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]),
len);
}
+}
+
+
+static int phy_info_iftype(struct hostapd_hw_modes *mode,
+ struct nlattr *nl_iftype)
+{
+ struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
+ struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1];
+ unsigned int i;
+
+ nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
+ nla_data(nl_iftype), nla_len(nl_iftype), NULL);
+
+ if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
+ return NL_STOP;
+
+ if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX,
+ tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL))
+ return NL_STOP;
+
+ for (i = 0; i < IEEE80211_MODE_NUM; i++)
+ phy_info_iftype_copy(&mode->he_capab[i], i, tb, tb_flags);
return NL_OK;
}