diff mbox series

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

Message ID 20200826062216.1104150-2-john@phrozen.org
State Changes Requested
Headers show
Series bss coloring: add support | expand

Commit Message

John Crispin Aug. 26, 2020, 6:22 a.m. UTC
Add the core code for handling bss color collision events and triggering
CCA inside the kernel.

Signed-off-by: John Crispin <john@phrozen.org>
---
 src/ap/ap_drv_ops.h          |  12 ++++
 src/ap/hostapd.c             | 119 +++++++++++++++++++++++++++++++++++
 src/ap/hostapd.h             |  16 +++++
 src/common/ieee802_11_defs.h |   6 ++
 src/drivers/driver.h         |  31 +++++++++
 5 files changed, 184 insertions(+)

Comments

Karthikeyan periyasamy Sept. 1, 2020, 4:52 a.m. UTC | #1
> +
> +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_time now;
> +	int i, r, b, ret;
> +
> +	if (os_get_time(&now))
> +		return;
> +
> +	/* check if there has been a recent collision */
> +	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 = 1;

Why don't we retain the previous color instead of going to the color "1" 
while disabled the bss color ?

Thanks,
Karthikeyan P.
John Crispin Sept. 1, 2020, 7:11 a.m. UTC | #2
On 01.09.20 06:52, Karthikeyan periyasamy wrote:
>
>> +
>> +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_time now;
>> +    int i, r, b, ret;
>> +
>> +    if (os_get_time(&now))
>> +        return;
>> +
>> +    /* check if there has been a recent collision */
>> +    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 = 1;
>
> Why don't we retain the previous color instead of going to the color 
> "1" while disabled the bss color ?
>
> Thanks,
> Karthikeyan P.
>
this is the default when coloring is disabled. There were inter-op 
issues when setting it to 0

     John
Karthikeyan periyasamy Sept. 4, 2020, 4:24 a.m. UTC | #3
> +
> +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_time now;
> +	int i, r, b, ret;
> +
> +	if (os_get_time(&now))
> +		return;
> +
> +	/* check if there has been a recent collision */
> +	if (now.sec - hapd->last_color_collision.sec >= 10)
> +		return;
> +

Why we are dropping CCA when there is no collision for more than 10 
secs.

As per the 802.11ax draft 6.0, AP need to wait and see the collision 
persists for a duration of at least dot11BSSColorCollisionAPPeriod 
(Default minimum value is 50 seconds).
in that case, if there is no collision for at least 
dot11BSSColorCollisionAPPeriod (Default minimum value is 50 seconds) 
then only we have to drop the CCA. right?

> +	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 = 1;
> +		for (b = 0; b < hapd->iface->num_bss; b++)
> +			ieee802_11_set_beacon(hapd->iface->bss[b]);
> +		return;
> +	}
> +

Thanks,
Karthikeyan P.
John Crispin Sept. 4, 2020, 4:41 a.m. UTC | #4
On 04.09.20 06:24, Karthikeyan periyasamy wrote:
>> +
>> +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_time now;
>> +    int i, r, b, ret;
>> +
>> +    if (os_get_time(&now))
>> +        return;
>> +
>> +    /* check if there has been a recent collision */
>> +    if (now.sec - hapd->last_color_collision.sec >= 10)
>> +        return;
>> +
>
> Why we are dropping CCA when there is no collision for more than 10 secs.
>
> As per the 802.11ax draft 6.0, AP need to wait and see the collision 
> persists for a duration of at least dot11BSSColorCollisionAPPeriod 
> (Default minimum value is 50 seconds).
> in that case, if there is no collision for at least 
> dot11BSSColorCollisionAPPeriod (Default minimum value is 50 seconds) 
> then only we have to drop the CCA. right?
>
>> +    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 = 1;
>> +        for (b = 0; b < hapd->iface->num_bss; b++)
>> +            ieee802_11_set_beacon(hapd->iface->bss[b]);
>> +        return;
>> +    }
>> +
>
> Thanks,
> Karthikeyan P.
>
correct, that should be > 50

     John
diff mbox series

Patch

diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 651b77e9a..44e010f1e 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 24ec082bf..0d44852f0 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -66,6 +66,8 @@  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);
+static void
+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx);
 
 
 int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
@@ -476,6 +478,9 @@  static 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
 }
 
 
@@ -3661,6 +3666,120 @@  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 = 0;
+}
+
+
+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 = 1;
+
+	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_time now;
+	int i, r, b, ret;
+
+	if (os_get_time(&now))
+		return;
+
+	/* check if there has been a recent collision */
+	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 = 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_time(&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 44d2c6068..19dcd1b51 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
+	int cca_in_progress;
+	u8 cca_count;
+	u8 cca_color;
+	unsigned int cca_c_off_beacon;
+	unsigned int cca_c_off_proberesp;
+	struct os_time last_color_collision;
+	u64 color_collision_bitmap;
+#endif
+
 #ifdef CONFIG_P2P
 	struct p2p_data *p2p;
 	struct p2p_group *p2p_group;
@@ -636,6 +646,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 7d1287763..5b834c5c8 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2265,6 +2265,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)
@@ -2342,4 +2343,9 @@  enum edmg_bw_config {
 /* DPP Public Action frame identifiers - OUI_WFA */
 #define DPP_OUI_TYPE 0x1A
 
+/* IEEE802.11/D6.0 - 26.17.3.5.1
+ * the minimum default timeout between color collision and color change is defined as 50s
+ */
+#define DOT11BSS_COLOR_COLLISION_AP_PERIOD	50
+
 #endif /* IEEE802_11_DEFS_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 1cc8ad37d..3223dc781 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2338,6 +2338,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),
@@ -3909,6 +3929,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