[5/6] AP: Add support for co-located AP configuration
diff mbox series

Message ID 20190619124916.14150-6-andrei.otcheretianski@intel.com
State New
Headers show
Series
  • AP: Support for 6GHz band
Related show

Commit Message

Otcheretianski, Andrei June 19, 2019, 12:49 p.m. UTC
Add configuration option to indicate co-located interfaces. When this
configuration is set, the AP will publish Reduced Neighbor Report
accordingly. It is possible to configure multiple co-located interfaces.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
---
 hostapd/Makefile             |  1 +
 hostapd/config_file.c        | 24 ++++++++++++
 hostapd/hostapd.conf         |  6 +++
 src/ap/ap_config.c           |  4 ++
 src/ap/ap_config.h           |  6 +++
 src/ap/beacon.c              | 74 ++++++++++++++++++++++++++++++++++++
 src/ap/hostapd.c             |  7 ++++
 src/common/ieee802_11_defs.h | 15 ++++++++
 wpa_supplicant/Makefile      |  1 +
 9 files changed, 138 insertions(+)

Comments

Igor Mitsyanko June 28, 2019, 9:28 p.m. UTC | #1
On 6/19/19 5:49 AM, Andrei Otcheretianski wrote:
> +               if (!h || !h->started || !h->iface->current_mode || h == hapd)
> +                       continue;

Hi Andrei, a few questions on when RnR element should be added:
- it should only be added to 2.4GHz and 5GHz BSS frames as far as I know.
- shouldn't we only add RnR for 6Ghz interfaces that are beaconing? That 
is, should we trace when interface start or stop beaconing (I believe 
!h->started is not enough)
- should we track channel changes? Update RnR if interface switches away 
from 6GHz channel, or switches to 6Ghz from other band.
- would it make sense for hostapd to automatically add RnR elements for 
any beaconing 6GHz BSS to any 2.4GHz and 5GHz IEs so that user won't 
have to specify co0located interfaces in configuration? What does spec 
says, is RnR element mandatory in co-located configuration, or it is 
optional?
Otcheretianski, Andrei June 30, 2019, 9:15 a.m. UTC | #2
> -----Original Message-----
> From: Igor Mitsyanko [mailto:igor.mitsyanko.os@quantenna.com]
> Sent: Saturday, June 29, 2019 00:29
> To: Otcheretianski, Andrei <andrei.otcheretianski@intel.com>;
> hostap@lists.infradead.org
> Subject: Re: [PATCH 5/6] AP: Add support for co-located AP configuration
> 
> On 6/19/19 5:49 AM, Andrei Otcheretianski wrote:
> > +               if (!h || !h->started || !h->iface->current_mode || h == hapd)
> > +                       continue;
> 
> Hi Andrei, a few questions on when RnR element should be added:
> - it should only be added to 2.4GHz and 5GHz BSS frames as far as I know.

The spec mandates to add RNR element on 2.4GHz and 5GHz co-located AP's.
I didn't find any restriction to add RNR on 6GHz AP, but I agree that it doesn't make much sense.

> - shouldn't we only add RnR for 6Ghz interfaces that are beaconing? That is,
> should we trace when interface start or stop beaconing (I believe !h->started is
> not enough)
> - should we track channel changes? Update RnR if interface switches away from
> 6GHz channel, or switches to 6Ghz from other band.

Yep. We should track both start/stop and channel switches. Need to update beacons in these cases.

> - would it make sense for hostapd to automatically add RnR elements for any
> beaconing 6GHz BSS to any 2.4GHz and 5GHz IEs so that user won't have to
> specify co0located interfaces in configuration? What does spec says, is RnR
> element mandatory in co-located configuration, or it is optional?

According to 802.11ax/D4.1 "26.17.2.4 Out of band discovery of a 6 GHz BSS" it is indeed mandatory:
"An AP that operates in the 2.4 GHz or 5 GHz bands and that is co-located with one or more APs that operate
in the 6 GHz band *shall* include in Beacon and Probe Response frames that it transmits a Reduced Neighbor
Report element with the Co-Located AP subfield in the TBTT Information Header subfield set to 1 to provide at
least the operating channels and operating classes of the co-located APs in the 6 GHz band"
So indeed, according to this, the configuration is not really needed.

Andrei

Patch
diff mbox series

diff --git a/hostapd/Makefile b/hostapd/Makefile
index a8d77fed36..fbf0ee8535 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -157,6 +157,7 @@  OBJS_c += ../src/utils/wpa_debug.o
 OBJS += ../src/utils/wpabuf.o
 OBJS += ../src/utils/os_$(CONFIG_OS).o
 OBJS += ../src/utils/ip_addr.o
+OBJS += ../src/utils/crc32.o
 
 OBJS += ../src/common/ieee802_11_common.o
 OBJS += ../src/common/wpa_common.o
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 21671721c0..322afe9115 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2411,6 +2411,27 @@  fail:
 }
 #endif /* CONFIG_SAE */
 
+static int parse_coloc_iface(struct hostapd_bss_config *bss, char *pos,
+				  int line)
+{
+	char **n;
+
+	if (bss->n_coloc_ifaces >= MAX_COLOC_IFACES_NUM)
+		return -1;
+
+	n = os_realloc_array(bss->coloc_ifaces,
+			     bss->n_coloc_ifaces + 1, sizeof(char *));
+	if (!n)
+		return -1;
+
+	bss->coloc_ifaces = n;
+	bss->coloc_ifaces[bss->n_coloc_ifaces] = os_strdup(pos);
+	if (!bss->coloc_ifaces[bss->n_coloc_ifaces])
+		return -1;
+	bss->n_coloc_ifaces++;
+
+	return 0;
+}
 
 #ifdef CONFIG_DPP2
 static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
@@ -4557,6 +4578,9 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 		}
 		bss->mka_psk_set |= MKA_PSK_SET_CKN;
 #endif /* CONFIG_MACSEC */
+	} else if (os_strcmp(buf, "co_located_iface") == 0) {
+		if (parse_coloc_iface(bss, pos, line) < 0)
+			return 1;
 	} else {
 		wpa_printf(MSG_ERROR,
 			   "Line %d: unknown configuration item '%s'",
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index a25d3f0092..ae33f0d5d9 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -2666,3 +2666,9 @@  own_ip_addr=127.0.0.1
 #bss=wlan0_1
 #bssid=00:13:10:95:fe:0b
 # ...
+
+# Co-located interfaces
+# A list of co-located APs. These APs will be reported in Reduced Neighbor
+# Report element in probe responses and beacons.
+#co_located_iface=wlan1
+#co_located_iface=wlan2
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 5f0f2e0da7..b371f87f99 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -788,6 +788,10 @@  void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 	}
 #endif /* CONFIG_AIRTIME_POLICY */
 
+	for (i = 0; i < conf->n_coloc_ifaces; i++)
+		os_free(conf->coloc_ifaces[i]);
+	os_free(conf->coloc_ifaces);
+
 	os_free(conf);
 }
 
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index fc6524c9e9..09e787b4c7 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -88,6 +88,7 @@  typedef enum hostap_security_policy {
 struct hostapd_ssid {
 	u8 ssid[SSID_MAX_LEN];
 	size_t ssid_len;
+	u32 short_ssid;
 	unsigned int ssid_set:1;
 	unsigned int utf8_ssid:1;
 	unsigned int wpa_passphrase_set:1;
@@ -820,6 +821,11 @@  struct hostapd_bss_config {
 	 */
 	u8 mka_psk_set;
 #endif /* CONFIG_MACSEC */
+
+#define MAX_COLOC_IFACES_NUM 16
+	/* Array of colocated interfaces */
+	char **coloc_ifaces;
+	size_t n_coloc_ifaces;
 };
 
 /**
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index c1aeb03a3d..724e1d8ca5 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -365,6 +365,78 @@  static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
 }
 
 
+/*
+ * Add Reduced Neighbor Report element to Beacons and Probe Responses
+ */
+static u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid)
+{
+	u8 *pos = eid;
+#ifdef CONFIG_FILS
+	u8 *len;
+	size_t i;
+
+	if (!hapd->conf->n_coloc_ifaces || !hapd->iface->interfaces)
+		return eid;
+
+	*pos++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+	len = pos++;
+	for (i = 0; i < hapd->conf->n_coloc_ifaces; i++) {
+		struct ieee80211_neighbor_ap_info *rnr;
+		struct hostapd_data *h =
+			hostapd_get_iface(hapd->iface->interfaces,
+					  hapd->conf->coloc_ifaces[i]);
+
+		if (!h || !h->started || !h->iface->current_mode || h == hapd)
+			continue;
+
+		rnr = (struct ieee80211_neighbor_ap_info *)pos;
+		rnr->tbtt_info_hdr = 0;
+		if (h->conf->ssid.ssid_len == hapd->conf->ssid.ssid_len &&
+		    os_memcmp(h->conf->ssid.ssid, hapd->conf->ssid.ssid,
+			      h->conf->ssid.ssid_len) == 0) {
+			rnr->tbtt_info_hdr |= RNR_TBTT_INFO_HDR_FILTERED;
+			/* TBTT offset + BSSID */
+			rnr->tbtt_info_len = 7;
+		} else {
+			/* TBTT offset + BSSID + Short SSID */
+			rnr->tbtt_info_len = 11;
+		}
+		rnr->tbtt_info_hdr |= RNR_TBTT_INFO_HDR_COLOC;
+		if (ieee80211_freq_to_channel_ext(h->iface->freq,
+						  h->iconf->secondary_channel,
+						  h->iconf->vht_oper_chwidth,
+						  &rnr->op_class,
+						  &rnr->channel) ==
+		    NUM_HOSTAPD_MODES) {
+			wpa_printf(MSG_DEBUG,
+				   "Skipping colocated iface with invalid channel configuration (%s)",
+				   hapd->conf->coloc_ifaces[i]);
+			/* It's safe to continue as pos isn't advanced yet */
+			continue;
+		}
+		rnr->neighbor_ap_tbtt_offset = 255; /* Unknown */
+		pos += sizeof(*rnr);
+		os_memcpy(pos, h->own_addr, ETH_ALEN);
+		pos += ETH_ALEN;
+
+		/* Include Short SSID if needed */
+		if (rnr->tbtt_info_len == 11) {
+			WPA_PUT_LE32(pos, h->conf->ssid.short_ssid);
+			pos += 4;
+		}
+	}
+
+	*len = pos - eid - 2;
+
+	/* don't add empty IE */
+	if (*len == 0)
+		return eid;
+#endif /* CONFIG_FILS */
+
+	return pos;
+}
+
+
 static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 				   const struct ieee80211_mgmt *req,
 				   int is_p2p, size_t *resp_len)
@@ -508,6 +580,7 @@  static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_IEEE80211AC */
 
+	pos = hostapd_eid_rnr(hapd, pos);
 	pos = hostapd_eid_fils_indic(hapd, pos, 0);
 
 #ifdef CONFIG_IEEE80211AX
@@ -1224,6 +1297,7 @@  int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_IEEE80211AC */
 
+	tailpos = hostapd_eid_rnr(hapd, tailpos);
 	tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
 
 #ifdef CONFIG_IEEE80211AX
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index c83fb2a464..5e886a44fd 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -10,6 +10,7 @@ 
 
 #include "utils/common.h"
 #include "utils/eloop.h"
+#include "utils/crc32.h"
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
 #include "common/hw_features_common.h"
@@ -1155,6 +1156,12 @@  static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
 		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
 	}
 
+	/*
+	 * Short SSID calculation is identical to FCS and it is defined in
+	 * IEEE802.11-REVmd/D2.2 9.4.2.170.3
+	 */
+	conf->ssid.short_ssid = crc32(conf->ssid.ssid, conf->ssid.ssid_len);
+
 	if (!hostapd_drv_none(hapd)) {
 		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
 			   " and ssid \"%s\"",
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index a1e11c7143..30d81dade4 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2228,4 +2228,19 @@  struct ieee80211_he_mu_edca_parameter_set {
 /* DPP Public Action frame identifiers - OUI_WFA */
 #define DPP_OUI_TYPE 0x1A
 
+#define RNR_TBTT_INFO_HDR_FILTERED BIT(2)
+#define RNR_TBTT_INFO_HDR_COLOC    BIT(3)
+#define RNR_TBTT_INFO_COUNT_OFFSET 4
+
+struct ieee80211_neighbor_ap_info {
+	u8 tbtt_info_hdr;
+	u8 tbtt_info_len;
+	u8 op_class;
+	u8 channel;
+	/* The Neighbor AP TBTT Offset subfield is always present */
+	u8 neighbor_ap_tbtt_offset;
+	/* Followed by the rest of  the TBTT Information field contents */
+	u8 data[0];
+} STRUCT_PACKED;
+
 #endif /* IEEE802_11_DEFS_H */
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 348f9015c2..ca83391174 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -891,6 +891,7 @@  OBJS += ../src/ap/utils.o
 OBJS += ../src/ap/authsrv.o
 OBJS += ../src/ap/ap_config.o
 OBJS += ../src/utils/ip_addr.o
+OBJS += ../src/utils/crc32.o
 OBJS += ../src/ap/sta_info.o
 OBJS += ../src/ap/tkip_countermeasures.o
 OBJS += ../src/ap/ap_mlme.o