mbox series

[RFC,v3,0/2] cfg80211: fix duplicated scan entries after channel switch

Message ID 20190710173651.15770-1-sergey.matyukevich.os@quantenna.com (mailing list archive)
Headers show
Series cfg80211: fix duplicated scan entries after channel switch | expand

Message

Sergey Matyukevich July 10, 2019, 5:36 p.m. UTC
Hi Johannes and all,

This is v3 of RFC patch aimed at fixing duplicated scan entries after channel
switch. The major change is updating non-transmitting bss entries. Since such
a bss cannot change channel without its transmitting bss (and vice versa),
the whole hierarchy of transmitting bss is updated, including channel and
location in rb-tree.

Suggested approach to handle non-transmitting BSS entries is simplified in the
following sense. If new entries have been already created after channel switch,
only transmitting bss will be updated using IEs of new entry for the same
transmitting bss. Non-transmitting bss entries will be updated as soon as
new mgmt frames are received. Updating non-transmitting bss entries seems
too expensive: nested nontrans_list traversing is needed since we can not
rely on the same order of old and new non-transmitting entries.

Basic use-case tested using both iwlwifi and qtnfmac.
However multi-BSSID support has not yet been tested. 

Regards,
Sergey

v1 -> v2
- use IEs of new BSS entry to update known BSS entry
  for this purpose extract BSS update code from cfg80211_bss_update
  into a separate function cfg80211_update_known_bss

v2 -> v3
- minor cleanup according to review comments
- split cfg80211_update_known_bss function into a separate patch
- update channel and location in rb-tree for nontransmit bss entries

Sergey Matyukevich (2):
  cfg80211: refactor cfg80211_bss_update
  cfg80211: fix duplicated scan entries after channel switch

 net/wireless/core.h    |   2 +
 net/wireless/nl80211.c |   2 +-
 net/wireless/scan.c    | 250 +++++++++++++++++++++++++++++++++----------------
 3 files changed, 171 insertions(+), 83 deletions(-)

Comments

Johannes Berg July 12, 2019, 9:11 a.m. UTC | #1
> Suggested approach to handle non-transmitting BSS entries is simplified in the
> following sense. If new entries have been already created after channel switch,
> only transmitting bss will be updated using IEs of new entry for the same
> transmitting bss. Non-transmitting bss entries will be updated as soon as
> new mgmt frames are received. Updating non-transmitting bss entries seems
> too expensive: nested nontrans_list traversing is needed since we can not
> rely on the same order of old and new non-transmitting entries.

That sounds like a reasonable trade-off. I do wonder though what happens
if we're connected to a non-transmitting BSS?

johannes
Sergey Matyukevich July 12, 2019, 9:27 a.m. UTC | #2
On Fri, Jul 12, 2019 at 11:11:19AM +0200, Johannes Berg wrote:
> 
> [External Email]: This email arrived from an external source - Please exercise caution when opening any attachments or clicking on links.
> 
> > Suggested approach to handle non-transmitting BSS entries is simplified in the
> > following sense. If new entries have been already created after channel switch,
> > only transmitting bss will be updated using IEs of new entry for the same
> > transmitting bss. Non-transmitting bss entries will be updated as soon as
> > new mgmt frames are received. Updating non-transmitting bss entries seems
> > too expensive: nested nontrans_list traversing is needed since we can not
> > rely on the same order of old and new non-transmitting entries.
> 
> That sounds like a reasonable trade-off. I do wonder though what happens
> if we're connected to a non-transmitting BSS?

Well, here I rely upon the assumption that CSA IEs of non-transmitting BSS
are handled correctly by mac80211 or any FullMAC firmware. And if we are
connected to non-transmitting BSS rather than transmitting one, the
following code in the beginning of new cfg80211_update_assoc_bss_entry
function is supposed to care about this use-case:

+       /* use transmitting bss */
+       if (cbss->pub.transmitted_bss)
+               cbss = container_of(cbss->pub.transmitted_bss,
+                                   struct cfg80211_internal_bss,
+                                   pub);

In other words, regardless of which BSS we are connected to, the whole
hierarchy of non-transmitting BSS entries will be updated, including
their channels and location in rb-tree.

Regards,
Sergey
Johannes Berg July 12, 2019, 9:40 a.m. UTC | #3
On Fri, 2019-07-12 at 09:27 +0000, Sergey Matyukevich wrote:
> On Fri, Jul 12, 2019 at 11:11:19AM +0200, Johannes Berg wrote:
> > 
> > [External Email]: This email arrived from an external source - Please exercise caution when opening any attachments or clicking on links.

Heh, you have a not so fun email system that rewrites mails ...

> > > Suggested approach to handle non-transmitting BSS entries is simplified in the
> > > following sense. If new entries have been already created after channel switch,
> > > only transmitting bss will be updated using IEs of new entry for the same
> > > transmitting bss. Non-transmitting bss entries will be updated as soon as
> > > new mgmt frames are received. Updating non-transmitting bss entries seems
> > > too expensive: nested nontrans_list traversing is needed since we can not
> > > rely on the same order of old and new non-transmitting entries.
> > 
> > That sounds like a reasonable trade-off. I do wonder though what happens
> > if we're connected to a non-transmitting BSS?
> 
> Well, here I rely upon the assumption that CSA IEs of non-transmitting BSS
> are handled correctly by mac80211 or any FullMAC firmware. And if we are
> connected to non-transmitting BSS rather than transmitting one, the
> following code in the beginning of new cfg80211_update_assoc_bss_entry
> function is supposed to care about this use-case:

Right, it will be updated on RX. But then if we chanswitch, we would
probably (mac80211 using a pointer to the non-transmitting BSS) update
only one of the nontransmitting BSSes?

Just saying that maybe we need to be careful there - or your wording
might be incorrect. We might end up updating a *nontransmitting* BSS,
and then its transmitting/other non-tx ones only later?

johannes
Sergey Matyukevich July 12, 2019, 10:52 a.m. UTC | #4
> > > [External Email]: This email arrived from an external source - Please exercise caution when opening any attachments or clicking on links.
> 
> Heh, you have a not so fun email system that rewrites mails ...

:(
 
> > > > Suggested approach to handle non-transmitting BSS entries is simplified in the
> > > > following sense. If new entries have been already created after channel switch,
> > > > only transmitting bss will be updated using IEs of new entry for the same
> > > > transmitting bss. Non-transmitting bss entries will be updated as soon as
> > > > new mgmt frames are received. Updating non-transmitting bss entries seems
> > > > too expensive: nested nontrans_list traversing is needed since we can not
> > > > rely on the same order of old and new non-transmitting entries.
> > > 
> > > That sounds like a reasonable trade-off. I do wonder though what happens
> > > if we're connected to a non-transmitting BSS?
> > 
> > Well, here I rely upon the assumption that CSA IEs of non-transmitting BSS
> > are handled correctly by mac80211 or any FullMAC firmware. And if we are
> > connected to non-transmitting BSS rather than transmitting one, the
> > following code in the beginning of new cfg80211_update_assoc_bss_entry
> > function is supposed to care about this use-case:
> 
> Right, it will be updated on RX. But then if we chanswitch, we would
> probably (mac80211 using a pointer to the non-transmitting BSS) update
> only one of the nontransmitting BSSes?
> 
> Just saying that maybe we need to be careful there - or your wording
> might be incorrect. We might end up updating a *nontransmitting* BSS,
> and then its transmitting/other non-tx ones only later?

Hmmm... I am not sure we are on the same page here. Could you please
clarify your concerns here ?

The normal (non multi-BSSID) BSS usecase seem to be clear: keep old and
remove new (if any), since it is not easy to update ifmgd->associated.

Now let me take another look at the usecase when STA is connected to
a transmitting or non-transmitting BSS of a multi-BSS AP. At the moment
suggested code does the following. If STA is connected to the non-transmitting
BSS, then we switch to its transmitting BSS, instead of working with
current_bss directly.

So we look for the new entry (with new channel) of the transmitting BSS.
If it exists, then we remove it and _all_ of its non-transmitting BSSs.
Finally, we update channel and location in rb-tree of the existing (old)
transmitting BSS as well as _all_ of its non-transmitting entries.

Regards,
Sergey
Johannes Berg July 26, 2019, 7:36 a.m. UTC | #5
Hi Sergey,

Sorry for dropping the ball on this thread.

> > Right, it will be updated on RX. But then if we chanswitch, we would
> > probably (mac80211 using a pointer to the non-transmitting BSS) update
> > only one of the nontransmitting BSSes?
> > 
> > Just saying that maybe we need to be careful there - or your wording
> > might be incorrect. We might end up updating a *nontransmitting* BSS,
> > and then its transmitting/other non-tx ones only later?
> 
> Hmmm... I am not sure we are on the same page here. Could you please
> clarify your concerns here ?

I'm trying to say we might have this:

cfg80211
 * transmitting BSS 0
   - nontx BSS 1
   - nontx BSS 2
   - nontx BSS 3
mac80211
 * ifmgd->associated (and cfg80211's wdev->current_bss?) = nontx BSS 2


Now, things like the channel information etc. will always be identical
between the 4 BSSes, by definition.

However, if you chanswitch and mac80211 just lets cfg80211 know about
the current_bss, then you may end up in a situation where the channel
information is no longer the same, which is very surprising.


> The normal (non multi-BSSID) BSS usecase seem to be clear: keep old and
> remove new (if any), since it is not easy to update ifmgd->associated.

Right.

> Now let me take another look at the usecase when STA is connected to
> a transmitting or non-transmitting BSS of a multi-BSS AP. At the moment
> suggested code does the following. If STA is connected to the non-transmitting
> BSS, then we switch to its transmitting BSS, instead of working with
> current_bss directly.

We switch? Where? Maybe I missed that.

> So we look for the new entry (with new channel) of the transmitting BSS.
> If it exists, then we remove it and _all_ of its non-transmitting BSSs.
> Finally, we update channel and location in rb-tree of the existing (old)
> transmitting BSS as well as _all_ of its non-transmitting entries.

That would indeed address the scenario I was thinking of ...

johannes
Sergey Matyukevich July 26, 2019, 10:11 a.m. UTC | #6
Hello Johannes,

> > > Right, it will be updated on RX. But then if we chanswitch, we would
> > > probably (mac80211 using a pointer to the non-transmitting BSS) update
> > > only one of the nontransmitting BSSes?
> > > 
> > > Just saying that maybe we need to be careful there - or your wording
> > > might be incorrect. We might end up updating a *nontransmitting* BSS,
> > > and then its transmitting/other non-tx ones only later?
> > 
> > Hmmm... I am not sure we are on the same page here. Could you please
> > clarify your concerns here ?
> 
> I'm trying to say we might have this:
> 
> cfg80211
>  * transmitting BSS 0
>    - nontx BSS 1
>    - nontx BSS 2
>    - nontx BSS 3
> mac80211
>  * ifmgd->associated (and cfg80211's wdev->current_bss?) = nontx BSS 2

Yes, this is the use-case that I tried to address in the last revision
of the patch. Suggested approach is similar to what is done for normal
case:
- to keep this hierarchy updating channels and location in rb-tree
- remove newly added hierarchy of the same transmitting BSS on the new
  channel

Note that here we update/remove not only transmitting BSSs, but their
nontx BSS hierarchies as well.

> 
> 
> Now, things like the channel information etc. will always be identical
> between the 4 BSSes, by definition.
> 
> However, if you chanswitch and mac80211 just lets cfg80211 know about
> the current_bss, then you may end up in a situation where the channel
> information is no longer the same, which is very surprising.
> 
> 
> > The normal (non multi-BSSID) BSS usecase seem to be clear: keep old and
> > remove new (if any), since it is not easy to update ifmgd->associated.
> 
> Right.
> 
> > Now let me take another look at the usecase when STA is connected to
> > a transmitting or non-transmitting BSS of a multi-BSS AP. At the moment
> > suggested code does the following. If STA is connected to the non-transmitting
> > BSS, then we switch to its transmitting BSS, instead of working with
> > current_bss directly.
> 
> We switch? Where? Maybe I missed that.

If you take a look at the top of new cfg80211_update_assoc_bss_entry
function:

+       /* use transmitting bss */
+       if (cbss->pub.transmitted_bss)
+               cbss = container_of(cbss->pub.transmitted_bss,
+                                   struct cfg80211_internal_bss,
+                                   pub);

> > So we look for the new entry (with new channel) of the transmitting BSS.
> > If it exists, then we remove it and _all_ of its non-transmitting BSSs.
> > Finally, we update channel and location in rb-tree of the existing (old)
> > transmitting BSS as well as _all_ of its non-transmitting entries.
> 
> That would indeed address the scenario I was thinking of ...

Ok! Let me know if you have any other concerns or questions.

Actually one of the major concerns is the lack of testing for the 'multi-BSSID'
scenario. I verified the 'normal' scenario using both mac80211 (iwlwifi) and
FullMAC (qtnfmac) cards. But at the moment I don't have any mac80211 card
supporting multi-BSSID.

Regards,
Sergey
Johannes Berg July 26, 2019, 12:02 p.m. UTC | #7
Hi Sergey,

> Yes, this is the use-case that I tried to address in the last revision
> of the patch.

OK! I didn't see it here and I guess I didn't look at the latest version
yet, or I missed it.

> If you take a look at the top of new cfg80211_update_assoc_bss_entry
> function:
> 
> +       /* use transmitting bss */
> +       if (cbss->pub.transmitted_bss)
> +               cbss = container_of(cbss->pub.transmitted_bss,
> +                                   struct cfg80211_internal_bss,
> +                                   pub);

Right, makes sense!

> Actually one of the major concerns is the lack of testing for the 'multi-BSSID'
> scenario. I verified the 'normal' scenario using both mac80211 (iwlwifi) and
> FullMAC (qtnfmac) cards. But at the moment I don't have any mac80211 card
> supporting multi-BSSID.

You might be able to do that with hwsim? There are multi-bssid test
cases in the hostap repository, and CSA test cases as well, so I guess
it'd be possible to come up with a combined one.

I'm not *too* worried about this though - we're still all testing and
developing this.

johannes