diff mbox series

[v4,03/15] mbssid: configure all BSSes before beacon setup

Message ID 20221201031847.26480-4-quic_alokad@quicinc.com
State Accepted
Headers show
Series v4: MBSSID and EMA support | expand

Commit Message

Aloka Dixit Dec. 1, 2022, 3:18 a.m. UTC
When multiple BSSID advertisements feature is enabled in 802.11ax
mode or later, beacons are not transmitted per interface, instead
only one of the interfaces transmits beacon(s) which include one
or more multiple BSSID elements with configuration for the remaining
interfaces on the same radio.

Change the existing logic such that all configuration details for
all the interfaces is available while building the beacon for the
transmitting interface itself.

Do not change the flow for the cases where multiple BSSID advertisements
are not enabled.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
---
 src/ap/hostapd.c | 49 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 8 deletions(-)

Comments

Jouni Malinen Dec. 2, 2022, 5:03 p.m. UTC | #1
On Wed, Nov 30, 2022 at 07:18:35PM -0800, Aloka Dixit wrote:
> When multiple BSSID advertisements feature is enabled in 802.11ax
> mode or later, beacons are not transmitted per interface, instead
> only one of the interfaces transmits beacon(s) which include one
> or more multiple BSSID elements with configuration for the remaining
> interfaces on the same radio.
> 
> Change the existing logic such that all configuration details for
> all the interfaces is available while building the beacon for the
> transmitting interface itself.
> 
> Do not change the flow for the cases where multiple BSSID advertisements
> are not enabled.

This actually does change the code sequence for existing cases and that
breaks things..

> diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
>  
> +static int hostapd_start_beacon(struct hostapd_data *hapd)
> +{
> +	struct hostapd_bss_config *conf = hapd->conf;
> +
> +	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
> +		return -1;

This is where the ieee802_11_set_beacon() call is moved..

> @@ -1399,9 +1417,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
>  		return -1;
>  	}
>  
> -	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
> -		return -1;

.. and this is where it is moved from..

>  	if (flush_old_stations && !conf->start_disabled &&
>  	    conf->broadcast_deauth) {
>  		u8 addr[ETH_ALEN];

In other words, this operation of sending the broadcast Deauthentication
frame would now be before the call to ieee802_11_set_beacon() and this
fails due to cfg80211/mac80211 constraints in AP mode.

I guess it would be fine to move this broadcast Deauthentication frame
item to hostapd_start_beacon() with the other two moved items so that
they remain in the same order.
diff mbox series

Patch

diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index e82f135960cb..e3ddcb9f54cc 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1114,19 +1114,37 @@  static int db_table_create_radius_attributes(sqlite3 *db)
 
 #endif /* CONFIG_NO_RADIUS */
 
+static int hostapd_start_beacon(struct hostapd_data *hapd)
+{
+	struct hostapd_bss_config *conf = hapd->conf;
+
+	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+		return -1;
+
+	if (hapd->driver && hapd->driver->set_operstate)
+		hapd->driver->set_operstate(hapd->drv_priv, 1);
+
+	return 0;
+}
 
 /**
  * hostapd_setup_bss - Per-BSS setup (initialization)
  * @hapd: Pointer to BSS data
  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
  *	but interface may exist
+ * @start_beacon: Whether beacons should be configured and transmission started
+ *	at this time. This is used when MBSSID IE is enabled where the
+ *	information regarding all BSSes should be retrieved before configuring
+ *	the beacons. The calling functions are responsible to configure the
+ *	beacon explicitly if this is set to 'false'.
  *
  * This function is used to initialize all per-BSS data structures and
  * resources. This gets called in a loop for each BSS when an interface is
  * initialized. Most of the modules that are initialized here will be
  * deinitialized in hostapd_cleanup().
  */
-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
+			     bool start_beacon)
 {
 	struct hostapd_bss_config *conf = hapd->conf;
 	u8 ssid[SSID_MAX_LEN + 1];
@@ -1399,9 +1417,6 @@  static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
 		return -1;
 	}
 
-	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
-		return -1;
-
 	if (flush_old_stations && !conf->start_disabled &&
 	    conf->broadcast_deauth) {
 		u8 addr[ETH_ALEN];
@@ -1420,8 +1435,8 @@  static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
 		return -1;
 
-	if (hapd->driver && hapd->driver->set_operstate)
-		hapd->driver->set_operstate(hapd->drv_priv, 1);
+	if (start_beacon)
+		return hostapd_start_beacon(hapd);
 
 	return 0;
 }
@@ -2146,7 +2161,7 @@  static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 		hapd = iface->bss[j];
 		if (j)
 			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
-		if (hostapd_setup_bss(hapd, j == 0)) {
+		if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
 			for (;;) {
 				hapd = iface->bss[j];
 				hostapd_bss_deinit_no_free(hapd);
@@ -2160,6 +2175,24 @@  static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 		if (is_zero_ether_addr(hapd->conf->bssid))
 			prev_addr = hapd->own_addr;
 	}
+
+	if (hapd->iconf->mbssid) {
+		for (j = 0; j < iface->num_bss; j++) {
+			hapd = iface->bss[j];
+			if (hostapd_start_beacon(hapd)) {
+				for (;;) {
+					hapd = iface->bss[j];
+					hostapd_bss_deinit_no_free(hapd);
+					hostapd_free_hapd_data(hapd);
+					if (j == 0)
+						break;
+					j--;
+				}
+				goto fail;
+			}
+		}
+	}
+
 	hapd = iface->bss[0];
 
 	hostapd_tx_queue_params(iface);
@@ -3056,7 +3089,7 @@  int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
 
 			if (start_ctrl_iface_bss(hapd) < 0 ||
 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
-			     hostapd_setup_bss(hapd, -1))) {
+			     hostapd_setup_bss(hapd, -1, true))) {
 				hostapd_cleanup(hapd);
 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
 				hapd_iface->conf->num_bss--;