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:
parent
c484b19882
commit
fb9a1c3e28
13 changed files with 149 additions and 0 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) { \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue