From: Venkateswara Naralasetty <vnaralas@xxxxxxxxxxxxxx> The purpose of Multi-AP specification is to enable inter-operability across Wi-Fi access points (APs) from different vendors. Advertise vendor specific Multi-AP capabilities in (Re)Association response frame, if user enable Multi-AP functionality through configuration parameter.Create one AP/VLAN interface for the client which supports Multi-AP since as per the Multi-AP spec fronthaul AP should receive both 3addr and 4addr frames from the backhaul STA. This patch introducing one new configuration parameter 'multi_ap_enabled' to enable Multi-AP functionlity. Signed-off-by: Venkateswara Naralasetty <vnaralas@xxxxxxxxxxxxxx> Signed-off-by: Jouni Malinen <jouni@xxxxxxxxxxxxxx> --- hostapd/Makefile | 4 +++ hostapd/config_file.c | 13 ++++++++++ hostapd/defconfig | 3 +++ hostapd/hostapd.conf | 7 ++++++ src/ap/ap_config.h | 4 +++ src/ap/ieee802_11.c | 57 +++++++++++++++++++++++++++++++++++++++++- src/ap/sta_info.c | 2 +- src/ap/sta_info.h | 1 + src/common/ieee802_11_common.c | 11 ++++++++ src/common/ieee802_11_common.h | 2 ++ src/common/ieee802_11_defs.h | 25 ++++++++++++++++++ 11 files changed, 127 insertions(+), 2 deletions(-) diff --git a/hostapd/Makefile b/hostapd/Makefile index 2ce8b7d..4db3d34 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -61,6 +61,10 @@ CFLAGS += -DCONFIG_NATIVE_WINDOWS LIBS += -lws2_32 endif +ifdef CONFIG_MULTI_AP +CFLAGS += -DCONFIG_MULTI_AP +endif + OBJS += main.o OBJS += config_file.o diff --git a/hostapd/config_file.c b/hostapd/config_file.c index b26da71..72508ab 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4111,6 +4111,19 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) { bss->coloc_intf_reporting = atoi(pos); #endif /* CONFIG_OWE */ +#ifdef CONFIG_MULTI_AP + } else if (os_strcmp(buf, "multi_ap_enabled") == 0) { + int val = atoi(pos); + + if (val > 3 || val < 0) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid multi_ap_enabled '%s'", + line, buf); + return -1; + } + + bss->multi_ap_enabled = val; +#endif /*CONFIG_MULTI_AP */ } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/defconfig b/hostapd/defconfig index c67c662..7746c13 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -373,3 +373,6 @@ CONFIG_IPV6=y # Override default value for the wpa_disable_eapol_key_retries configuration # parameter. See that parameter in hostapd.conf for more details. #CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1 + +#Multi-AP protocol support +#CONFIG_MULTI_AP=y diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index a005217..5a2c4bb 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -438,6 +438,13 @@ wmm_ac_vo_txop_limit=47 wmm_ac_vo_acm=0 # Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 +#Enable Multi-AP functionality. +#0:default +#1:Enable Multi-AP as BACKHAUL_BSS +#2:Enable Multi-AP as FRONTHAUL_BSS +#3:Enable Multi-AP as BACKHAUL_BSS and FRONTHAUL_BSS +#multi_ap_enabled=0 + # Static WEP key configuration # # The key number to use when transmitting. diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 778366d..7fa45f7 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -686,6 +686,10 @@ struct hostapd_bss_config { #endif /* CONFIG_OWE */ int coloc_intf_reporting; + +#ifdef CONFIG_MULTI_AP + int multi_ap_enabled; +#endif /*CONFIG_MULTI_AP */ }; /** diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index d2d6b17..d464d82 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -62,6 +62,34 @@ prepare_auth_resp_fils(struct hostapd_data *hapd, int *is_pub); #endif /* CONFIG_FILS */ +u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + +#ifdef CONFIG_MULTI_AP + struct multi_ap_ie *map = (struct multi_ap_ie *) (pos + 2); + int multi_ap_enabled = hapd->conf->multi_ap_enabled; + + if (!multi_ap_enabled) + return eid; + + eid[0] = WLAN_EID_VENDOR_SPECIFIC; + eid[1] = 7; /* len */ + WPA_PUT_BE24(map->oui, OUI_WFA); + map->oui_type = MULTI_AP_OUI_TYPE; + map->sub_elem_id = MULTI_AP_SUB_ELEM_TYPE; + map->sub_elem_len = 0x1; + if (multi_ap_enabled & BACKHAUL_BSS) + map->sub_elem_val |= MULTI_AP_BACKHAUL_BSS; + if (multi_ap_enabled & FRONTHAUL_BSS) + map->sub_elem_val |= MULTI_AP_FRONTHAUL_BSS; + + pos = (u8 *) (map + 1); +#endif /* CONFIG_MULTI_AP */ + + return pos; +} + u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; @@ -2210,6 +2238,21 @@ static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } +#ifdef CONFIG_MULTI_AP +static u16 hostapd_validate_multi_ap_ie(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *multi_ap_ie) +{ + sta->flags &= ~WLAN_STA_MULTI_AP; + + if (multi_ap_ie) { + struct multi_ap_ie *map = (struct multi_ap_ie *)multi_ap_ie; + if (map->sub_elem_id != MULTI_AP_SUB_ELEM_TYPE) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + sta->flags |= WLAN_STA_MULTI_AP; + } + return WLAN_STATUS_SUCCESS; +} +#endif /* CONFIG_MULTI_AP */ static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta, struct ieee802_11_elems *elems) @@ -2466,6 +2509,15 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, resp = copy_supp_rates(hapd, sta, &elems); if (resp != WLAN_STATUS_SUCCESS) return resp; + +#ifdef CONFIG_MULTI_AP + if (hapd->conf->multi_ap_enabled) { + resp = hostapd_validate_multi_ap_ie(hapd, sta, elems.multi_ap); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_MULTI_AP */ + #ifdef CONFIG_IEEE80211N resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities); if (resp != WLAN_STATUS_SUCCESS) @@ -2995,6 +3047,9 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_WPS */ + if (sta && (sta->flags & WLAN_STA_MULTI_AP)) + p = hostapd_eid_multi_ap(hapd, p); + #ifdef CONFIG_P2P if (sta && sta->p2p_ie && hapd->p2p_group) { struct wpabuf *p2p_resp_ie; @@ -4227,7 +4282,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd, sta->flags |= WLAN_STA_WDS; } - if (sta->flags & WLAN_STA_WDS) { + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) { int ret; char ifname_wds[IFNAMSIZ + 1]; diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 179cf43..6d683f7 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -166,7 +166,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) /* just in case */ ap_sta_set_authorized(hapd, sta, 0); - if (sta->flags & WLAN_STA_WDS) + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); if (sta->ipaddr) diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 9cac6f1..2b60e92 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -36,6 +36,7 @@ #define WLAN_STA_VHT_OPMODE_ENABLED BIT(20) #define WLAN_STA_VENDOR_VHT BIT(21) #define WLAN_STA_PENDING_FILS_ERP BIT(22) +#define WLAN_STA_MULTI_AP BIT(23) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index e1ef277..3f138da 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -126,6 +126,17 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->roaming_cons_sel = pos; elems->roaming_cons_sel_len = elen; break; + case MULTI_AP_OUI_TYPE: + if (elen < 7) { + wpa_printf(MSG_MSGDUMP, "short Multi-AP " + "information element ignored " + "(len=%lu)", + (unsigned long) elen); + return -1; + } + elems->multi_ap = pos; + elems->multi_ap_len = elen; + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index ff7e51d..f602f87 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -84,6 +84,7 @@ struct ieee802_11_elems { const u8 *power_capab; const u8 *roaming_cons_sel; const u8 *password_id; + const u8 *multi_ap; u8 ssid_len; u8 supp_rates_len; @@ -130,6 +131,7 @@ struct ieee802_11_elems { u8 power_capab_len; u8 roaming_cons_sel_len; u8 password_id_len; + u8 multi_ap_len; struct mb_ies_info mb_ies; }; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 762e731..c1a3a85 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1210,6 +1210,31 @@ struct ieee80211_ampe_ie { #define MBO_OUI_TYPE 22 #define OWE_IE_VENDOR_TYPE 0x506f9a1c #define OWE_OUI_TYPE 28 +#define MULTI_AP_OUI_TYPE 0x1B + +#ifdef CONFIG_MULTI_AP +#define MULTI_AP_SUB_ELEM_TYPE 0x06 +#define MULTI_AP_BACKHAUL_BSS 0x40 +#define MULTI_AP_FRONTHAUL_BSS 0x20 +#define BACKHAUL_BSS 1 +#define FRONTHAUL_BSS 2 + +/*MAP Information Element (used in (Re)Association Request frames) + */ +struct multi_ap_ie { + /* Element ID: 221 (0xdd); Length: 7 */ + u8 oui[3]; /* OUI_WFA 50:6F:9A */ + u8 oui_type; /* 0x1B */ + u8 sub_elem_id; /* 0x06 */ + u8 sub_elem_len; /* 1 */ + u8 sub_elem_val; /* BIT(7):Backhaul STA + * BIT(6):Backhaul BSS + * BIT(5):Fronthaul BSS + * BIT(3) to BIT(0) reserved + */ + +} STRUCT_PACKED; +#endif /* CONFIG_MULTI_AP */ #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap