diff mbox series

[v2,1/5] bss coloring: add support for handling collision events and triggering CCA

Message ID 2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com
State Superseded
Headers show
Series [v2,1/5] bss coloring: add support for handling collision events and triggering CCA | expand

Commit Message

Ryder Lee Nov. 8, 2021, 3:04 a.m. UTC
From: John Crispin <john@phrozen.org>

Add the core code for handling bss color collision events and triggering
CCA inside the kernel. The caller of hostapd_switch_color() will be added
in the following commits.

Tested-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
changes since v2 -
- use os_get_reltime and os_reltime instead.
- use bool cca_in_progress.
- use random BSS color to avoid hardcoded BSS color value of 1.
- modify comment for DOT11BSS_COLOR_COLLISION_AP_PERIOD.
- add a note for collision behavior.
- fix compiler warnings.
- Be clear in the commit message regarding hostapd_switch_color().
---
 src/ap/ap_drv_ops.h          |  12 ++++
 src/ap/hostapd.c             | 134 ++++++++++++++++++++++++++++++++++-
 src/ap/hostapd.h             |  16 +++++
 src/common/ieee802_11_defs.h |   6 ++
 src/drivers/driver.h         |  31 ++++++++
 5 files changed, 198 insertions(+), 1 deletion(-)

Comments

Ryder Lee Jan. 19, 2022, 7:20 a.m. UTC | #1
On Sun, 2021-11-07 at 19:04 -0800, Ryder Lee wrote:
> From: John Crispin <john@phrozen.org>
> 
> Add the core code for handling bss color collision events and
> triggering
> CCA inside the kernel. The caller of hostapd_switch_color() will be
> added
> in the following commits.
> 
> Tested-by: Peter Chiu <chui-hao.chiu@mediatek.com>
> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: John Crispin <john@phrozen.org>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
> changes since v2 -
> - use os_get_reltime and os_reltime instead.
> - use bool cca_in_progress.
> - use random BSS color to avoid hardcoded BSS color value of 1.
> - modify comment for DOT11BSS_COLOR_COLLISION_AP_PERIOD.
> - add a note for collision behavior.
> - fix compiler warnings.
> - Be clear in the commit message regarding hostapd_switch_color().
> ---

Hi Jouni,

Just a gentle ping as this series has been posted over two months. Our
plan is add CCA into Assoc frames (kernel change first) after this
series get accepted. 

Ryder
diff mbox series

Patch

diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 61c8f64eb..003f0daf7 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -299,6 +299,18 @@  static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
 	return hapd->driver->switch_channel(hapd->drv_priv, settings);
 }
 
+#ifdef CONFIG_IEEE80211AX
+static inline int hostapd_drv_switch_color(struct hostapd_data *hapd,
+					   struct cca_settings *settings)
+{
+	if (hapd->driver == NULL || hapd->driver->switch_color == NULL ||
+	    hapd->drv_priv == NULL)
+		return -1;
+
+	return hapd->driver->switch_color(hapd->drv_priv, settings);
+}
+#endif
+
 static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
 				     size_t buflen)
 {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 913a8e29e..4ec3ee62d 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -66,7 +66,10 @@  static int setup_interface2(struct hostapd_iface *iface);
 static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
 static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
 						    void *timeout_ctx);
-
+#ifdef CONFIG_IEEE80211AX
+static void
+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx);
+#endif
 
 int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
 			       int (*cb)(struct hostapd_iface *iface,
@@ -462,6 +465,9 @@  void hostapd_free_hapd_data(struct hostapd_data *hapd)
 	}
 	eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL);
 #endif /* CONFIG_SAE */
+#ifdef CONFIG_IEEE80211AX
+	eloop_cancel_timeout(hostapd_switch_color_timeout_handler, hapd, NULL);
+#endif
 }
 
 
@@ -3691,6 +3697,132 @@  hostapd_switch_channel_fallback(struct hostapd_iface *iface,
 	hostapd_enable_iface(iface);
 }
 
+
+#ifdef CONFIG_IEEE80211AX
+void hostapd_cleanup_cca_params(struct hostapd_data *hapd)
+{
+	hapd->cca_count = 0;
+	hapd->cca_color = 0;
+	hapd->cca_c_off_beacon = 0;
+	hapd->cca_c_off_proberesp = 0;
+	hapd->cca_in_progress = false;
+}
+
+
+static int hostapd_fill_cca_settings(struct hostapd_data *hapd,
+				     struct cca_settings *settings)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	u8 old_color;
+	int ret;
+
+	if (!iface || iface->conf->he_op.he_bss_color_disabled)
+		return -1;
+
+        old_color = iface->conf->he_op.he_bss_color;
+	iface->conf->he_op.he_bss_color = hapd->cca_color;
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
+	iface->conf->he_op.he_bss_color = old_color;
+
+	settings->cca_count = hapd->cca_count;
+	settings->cca_color = hapd->cca_color,
+	hapd->cca_in_progress = true;
+
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_cca);
+	if (ret) {
+		free_beacon_data(&settings->beacon_after);
+		return ret;
+	}
+
+	settings->counter_offset_beacon = hapd->cca_c_off_beacon;
+	settings->counter_offset_presp = hapd->cca_c_off_proberesp;
+
+	return 0;
+}
+
+
+static void
+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx)
+{
+	struct hostapd_data *hapd = (struct hostapd_data *) eloop_data;
+	struct cca_settings settings;
+	struct os_reltime now;
+	unsigned int b;
+	int i, r, ret;
+
+	if (os_get_reltime(&now))
+		return;
+
+	/* 10s window is the approximate margin of collision persistent
+	 * as an initial implementation. CCA can only be triggered once
+	 * handler constantly receives collision events to update the
+	 * last_color_collision.sec. How does it work -
+	 *
+	 * 1. BSS color collision persistent for at least 50 seconds.
+	 * 2. The BSS Color Disabled subfield is set to 1.
+	 * 3. CCA.
+	 *
+	 * TODO: implement other 'persistent' computation methods.
+	 */
+	if (now.sec - hapd->last_color_collision.sec >= 10)
+		return;
+
+	r = os_random() % HE_OPERATION_BSS_COLOR_MAX;
+	for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
+		if (r && (hapd->color_collision_bitmap & (1 << r)) == 0)
+			break;
+		r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX;
+	}
+
+	if (i == HE_OPERATION_BSS_COLOR_MAX) {
+		/* there are no free colors so turn bss coloring off */
+		wpa_printf(MSG_INFO, "no free colors left, turning of BSS coloring");
+		hapd->iface->conf->he_op.he_bss_color_disabled = 1;
+		hapd->iface->conf->he_op.he_bss_color = os_random() % 63 + 1;
+		for (b = 0; b < hapd->iface->num_bss; b++)
+			ieee802_11_set_beacon(hapd->iface->bss[b]);
+		return;
+	}
+
+	for (b = 0; b < hapd->iface->num_bss; b++) {
+		struct hostapd_data *bss = hapd->iface->bss[b];
+
+		hostapd_cleanup_cca_params(bss);
+		bss->cca_color = r;
+		bss->cca_count = 10;
+
+		if (hostapd_fill_cca_settings(bss, &settings)) {
+			hostapd_cleanup_cca_params(bss);
+			continue;
+		}
+
+		ret = hostapd_drv_switch_color(bss, &settings);
+		free_beacon_data(&settings.beacon_cca);
+		free_beacon_data(&settings.beacon_after);
+
+		if (ret)
+			hostapd_cleanup_cca_params(bss);
+	}
+}
+
+
+void
+hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap)
+{
+	if (hapd->cca_in_progress)
+		return;
+
+	if (os_get_reltime(&hapd->last_color_collision))
+		return;
+
+	hapd->color_collision_bitmap = bitmap;
+
+	if (!eloop_is_timeout_registered(hostapd_switch_color_timeout_handler, hapd, NULL))
+		eloop_register_timeout(DOT11BSS_COLOR_COLLISION_AP_PERIOD, 0,
+				       hostapd_switch_color_timeout_handler, hapd, NULL);
+}
+#endif
+
 #endif /* NEED_AP_MLME */
 
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 07d0aaa92..70ae05291 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -292,6 +292,16 @@  struct hostapd_data {
 	unsigned int cs_c_off_ecsa_beacon;
 	unsigned int cs_c_off_ecsa_proberesp;
 
+#ifdef CONFIG_IEEE80211AX
+	bool cca_in_progress;
+	u8 cca_count;
+	u8 cca_color;
+	unsigned int cca_c_off_beacon;
+	unsigned int cca_c_off_proberesp;
+	struct os_reltime last_color_collision;
+	u64 color_collision_bitmap;
+#endif
+
 #ifdef CONFIG_P2P
 	struct p2p_data *p2p;
 	struct p2p_group *p2p_group;
@@ -645,6 +655,12 @@  void hostapd_periodic_iface(struct hostapd_iface *iface);
 int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
 void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
 
+
+#ifdef CONFIG_IEEE80211AX
+void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
+void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
+#endif
+
 /* utils.c */
 int hostapd_register_probereq_cb(struct hostapd_data *hapd,
 				 int (*cb)(void *ctx, const u8 *sa,
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 24dbfa8bd..adb89d111 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2305,6 +2305,7 @@  struct ieee80211_spatial_reuse {
 #define HE_OPERATION_BSS_COLOR_PARTIAL		((u32) BIT(30))
 #define HE_OPERATION_BSS_COLOR_DISABLED		((u32) BIT(31))
 #define HE_OPERATION_BSS_COLOR_OFFSET		24
+#define HE_OPERATION_BSS_COLOR_MAX		64
 
 /* Spatial Reuse defines */
 #define SPATIAL_REUSE_SRP_DISALLOWED		BIT(0)
@@ -2450,6 +2451,11 @@  enum mscs_description_subelem {
  */
 #define FD_MAX_INTERVAL_6GHZ                  20 /* TUs */
 
+/* IEEE802.11/D6.0 - 26.17.3.5.1, AP needs to wait and see the collision
+ * persists for at least the minimum default timeout
+ */
+#define DOT11BSS_COLOR_COLLISION_AP_PERIOD	50
+
 /* Protected Vendor-specific QoS Management Action frame identifiers - WFA */
 #define QM_ACTION_VENDOR_TYPE 0x506f9a1a
 #define QM_ACTION_OUI_TYPE 0x1a
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2020184c5..f762ccccc 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2395,6 +2395,26 @@  struct csa_settings {
 	u16 counter_offset_presp[2];
 };
 
+/**
+ * struct cca_settings - Settings for color switch command
+ * @cca_count: Count in Beacon frames (TBTT) to perform the switch
+ * @cca_color: The new color that we are switching to
+ * @beacon_cca: Beacon/probe resp/asooc resp info for color switch period
+ * @beacon_after: Next beacon/probe resp/asooc resp info
+ * @counter_offset_beacon: Offset to the count field in beacon's tail
+ * @counter_offset_presp: Offset to the count field in probe resp.
+ */
+struct cca_settings {
+	u8 cca_count;
+	u8 cca_color;
+
+	struct beacon_data beacon_cca;
+	struct beacon_data beacon_after;
+
+	u16 counter_offset_beacon;
+	u16 counter_offset_presp;
+};
+
 /* TDLS peer capabilities for send_tdls_mgmt() */
 enum tdls_peer_capability {
 	TDLS_PEER_HT = BIT(0),
@@ -3977,6 +3997,17 @@  struct wpa_driver_ops {
 	 */
 	int (*switch_channel)(void *priv, struct csa_settings *settings);
 
+	/**
+	 * switch_color - Announce color switch and migrate the BSS to the
+	 * given color
+	 * @priv: Private driver interface data
+	 * @settings: Settings for CCA period and new color
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to move the BSS to its new color.
+	 */
+	int (*switch_color)(void *priv, struct cca_settings *settings);
+
 	/**
 	 * add_tx_ts - Add traffic stream
 	 * @priv: Private driver interface data