diff mbox series

[1/2] hostapd: Add Multi-AP protocol support

Message ID 1542579539-16577-1-git-send-email-jouni@codeaurora.org
State Changes Requested
Headers show
Series [1/2] hostapd: Add Multi-AP protocol support | expand

Commit Message

Jouni Malinen Nov. 18, 2018, 10:18 p.m. UTC
From: Venkateswara Naralasetty <vnaralas@codeaurora.org>

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@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 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(-)

Comments

Arnout Vandecappelle Nov. 19, 2018, 10:33 a.m. UTC | #1
On 18/11/2018 23:18, Jouni Malinen wrote:
> +/*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 */

 I could be wrong, but I think the intention is that the Multi-AP IE would
contain a TLV list, of which currently only type 0x06 is defined. If that is the
case, I think it should be processed similar to e.g. mbo, as a sequence of
subelements rather than a fixed structure.

 Regards,
 Arnout

> +	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 */
Jouni Malinen Nov. 19, 2018, 6:34 p.m. UTC | #2
On Mon, Nov 19, 2018 at 11:33:38AM +0100, Arnout Vandecappelle wrote:
> On 18/11/2018 23:18, Jouni Malinen wrote:
> > +/*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 */
> 
>  I could be wrong, but I think the intention is that the Multi-AP IE would
> contain a TLV list, of which currently only type 0x06 is defined. If that is the
> case, I think it should be processed similar to e.g. mbo, as a sequence of
> subelements rather than a fixed structure.

Agreed. While this hardcoded design with a single subelement would work
for constructing a Multi-AP IE for the current use cases (well, with the
struct renamed to be more specific for that use case), it is not really
a good idea to use this for parsing the element. There is no guarantee
in the tech spec that the particular Multi-AP Extension subelement would
be the first subelement in the received Multi-AP IE.
Arnout Vandecappelle Nov. 27, 2018, 2:59 p.m. UTC | #3
One more question...

On 18/11/2018 23:18, Jouni Malinen wrote:
> +ifdef CONFIG_MULTI_AP
> +CFLAGS += -DCONFIG_MULTI_AP
> +endif

 Is it useful to make a CONFIG_ option for this? I don't think this feature adds
much code size, data size or runtime overhead, and it's covered by a .conf
option anyway.

 Regards,
 Arnout
Jouni Malinen Dec. 2, 2018, 10:45 p.m. UTC | #4
On Tue, Nov 27, 2018 at 03:59:57PM +0100, Arnout Vandecappelle wrote:
>  One more question...
> 
> On 18/11/2018 23:18, Jouni Malinen wrote:
> > +ifdef CONFIG_MULTI_AP
> > +CFLAGS += -DCONFIG_MULTI_AP
> > +endif
> 
>  Is it useful to make a CONFIG_ option for this? I don't think this feature adds
> much code size, data size or runtime overhead, and it's covered by a .conf
> option anyway.

That's probably not much of an issue with this, so I would not have
problems with those ifdefs being removed.
diff mbox series

Patch

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