diff mbox series

CSA MBSS: CHAN_SWITCH is always failing.

Message ID 20231012211203.529730-1-gasmibal@gmail.com
State New
Headers show
Series CSA MBSS: CHAN_SWITCH is always failing. | expand

Commit Message

Baligh GASMI Oct. 12, 2023, 9:12 p.m. UTC
When asking hostapd to switch channel in the multi-BSS configuration,
only the first (associated to the first BSS) request is executed
correctly by some driver, other BSS's request are failing.
This is because multi-BSS configuration is using same Radio and one
request seems to be suffisant to driver to switch on.

Solution in here is to return SUCCESS if there was at least one BSS
switched OK.

Signed-off-by: Baligh Gasmi <gasmibal@gmail.com>
---
 hostapd/ctrl_iface.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Comments

Benjamin Berg Oct. 13, 2023, 9:31 a.m. UTC | #1
Hi,

On Thu, 2023-10-12 at 23:12 +0200, Baligh Gasmi wrote:
> When asking hostapd to switch channel in the multi-BSS configuration,
> only the first (associated to the first BSS) request is executed
> correctly by some driver, other BSS's request are failing.
> This is because multi-BSS configuration is using same Radio and one
> request seems to be suffisant to driver to switch on.
> 
> Solution in here is to return SUCCESS if there was at least one BSS
> switched OK.

I think this solution may confuse the internal state a bit as
hostapd_switch_channel resets some state on failure and also sets
csa_in_progress on success.

I am thinking right now that two things might make sense:
   1. Either splitting channel switch into three steps, or always
      switching the BSSs together.
   2. Only doing a single call to the driver interface with the
      information for all BSSs. After all, the switch will need to
      happen at the same point in time.

But, I don't really know right now what underlying drivers are
expecting, so maybe the suggestion is just wrong. Another solution
could be that the driver detects that the switch is already in progress
and ensures a success return if appropriate.

Benjamin

> 
> Signed-off-by: Baligh Gasmi <gasmibal@gmail.com>
> ---
>  hostapd/ctrl_iface.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
> index f90eb22c4..cf3d65172 100644
> --- a/hostapd/ctrl_iface.c
> +++ b/hostapd/ctrl_iface.c
> @@ -2694,6 +2694,8 @@ static int
> hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
>                 return 0;
>         }
>  
> +       int one_success = 0;
> +       int last_fail = ret;
>         for (i = 0; i < iface->num_bss; i++) {
>  
>                 /* Save CHAN_SWITCH VHT, HE, and EHT config */
> @@ -2704,11 +2706,13 @@ static int
> hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
>                 if (ret) {
>                         /* FIX: What do we do if CSA fails in the
> middle of
>                          * submitting multi-BSS CSA requests? */
> -                       return ret;
> +                       last_fail = ret;
> +               } else {
> +                       one_success = 1;
>                 }
>         }
>  
> -       return 0;
> +       return one_success ? 0 : last_fail;
>  #else /* NEED_AP_MLME */
>         return -1;
>  #endif /* NEED_AP_MLME */
Baligh GASMI Oct. 13, 2023, 10:07 a.m. UTC | #2
>
> Hi,
>
> On Thu, 2023-10-12 at 23:12 +0200, Baligh Gasmi wrote:
> > When asking hostapd to switch channel in the multi-BSS configuration,
> > only the first (associated to the first BSS) request is executed
> > correctly by some driver, other BSS's request are failing.
> > This is because multi-BSS configuration is using same Radio and one
> > request seems to be suffisant to driver to switch on.
> >
> > Solution in here is to return SUCCESS if there was at least one BSS
> > switched OK.
>
> I think this solution may confuse the internal state a bit as
> hostapd_switch_channel resets some state on failure and also sets
> csa_in_progress on success.
>
> I am thinking right now that two things might make sense:
>    1. Either splitting channel switch into three steps, or always
>       switching the BSSs together.
>    2. Only doing a single call to the driver interface with the
>       information for all BSSs. After all, the switch will need to
>       happen at the same point in time.
>
> But, I don't really know right now what underlying drivers are
> expecting, so maybe the suggestion is just wrong. Another solution
> could be that the driver detects that the switch is already in progress
> and ensures a success return if appropriate.
>
> Benjamin
>

Hello,

Sorry, but I do not get it!
I'm not saying that the patch is correct or to be used as it, trying
just to understand.

With the patch, when hostapd_switch_channel() fails, that means that
no switch on any BSS has succussed, so may the reset of the state is
coherent.
Other way, if it successed with one BSS (some or all), that means that
the CSA is ongoing, and having csa_in_progress is coherent too.

I can think about adding CHAN_SWITCH argument, according to which we
use all BSSes or only the main BSS, but still not global solution I
think, since we will have to detect driver behaviour to add/remove new
arg.

Baligh
Benjamin Berg Oct. 13, 2023, 10:14 a.m. UTC | #3
On Fri, 2023-10-13 at 12:07 +0200, Baligh GASMI wrote:
> > 
> > Hi,
> > 
> > On Thu, 2023-10-12 at 23:12 +0200, Baligh Gasmi wrote:
> > > When asking hostapd to switch channel in the multi-BSS
> > > configuration,
> > > only the first (associated to the first BSS) request is executed
> > > correctly by some driver, other BSS's request are failing.
> > > This is because multi-BSS configuration is using same Radio and
> > > one
> > > request seems to be suffisant to driver to switch on.
> > > 
> > > Solution in here is to return SUCCESS if there was at least one
> > > BSS
> > > switched OK.
> > 
> > I think this solution may confuse the internal state a bit as
> > hostapd_switch_channel resets some state on failure and also sets
> > csa_in_progress on success.
> > 
> > I am thinking right now that two things might make sense:
> >    1. Either splitting channel switch into three steps, or always
> >       switching the BSSs together.
> >    2. Only doing a single call to the driver interface with the
> >       information for all BSSs. After all, the switch will need to
> >       happen at the same point in time.
> > 
> > But, I don't really know right now what underlying drivers are
> > expecting, so maybe the suggestion is just wrong. Another solution
> > could be that the driver detects that the switch is already in
> > progress
> > and ensures a success return if appropriate.
> > 
> > Benjamin
> > 
> 
> Hello,
> 
> Sorry, but I do not get it!
> I'm not saying that the patch is correct or to be used as it, trying
> just to understand.
> 
> With the patch, when hostapd_switch_channel() fails, that means that
> no switch on any BSS has succussed, so may the reset of the state is
> coherent.
> Other way, if it successed with one BSS (some or all), that means that
> the CSA is ongoing, and having csa_in_progress is coherent too.

I was talking about the internal hostapd state. i.e.:

int hostapd_switch_channel(struct hostapd_data *hapd,
			   struct csa_settings *settings)
{
	int ret;
...
	ret = hostapd_drv_switch_channel(hapd, settings);
	free_beacon_data(&settings->beacon_csa);
	free_beacon_data(&settings->beacon_after);

	if (ret) {
		/* if we failed, clean cs parameters */
		hostapd_cleanup_cs_params(hapd);
		return ret;
	}

	hapd->csa_in_progress = 1;
	return 0;
}

If hostapd_drv_switch_channel fails (which you expect to happen), then
csa_in_progress is not set to 1 and hostapd_cleanup_cs_params is
called.

Both of this seem like an undesired side-effect.

Benjamin

> 
> I can think about adding CHAN_SWITCH argument, according to which we
> use all BSSes or only the main BSS, but still not global solution I
> think, since we will have to detect driver behaviour to add/remove
> new
> arg.
> 
> Baligh
>
Baligh GASMI Oct. 13, 2023, 10:33 a.m. UTC | #4
>
> On Fri, 2023-10-13 at 12:07 +0200, Baligh GASMI wrote:
> > >
> > > Hi,
> > >
> > > On Thu, 2023-10-12 at 23:12 +0200, Baligh Gasmi wrote:
> > > > When asking hostapd to switch channel in the multi-BSS
> > > > configuration,
> > > > only the first (associated to the first BSS) request is executed
> > > > correctly by some driver, other BSS's request are failing.
> > > > This is because multi-BSS configuration is using same Radio and
> > > > one
> > > > request seems to be suffisant to driver to switch on.
> > > >
> > > > Solution in here is to return SUCCESS if there was at least one
> > > > BSS
> > > > switched OK.
> > >
> > > I think this solution may confuse the internal state a bit as
> > > hostapd_switch_channel resets some state on failure and also sets
> > > csa_in_progress on success.
> > >
> > > I am thinking right now that two things might make sense:
> > >    1. Either splitting channel switch into three steps, or always
> > >       switching the BSSs together.
> > >    2. Only doing a single call to the driver interface with the
> > >       information for all BSSs. After all, the switch will need to
> > >       happen at the same point in time.
> > >
> > > But, I don't really know right now what underlying drivers are
> > > expecting, so maybe the suggestion is just wrong. Another solution
> > > could be that the driver detects that the switch is already in
> > > progress
> > > and ensures a success return if appropriate.
> > >
> > > Benjamin
> > >
> >
> > Hello,
> >
> > Sorry, but I do not get it!
> > I'm not saying that the patch is correct or to be used as it, trying
> > just to understand.
> >
> > With the patch, when hostapd_switch_channel() fails, that means that
> > no switch on any BSS has succussed, so may the reset of the state is
> > coherent.
> > Other way, if it successed with one BSS (some or all), that means that
> > the CSA is ongoing, and having csa_in_progress is coherent too.
>
> I was talking about the internal hostapd state. i.e.:
>
> int hostapd_switch_channel(struct hostapd_data *hapd,
>                            struct csa_settings *settings)
> {
>         int ret;
> ...
>         ret = hostapd_drv_switch_channel(hapd, settings);
>         free_beacon_data(&settings->beacon_csa);
>         free_beacon_data(&settings->beacon_after);
>
>         if (ret) {
>                 /* if we failed, clean cs parameters */
>                 hostapd_cleanup_cs_params(hapd);
>                 return ret;
>         }
>
>         hapd->csa_in_progress = 1;
>         return 0;
> }
>
> If hostapd_drv_switch_channel fails (which you expect to happen), then
> csa_in_progress is not set to 1 and hostapd_cleanup_cs_params is
> called.

csa_in_progress is per BSS, so if the driver fails on one BSS, it will
not impact other.
right?

>
>
> Both of this seem like an undesired side-effect.
>
> Benjamin
>
> >
> > I can think about adding CHAN_SWITCH argument, according to which we
> > use all BSSes or only the main BSS, but still not global solution I
> > think, since we will have to detect driver behaviour to add/remove
> > new
> > arg.
> >
> > Baligh
> >
>
Benjamin Berg Oct. 13, 2023, 1 p.m. UTC | #5
Hi,

On Fri, 2023-10-13 at 12:33 +0200, Baligh GASMI wrote:
> > > [SNIP]
> > 
> > I was talking about the internal hostapd state. i.e.:
> > 
> > int hostapd_switch_channel(struct hostapd_data *hapd,
> >                            struct csa_settings *settings)
> > {
> >         int ret;
> > ...
> >         ret = hostapd_drv_switch_channel(hapd, settings);
> >         free_beacon_data(&settings->beacon_csa);
> >         free_beacon_data(&settings->beacon_after);
> > 
> >         if (ret) {
> >                 /* if we failed, clean cs parameters */
> >                 hostapd_cleanup_cs_params(hapd);
> >                 return ret;
> >         }
> > 
> >         hapd->csa_in_progress = 1;
> >         return 0;
> > }
> > 
> > If hostapd_drv_switch_channel fails (which you expect to happen), then
> > csa_in_progress is not set to 1 and hostapd_cleanup_cs_params is
> > called.
> 
> csa_in_progress is per BSS, so if the driver fails on one BSS, it will
> not impact other.
> right?

Yes, csa_in_progress would be set for the first BSS and not the others.
I guess hapd_csa_in_progress actually checks all BSSs, so things might
work fine for the most part?

It may be acceptable to ignore the error on the other BSSs (at least if
they are non-transmitting ones, otherwise we might need to update the
beacon?). I don't want to comment on whether that is right or not.

It just doesn't sit quite right to me to ignore the error in this way.
If simply ignoring it is what you want to do, then wouldn't it be
possible to do so inside the driver code?

Benjamin

> > 
> > 
> > Both of this seem like an undesired side-effect.
> > 
> > Benjamin
> > 
> > > 
> > > I can think about adding CHAN_SWITCH argument, according to which
> > > we
> > > use all BSSes or only the main BSS, but still not global solution
> > > I
> > > think, since we will have to detect driver behaviour to
> > > add/remove
> > > new
> > > arg.
> > > 
> > > Baligh
> > > 
> > 
>
Baligh GASMI Feb. 20, 2024, 8:49 p.m. UTC | #6
Hello,

It appears that a similar patch has already been applied."

Thanks.

Le ven. 13 oct. 2023 à 15:00, Benjamin Berg
<benjamin@sipsolutions.net> a écrit :
>
> Hi,
>
> On Fri, 2023-10-13 at 12:33 +0200, Baligh GASMI wrote:
> > > > [SNIP]
> > >
> > > I was talking about the internal hostapd state. i.e.:
> > >
> > > int hostapd_switch_channel(struct hostapd_data *hapd,
> > >                            struct csa_settings *settings)
> > > {
> > >         int ret;
> > > ...
> > >         ret = hostapd_drv_switch_channel(hapd, settings);
> > >         free_beacon_data(&settings->beacon_csa);
> > >         free_beacon_data(&settings->beacon_after);
> > >
> > >         if (ret) {
> > >                 /* if we failed, clean cs parameters */
> > >                 hostapd_cleanup_cs_params(hapd);
> > >                 return ret;
> > >         }
> > >
> > >         hapd->csa_in_progress = 1;
> > >         return 0;
> > > }
> > >
> > > If hostapd_drv_switch_channel fails (which you expect to happen), then
> > > csa_in_progress is not set to 1 and hostapd_cleanup_cs_params is
> > > called.
> >
> > csa_in_progress is per BSS, so if the driver fails on one BSS, it will
> > not impact other.
> > right?
>
> Yes, csa_in_progress would be set for the first BSS and not the others.
> I guess hapd_csa_in_progress actually checks all BSSs, so things might
> work fine for the most part?
>
> It may be acceptable to ignore the error on the other BSSs (at least if
> they are non-transmitting ones, otherwise we might need to update the
> beacon?). I don't want to comment on whether that is right or not.
>
> It just doesn't sit quite right to me to ignore the error in this way.
> If simply ignoring it is what you want to do, then wouldn't it be
> possible to do so inside the driver code?
>
> Benjamin
>
> > >
> > >
> > > Both of this seem like an undesired side-effect.
> > >
> > > Benjamin
> > >
> > > >
> > > > I can think about adding CHAN_SWITCH argument, according to which
> > > > we
> > > > use all BSSes or only the main BSS, but still not global solution
> > > > I
> > > > think, since we will have to detect driver behaviour to
> > > > add/remove
> > > > new
> > > > arg.
> > > >
> > > > Baligh
> > > >
> > >
> >
>
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index f90eb22c4..cf3d65172 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2694,6 +2694,8 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 		return 0;
 	}
 
+	int one_success = 0;
+	int last_fail = ret;
 	for (i = 0; i < iface->num_bss; i++) {
 
 		/* Save CHAN_SWITCH VHT, HE, and EHT config */
@@ -2704,11 +2706,13 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 		if (ret) {
 			/* FIX: What do we do if CSA fails in the middle of
 			 * submitting multi-BSS CSA requests? */
-			return ret;
+			last_fail = ret;
+		} else {
+			one_success = 1;
 		}
 	}
 
-	return 0;
+	return one_success ? 0 : last_fail;
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */