hostapd: Add MBO IE to Beacon, Probe Response, Association Response

Add MBO IE with AP capability attribute to Beacon, Probe Response, and
(Re)Association Response frames to indicate the AP supports MBO.

Add option to add Association Disallowed attribute to Beacon, Probe
Response, and (Re)Association Response frames. Usage:

SET mbo_assoc_disallow <reason code>

Valid reason code values are between 1-5. Setting the reason code to
0 will remove the Association Disallowed attribute from the MBO IE
and will allow new associations.

MBO functionality is enabled by setting "mbo=1" in the config file.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
This commit is contained in:
Avraham Stern 2016-02-15 16:53:52 +02:00 committed by Jouni Malinen
parent c484b19882
commit fb9a1c3e28
13 changed files with 149 additions and 0 deletions

View file

@ -263,6 +263,10 @@ ifdef CONFIG_IEEE80211AC
L_CFLAGS += -DCONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC
endif endif
ifdef CONFIG_MBO
L_CFLAGS += -DCONFIG_MBO
endif
ifdef CONFIG_FST ifdef CONFIG_FST
L_CFLAGS += -DCONFIG_FST L_CFLAGS += -DCONFIG_FST
OBJS += src/fst/fst.c OBJS += src/fst/fst.c

View file

@ -282,6 +282,10 @@ ifdef CONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC
endif endif
ifdef CONFIG_MBO
CFLAGS += -DCONFIG_MBO
endif
include ../src/drivers/drivers.mak include ../src/drivers/drivers.mak
OBJS += $(DRV_AP_OBJS) OBJS += $(DRV_AP_OBJS)
CFLAGS += $(DRV_AP_CFLAGS) CFLAGS += $(DRV_AP_CFLAGS)

View file

@ -194,3 +194,8 @@ CONFIG_AP=y
# Enable Fast Session Transfer (FST) # Enable Fast Session Transfer (FST)
#CONFIG_FST=y #CONFIG_FST=y
# Multiband Operation support
# These extentions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y

View file

@ -3300,6 +3300,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "subscr_remediation_method") == 0) { } else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
bss->subscr_remediation_method = atoi(pos); bss->subscr_remediation_method = atoi(pos);
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
} else if (os_strcmp(buf, "mbo") == 0) {
bss->mbo_enabled = atoi(pos);
#endif /* CONFIG_MBO */
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
#define PARSE_TEST_PROBABILITY(_val) \ #define PARSE_TEST_PROBABILITY(_val) \
} else if (os_strcmp(buf, #_val) == 0) { \ } else if (os_strcmp(buf, #_val) == 0) { \

View file

@ -1320,6 +1320,25 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
hapd->ext_eapol_frame_io = atoi(value); hapd->ext_eapol_frame_io = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
} else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
int val;
if (!hapd->conf->mbo_enabled)
return -1;
val = atoi(value);
if (val < 0 || val > 1)
return -1;
hapd->mbo_assoc_disallow = val;
ieee802_11_update_beacons(hapd->iface);
/*
* TODO: Need to configure drivers that do AP MLME offload with
* disallowing station logic.
*/
#endif /* CONFIG_MBO */
} else { } else {
struct sta_info *sta; struct sta_info *sta;
struct vlan_description vlan_id; struct vlan_description vlan_id;

View file

@ -332,3 +332,8 @@ CONFIG_IPV6=y
# http://wireless.kernel.org/en/users/Documentation/acs # http://wireless.kernel.org/en/users/Documentation/acs
# #
#CONFIG_ACS=y #CONFIG_ACS=y
# Multiband Operation support
# These extentions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y

View file

@ -575,6 +575,10 @@ struct hostapd_bss_config {
char *no_auth_if_seen_on; char *no_auth_if_seen_on;
int pbss; int pbss;
#ifdef CONFIG_MBO
int mbo_enabled;
#endif /* CONFIG_MBO */
}; };

View file

@ -204,6 +204,25 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
} }
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
if (hapd->conf->mbo_enabled) {
pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
if (pos != buf) {
if (wpabuf_resize(&beacon, pos - buf) != 0)
goto fail;
wpabuf_put_data(beacon, buf, pos - buf);
if (wpabuf_resize(&proberesp, pos - buf) != 0)
goto fail;
wpabuf_put_data(proberesp, buf, pos - buf);
if (wpabuf_resize(&assocresp, pos - buf) != 0)
goto fail;
wpabuf_put_data(assocresp, buf, pos - buf);
}
}
#endif /* CONFIG_MBO */
if (hapd->conf->vendor_elements) { if (hapd->conf->vendor_elements) {
size_t add = wpabuf_len(hapd->conf->vendor_elements); size_t add = wpabuf_len(hapd->conf->vendor_elements);
if (wpabuf_resize(&beacon, add) == 0) if (wpabuf_resize(&beacon, add) == 0)

View file

@ -387,6 +387,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
2 + sizeof(struct ieee80211_vht_operation); 2 + sizeof(struct ieee80211_vht_operation);
} }
buflen += hostapd_mbo_ie_len(hapd);
resp = os_zalloc(buflen); resp = os_zalloc(buflen);
if (resp == NULL) if (resp == NULL)
return NULL; return NULL;
@ -518,6 +521,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_osen(hapd, pos); pos = hostapd_eid_osen(hapd, pos);
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
if (hapd->conf->vendor_elements) { if (hapd->conf->vendor_elements) {
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements)); wpabuf_len(hapd->conf->vendor_elements));
@ -980,6 +985,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
} }
#endif /* CONFIG_IEEE80211AC */ #endif /* CONFIG_IEEE80211AC */
tail_len += hostapd_mbo_ie_len(hapd);
tailpos = tail = os_malloc(tail_len); tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) { if (head == NULL || tail == NULL) {
wpa_printf(MSG_ERROR, "Failed to set beacon data"); wpa_printf(MSG_ERROR, "Failed to set beacon data");
@ -1133,6 +1140,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_osen(hapd, tailpos); tailpos = hostapd_eid_osen(hapd, tailpos);
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
if (hapd->conf->vendor_elements) { if (hapd->conf->vendor_elements) {
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements)); wpabuf_len(hapd->conf->vendor_elements));

View file

@ -281,6 +281,10 @@ struct hostapd_data {
struct l2_packet_data *l2_test; struct l2_packet_data *l2_test;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
unsigned int mbo_assoc_disallow;
#endif /* CONFIG_MBO */
}; };

View file

@ -1915,6 +1915,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_p2p_manage(hapd, p); p = hostapd_eid_p2p_manage(hapd, p);
#endif /* CONFIG_P2P_MANAGER */ #endif /* CONFIG_P2P_MANAGER */
p = hostapd_eid_mbo(hapd, p, buf + sizeof(buf) - p);
send_len += p - reply->u.assoc_resp.variable; send_len += p - reply->u.assoc_resp.variable;
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) { if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
@ -2048,6 +2050,13 @@ static void handle_assoc(struct hostapd_data *hapd,
goto fail; goto fail;
} }
#ifdef CONFIG_MBO
if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
#endif /* CONFIG_MBO */
/* followed by SSID and Supported rates; and HT capabilities if 802.11n /* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */ * is used */
resp = check_assoc_ies(hapd, sta, pos, left, reassoc); resp = check_assoc_ies(hapd, sta, pos, left, reassoc);

View file

@ -109,4 +109,25 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
} }
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#ifdef CONFIG_MBO
u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len);
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd);
#else /* CONFIG_MBO */
static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid,
size_t len)
{
return eid;
}
static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
{
return 0;
}
#endif /* CONFIG_MBO */
#endif /* IEEE802_11_H */ #endif /* IEEE802_11_H */

View file

@ -508,3 +508,45 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
return pos; return pos;
} }
#ifdef CONFIG_MBO
u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
{
u8 mbo[6], *mbo_pos = mbo;
u8 *pos = eid;
if (!hapd->conf->mbo_enabled)
return eid;
*mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
*mbo_pos++ = 1;
/* Not Cellular aware */
*mbo_pos++ = 0;
if (hapd->mbo_assoc_disallow) {
*mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
*mbo_pos++ = 1;
*mbo_pos++ = hapd->mbo_assoc_disallow;
}
pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
return pos;
}
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
{
if (!hapd->conf->mbo_enabled)
return 0;
/*
* MBO IE header (6) + Capability Indication attribute (3) +
* Association Disallowed attribute (3) = 12
*/
return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
}
#endif /* CONFIG_MBO */