Do not store dynamic HT IEs in configuration structures

The configuration data should only store the static configuration data and
not dynamic data. In addition, storing HT configuration and state in IEs is
not the easiest way of doing this, so use more convenient data types for
storing configuration and dynamic state. The HT IEs are then generated
based on the static configuration and dynamic state whenever needed.
This commit is contained in:
Jouni Malinen 2008-08-22 20:55:52 +03:00 committed by Jouni Malinen
parent 71b6ae1425
commit edd360e170
7 changed files with 87 additions and 98 deletions

View file

@ -386,18 +386,19 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
#ifdef CONFIG_IEEE80211N #ifdef CONFIG_IEEE80211N
if (hapd->conf->ieee80211n) { if (hapd->conf->ieee80211n) {
u8 *start;
start = tailpos;
tailpos = hostapd_eid_ht_capabilities_info(hapd, tailpos); tailpos = hostapd_eid_ht_capabilities_info(hapd, tailpos);
tailpos = hostapd_eid_ht_operation(hapd, tailpos); if (hostapd_set_ht_capability(hapd->conf->iface, hapd,
start + 2)) {
if (hostapd_set_ht_capability(
hapd->conf->iface, hapd,
&hapd->conf->ht_capabilities.data)) {
wpa_printf(MSG_ERROR, "Could not set HT capabilities " wpa_printf(MSG_ERROR, "Could not set HT capabilities "
"for kernel driver"); "for kernel driver");
} }
if (hostapd_set_ht_operation(
hapd->conf->iface, hapd, start = tailpos;
&hapd->conf->ht_operation.data)) tailpos = hostapd_eid_ht_operation(hapd, tailpos);
if (hostapd_set_ht_operation(hapd->conf->iface, hapd,
start + 2))
wpa_printf(MSG_ERROR, "Could not set HT operation for " wpa_printf(MSG_ERROR, "Could not set HT operation for "
"kernel driver"); "kernel driver");
} }

View file

@ -184,54 +184,6 @@ static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
} }
#ifdef CONFIG_IEEE80211N
static int hostapd_config_defaults_bss_80211n(struct hostapd_bss_config *bss)
{
u16 capabilities_info = 0;
u16 operation_mode = 0;
if (bss == NULL)
return -1;
/* add default values to HT capabilities parameters */
os_memset(&bss->ht_capabilities, 0, sizeof(struct ht_cap_ie));
bss->ht_capabilities.id = WLAN_EID_HT_CAP;
bss->ht_capabilities.length = HT_CAPABILITIES_LEN;
#if 0 /* FIX: remove? was commented out */
bss->ht_capabilities.mac_ht_param_info.max_rx_ampdu_factor =
MAX_RX_AMPDU_FACTOR_64KB;
#endif
SET_2BIT_U8(&bss->ht_capabilities.data.mac_ht_params_info,
MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET,
MAX_RX_AMPDU_FACTOR_64KB);
SET_2BIT_LE16(&capabilities_info,
HT_CAP_INFO_MIMO_PWR_SAVE_OFFSET,
MIMO_PWR_NO_LIMIT_ON_MIMO_SEQS);
capabilities_info |= HT_CAP_INFO_GREEN_FIELD;
bss->ht_capabilities.data.capabilities_info =
host_to_le16(capabilities_info);
bss->ht_capabilities.data.supported_mcs_set[0] = 0xff;
bss->ht_capabilities.data.supported_mcs_set[1] = 0xff;
/* add default values to HT operation parameters */
os_memset(&bss->ht_operation, 0, sizeof(struct ht_operation_ie));
bss->ht_operation.id = WLAN_EID_HT_OPERATION;
bss->ht_operation.length = HT_OPERATION_LEN;
SET_2BIT_LE16(&operation_mode,
HT_INFO_OPERATION_MODE_OP_MODE_OFFSET,
OP_MODE_PURE);
bss->ht_operation.data.operation_mode = host_to_le16(operation_mode);
return 0;
}
#endif /* CONFIG_IEEE80211N */
static struct hostapd_config * hostapd_config_defaults(void) static struct hostapd_config * hostapd_config_defaults(void)
{ {
struct hostapd_config *conf; struct hostapd_config *conf;
@ -294,7 +246,11 @@ static struct hostapd_config * hostapd_config_defaults(void)
conf->wme_ac_params[3] = ac_vo; conf->wme_ac_params[3] = ac_vo;
#ifdef CONFIG_IEEE80211N #ifdef CONFIG_IEEE80211N
hostapd_config_defaults_bss_80211n(bss); SET_2BIT_LE16(&bss->ht_capab,
HT_CAP_INFO_MIMO_PWR_SAVE_OFFSET,
MIMO_PWR_NO_LIMIT_ON_MIMO_SEQS);
bss->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
#endif /* CONFIG_IEEE80211N */ #endif /* CONFIG_IEEE80211N */
return conf; return conf;

View file

@ -19,9 +19,6 @@
#include "defs.h" #include "defs.h"
#include "ip_addr.h" #include "ip_addr.h"
#include "wpa_common.h" #include "wpa_common.h"
#ifdef CONFIG_IEEE80211N
#include "ieee802_11_defs.h"
#endif /* CONFIG_IEEE80211N */
#ifndef IFNAMSIZ #ifndef IFNAMSIZ
#define IFNAMSIZ 16 #define IFNAMSIZ 16
@ -279,12 +276,8 @@ struct hostapd_bss_config {
#ifdef CONFIG_IEEE80211N #ifdef CONFIG_IEEE80211N
int ieee80211n; int ieee80211n;
/* TODO: these structures should not really be used here; move to
* struct hostapd_data or struct hostapd_iface and just include the
* needed values here for generating IEs elsewhere */
struct ht_cap_ie ht_capabilities;
struct ht_operation_ie ht_operation;
int ht_op_mode_fixed; int ht_op_mode_fixed;
u16 ht_capab;
#endif /* CONFIG_IEEE80211N */ #endif /* CONFIG_IEEE80211N */
}; };

View file

@ -743,25 +743,25 @@ hostapd_set_radius_acl_expire(struct hostapd_data *hapd, const u8 *mac)
#ifdef CONFIG_IEEE80211N #ifdef CONFIG_IEEE80211N
static inline int static inline int
hostapd_set_ht_capability(const char *ifname, struct hostapd_data *hapd, hostapd_set_ht_capability(const char *ifname, struct hostapd_data *hapd,
const struct ieee80211_ht_capability *ht_cap) const u8 *ht_cap)
{ {
if (hapd->driver == NULL || hapd->driver->set_ht_capability == NULL || if (hapd->driver == NULL || hapd->driver->set_ht_capability == NULL ||
ht_cap == NULL) ht_cap == NULL)
return 0; return 0;
return hapd->driver->set_ht_capability( return hapd->driver->set_ht_capability(
ifname, hapd->drv_priv, (const u8 *) ht_cap, ifname, hapd->drv_priv, ht_cap,
sizeof(struct ieee80211_ht_capability)); sizeof(struct ieee80211_ht_capability));
} }
static inline int static inline int
hostapd_set_ht_operation(const char *ifname, struct hostapd_data *hapd, hostapd_set_ht_operation(const char *ifname, struct hostapd_data *hapd,
const struct ieee80211_ht_operation *ht_operation) const u8 *ht_operation)
{ {
if (hapd->driver == NULL || hapd->driver->set_ht_operation == NULL || if (hapd->driver == NULL || hapd->driver->set_ht_operation == NULL ||
ht_operation == NULL) ht_operation == NULL)
return 0; return 0;
return hapd->driver->set_ht_operation( return hapd->driver->set_ht_operation(
ifname, hapd->drv_priv, (const u8 *) ht_operation, ifname, hapd->drv_priv, ht_operation,
sizeof(struct ieee80211_ht_operation)); sizeof(struct ieee80211_ht_operation));
} }
#endif /* CONFIG_IEEE80211N */ #endif /* CONFIG_IEEE80211N */

View file

@ -1563,6 +1563,12 @@ static int setup_interface1(struct hostapd_iface *iface)
if (hostapd_validate_bssid_configuration(iface)) if (hostapd_validate_bssid_configuration(iface))
return -1; return -1;
#ifdef CONFIG_IEEE80211N
SET_2BIT_LE16(&iface->ht_op_mode,
HT_INFO_OPERATION_MODE_OP_MODE_OFFSET,
OP_MODE_PURE);
#endif /* CONFIG_IEEE80211N */
os_memcpy(country, hapd->iconf->country, 3); os_memcpy(country, hapd->iconf->country, 3);
country[3] = '\0'; country[3] = '\0';
if (hostapd_set_country(hapd, country) < 0) { if (hostapd_set_country(hapd, country) < 0) {

View file

@ -244,6 +244,10 @@ struct hostapd_iface {
struct hostapd_config_change *change; struct hostapd_config_change *change;
hostapd_iface_cb reload_iface_cb; hostapd_iface_cb reload_iface_cb;
hostapd_iface_cb config_reload_cb; hostapd_iface_cb config_reload_cb;
#ifdef CONFIG_IEEE80211N
u16 ht_op_mode;
#endif /* CONFIG_IEEE80211N */
}; };
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,

View file

@ -105,19 +105,50 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid)
{ {
struct ieee80211_ht_capability *cap;
u8 *pos = eid; u8 *pos = eid;
os_memcpy(pos, &hapd->conf->ht_capabilities, sizeof(struct ht_cap_ie));
pos += sizeof(struct ht_cap_ie); if (!hapd->conf->ieee80211n)
return eid;
*pos++ = WLAN_EID_HT_CAP;
*pos++ = sizeof(*cap);
cap = (struct ieee80211_ht_capability *) pos;
os_memset(cap, 0, sizeof(*cap));
SET_2BIT_U8(&cap->mac_ht_params_info,
MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET,
MAX_RX_AMPDU_FACTOR_64KB);
cap->capabilities_info = host_to_le16(hapd->conf->ht_capab);
cap->supported_mcs_set[0] = 0xff;
cap->supported_mcs_set[1] = 0xff;
pos += sizeof(*cap);
return pos; return pos;
} }
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
{ {
struct ieee80211_ht_operation *oper;
u8 *pos = eid; u8 *pos = eid;
os_memcpy(pos, &hapd->conf->ht_operation,
sizeof(struct ht_operation_ie)); if (!hapd->conf->ieee80211n)
pos += sizeof(struct ht_operation_ie); return eid;
*pos++ = WLAN_EID_HT_OPERATION;
*pos++ = sizeof(*oper);
oper = (struct ieee80211_ht_operation *) pos;
os_memset(oper, 0, sizeof(*oper));
oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
pos += sizeof(*oper);
return pos; return pos;
} }
@ -136,8 +167,6 @@ Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
*/ */
int hostapd_ht_operation_update(struct hostapd_iface *iface) int hostapd_ht_operation_update(struct hostapd_iface *iface)
{ {
struct ht_operation_ie *ht_operation;
u16 operation_mode = 0;
u16 cur_op_mode, new_op_mode; u16 cur_op_mode, new_op_mode;
int op_mode_changes = 0; int op_mode_changes = 0;
struct hostapd_data *hapd = iface->bss[0]; struct hostapd_data *hapd = iface->bss[0];
@ -148,29 +177,31 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
if (!hapd->conf->ieee80211n || hapd->conf->ht_op_mode_fixed) if (!hapd->conf->ieee80211n || hapd->conf->ht_op_mode_fixed)
return 0; return 0;
ht_operation = &hapd->conf->ht_operation;
operation_mode = le_to_host16(ht_operation->data.operation_mode);
wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
__func__, operation_mode); __func__, iface->ht_op_mode);
if ((operation_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) == 0 if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
&& iface->num_sta_ht_no_gf) { && iface->num_sta_ht_no_gf) {
operation_mode |= HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; iface->ht_op_mode |=
HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
op_mode_changes++; op_mode_changes++;
} else if ((operation_mode & } else if ((iface->ht_op_mode &
HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
iface->num_sta_ht_no_gf == 0) { iface->num_sta_ht_no_gf == 0) {
operation_mode &= ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; iface->ht_op_mode &=
~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
op_mode_changes++; op_mode_changes++;
} }
if ((operation_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) == 0 if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
&& (iface->num_sta_no_ht || iface->olbc_ht)) { (iface->num_sta_no_ht || iface->olbc_ht)) {
operation_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
op_mode_changes++; op_mode_changes++;
} else if ((operation_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) } else if ((iface->ht_op_mode &
&& (iface->num_sta_no_ht == 0 && iface->olbc_ht == 0)) { HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
operation_mode &= ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
iface->ht_op_mode &=
~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
op_mode_changes++; op_mode_changes++;
} }
@ -180,10 +211,9 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
*/ */
new_op_mode = 0; new_op_mode = 0;
if (iface->num_sta_no_ht || if (iface->num_sta_no_ht ||
(operation_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
new_op_mode = OP_MODE_MIXED; new_op_mode = OP_MODE_MIXED;
else if ((hapd->conf->ht_capabilities.data.capabilities_info & else if ((hapd->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
iface->num_sta_ht_20mhz) iface->num_sta_ht_20mhz)
new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
else if (iface->olbc_ht) else if (iface->olbc_ht)
@ -191,16 +221,15 @@ int hostapd_ht_operation_update(struct hostapd_iface *iface)
else else
new_op_mode = OP_MODE_PURE; new_op_mode = OP_MODE_PURE;
cur_op_mode = operation_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
if (cur_op_mode != new_op_mode) { if (cur_op_mode != new_op_mode) {
operation_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
operation_mode |= new_op_mode; iface->ht_op_mode |= new_op_mode;
op_mode_changes++; op_mode_changes++;
} }
wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
__func__, operation_mode, op_mode_changes); __func__, iface->ht_op_mode, op_mode_changes);
ht_operation->data.operation_mode = host_to_le16(operation_mode);
return op_mode_changes; return op_mode_changes;
} }