2009-09-18 16:50:09

by Holger Schurig

[permalink] [raw]
Subject: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

This attribute allows user-space to override or turn of the default
BSS expiration time for NL80211_CMD_GET_SCAN.

It also allows to set an expiration for NL80211_CMD_TRIGGER_SCAN. Setting
the expiration to 0 will clean the whole BSS list.

Signed-off-by: Holger Schurig <[email protected]>

---

Currently, I'm using the user-space AS-IS. Maybe I should do

export = nla_get_u32(..) * HZ

or, if we want to specify this in ms:

export = nla_get_u32(..) * HZ / 1000

???


A simple demo patch for iw that swaps behavior (expire all BSS at scan time,
never expire at dump time) is here:

xx iw.orig/scan.c 2009-09-18 16:28:07.000000000 +0200
xx iw/scan.c 2009-09-18 16:45:41.000000000 +0200
xx -102,6 +102,8 @@ static int handle_scan(struct nl80211_st
if (have_freqs)
nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);

+ NLA_PUT_U32(msg, 83 /* NL80211_ATTR_SCAN_EXPIRE */, 0);
+
err = 0;
nla_put_failure:
nlmsg_free(ssids);
xx -871,7 +873,10 @@ static int handle_scan_dump(struct nl802

nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler,
&scan_params);
+ NLA_PUT_U32(msg, 83 /* NL80211_ATTR_SCAN_EXPIRE */, 0);
return 0;
+nla_put_failure:
+ return 2;
}

static int handle_scan_combined(struct nl80211_state *state,


Index: linux-wl/net/wireless/core.h
===================================================================
--- linux-wl.orig/net/wireless/core.h 2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/core.h 2009-09-18 17:31:05.000000000 +0200
@@ -270,7 +270,9 @@ void ieee80211_set_bitrate_flags(struct
void wiphy_update_regulatory(struct wiphy *wiphy,
enum nl80211_reg_initiator setby);

-void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
+#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
+
+void cfg80211_bss_expire(struct cfg80211_registered_device *dev, int expire);
void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs);

Index: linux-wl/net/wireless/nl80211.c
===================================================================
--- linux-wl.orig/net/wireless/nl80211.c 2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/nl80211.c 2009-09-18 17:36:04.000000000 +0200
@@ -138,6 +138,7 @@ static struct nla_policy nl80211_policy[
[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
[NL80211_ATTR_PID] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCAN_EXPIRE] = { .type = NLA_U32 },
};

/* policy for the attributes */
@@ -2945,6 +2946,13 @@ static int nl80211_trigger_scan(struct s
goto out;
}

+ if (info->attrs[NL80211_ATTR_SCAN_EXPIRE]) {
+ u32 expire = nla_get_u32(info->attrs[NL80211_ATTR_SCAN_EXPIRE]);
+ spin_lock_bh(&rdev->bss_lock);
+ cfg80211_bss_expire(rdev, expire);
+ spin_unlock_bh(&rdev->bss_lock);
+ }
+
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
n_channels = validate_scan_freqs(
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
@@ -3158,11 +3166,13 @@ static int nl80211_dump_scan(struct sk_b
int ifidx = cb->args[0];
int start = cb->args[1], idx = 0;
int err;
+ u32 expire = IEEE80211_SCAN_RESULT_EXPIRE;
+
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
+ nl80211_policy);

if (!ifidx) {
- err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
if (err)
return err;

@@ -3187,9 +3197,20 @@ static int nl80211_dump_scan(struct sk_b

wdev = dev->ieee80211_ptr;

+ /*
+ * If expire is set (the default), expire the BSS list before
+ * returning values. However, user-space can set a different
+ * expire time via NL80211_ATTR_SCAN_EXPIRE. It can also set
+ * no expire-time at all, then we skip the expiration.
+ */
+ if (!err && nl80211_fam.attrbuf[NL80211_ATTR_SCAN_EXPIRE])
+ expire =
+ nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_SCAN_EXPIRE]);
+
wdev_lock(wdev);
spin_lock_bh(&rdev->bss_lock);
- cfg80211_bss_expire(rdev);
+ if (expire)
+ cfg80211_bss_expire(rdev, expire);

list_for_each_entry(scan, &rdev->bss_list, list) {
if (++idx <= start)
Index: linux-wl/net/wireless/scan.c
===================================================================
--- linux-wl.orig/net/wireless/scan.c 2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/scan.c 2009-09-18 17:32:08.000000000 +0200
@@ -16,8 +16,6 @@
#include "nl80211.h"
#include "wext-compat.h"

-#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
-
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
{
struct cfg80211_scan_request *request;
@@ -121,7 +119,7 @@ void cfg80211_bss_age(struct cfg80211_re
}

/* must hold dev->bss_lock! */
-void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
+void cfg80211_bss_expire(struct cfg80211_registered_device *dev, int expire)
{
struct cfg80211_internal_bss *bss, *tmp;
bool expired = false;
@@ -129,7 +127,11 @@ void cfg80211_bss_expire(struct cfg80211
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
if (atomic_read(&bss->hold))
continue;
- if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
+ /*
+ * If expire==0, then expire all BSS from the list,
+ * else only expire those that are older than expire.
+ */
+ if (expire && !time_after(jiffies, bss->ts + expire))
continue;
list_del(&bss->list);
rb_erase(&bss->rbn, &dev->bss_tree);
@@ -970,9 +972,11 @@ static int ieee80211_scan_results(struct
char *current_ev = buf;
char *end_buf = buf + len;
struct cfg80211_internal_bss *bss;
+ u32 expire = IEEE80211_SCAN_RESULT_EXPIRE;

spin_lock_bh(&dev->bss_lock);
- cfg80211_bss_expire(dev);
+ if (expire)
+ cfg80211_bss_expire(dev, expire);

list_for_each_entry(bss, &dev->bss_list, list) {
if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
Index: linux-wl/include/linux/nl80211.h
===================================================================
--- linux-wl.orig/include/linux/nl80211.h 2009-09-18 15:10:53.000000000 +0200
+++ linux-wl/include/linux/nl80211.h 2009-09-18 15:11:44.000000000 +0200
@@ -481,6 +481,7 @@ enum nl80211_commands {
* @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
* scanning and include a zero-length SSID (wildcard) for wildcard scan
* @NL80211_ATTR_BSS: scan result BSS
+ * @NL80211_ATTR_SCAN: expire time for cached bss list
*
* @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
* currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
@@ -714,6 +715,8 @@ enum nl80211_attrs {

NL80211_ATTR_PID,

+ NL80211_ATTR_SCAN_EXPIRE,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,

--
http://www.holgerschurig.de


2009-09-22 23:29:49

by Dan Williams

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Mon, 2009-09-21 at 09:46 +0200, Holger Schurig wrote:
> > It's not actually the same, and you didn't explain that well.
> > You care about the disappear case, but you made it sound like
> > you cared about the _reappear_ case.
>
> Okay, sorry. I thought you read my other mails about
> scan-life-time and that thus the context was/is clear.
>
>
> The base issue is: SCAN_TRIGGER does normally not a "clean scan",
> it normally adds entries to the BSS list or updates existing
> ones.
>
> Entries in the BSS list are only deleted after 15 seconds.

So on the supplicant side, this weekend I was discussing with Jouni
about making the supplicant *not* trigger a completely new scan when
trying to associate if the scan list was current in the past 5 or 10
seconds. The issue here is that NM requests a scan, figures out what AP
to start using, then tells the supplicant to associate with it. Then
the supplicant throws away any scan results it has an does a full *new*
scan before associating. That adds about 5 seconds to each NM
connection attempt that I'd like to get rid of.

Would that interfere with your forklift case?

BTW, 10 years ago I did a forklift deployment too with pre-802.11
Aironet equipment and Netware. Wasn't that fun to get up and running.
This was at a paper company too, and guess what huge rolls of paper do?
They absorb radio waves quite well. Suck. And forklifts can go *fast*.

Dan

>
>
> However, in 15 seconds you can easily leave the range of AP_OLD
> and be in the range of a completely AP_NEW. But it can also be
> the case that the (now stale!) signal of AP_OLD is higher than
> the (real) signal of AP_NEW. In this case wpa_supplicant tries
> to associate to AP_OLD, which is out-of-sight. And that takes
> unneeded time.
>
>
> I simple tried to mimick this scenario in the office, by
> switching off an AP (just that I didn't really switch it off,
> because the boot-times of Cisco-APs are soooooooo sloooooow).
>
> About your "It's not actually the same": I think that my
> laboratory experiment very well shows this behavior, e.g. see my
> 2nd message with subject "Life-time of scan-results?":
>
> 1253275108.958746: Trying to authenticate with 00:13:19:80:da:30
> (SSID='MNHS' freq=2412 MHz)
>
> Bit this is the "vanished" AP_OLD. With wireshark on a second
> WLAN card I saw the attemps of mac80211 to associate to this
> now-out-of-sight AP. This takes some tries from mac80211, then a
> timeout on wpa_supplicant, than a new scan, then a new attempt.
> All of those delays completely unnecessary if there would have
> been a way to not get stale data via SCAN_DUMP.
>
>
>
> So, clearly I have a visible problem and need to fix that.
>
> I could fix that by making SCAN_TRIGGER always delete all stale
> (cached) entries. Then I wouldn't need NL80211_ATTR_SCAN_EXPIRE.
>
> However, a scan because "I want to look what is around" might be
> different to a scan because "I need fresh data of APs around for
> associating". And so I thought I make that configurable.
>
>
> I hope this now makes more sense.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2009-09-21 06:44:37

by Holger Schurig

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

> > It also allows to set an expiration for
> > NL80211_CMD_TRIGGER_SCAN. Setting the expiration to 0 will
> > clean the whole BSS list.
>
> tbh, I don't really understand the need for it. changing your
> AP settings doesn't seem like a use case anyone would really
> care about that much.

Turning of an AP is one way making the AP vanish.

Sitting into a fork-lift and driving throught a ware-house hall
is another way to accomplish the same.

However, it's way easier for me to change the AP's setting than
to actually leave me office :-)


/me wishes kernel developers would have more sense for real
life :-)

--
http://www.holgerschurig.de

2009-09-21 07:15:37

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Mon, 2009-09-21 at 08:42 +0200, Holger Schurig wrote:
> > > It also allows to set an expiration for
> > > NL80211_CMD_TRIGGER_SCAN. Setting the expiration to 0 will
> > > clean the whole BSS list.
> >
> > tbh, I don't really understand the need for it. changing your
> > AP settings doesn't seem like a use case anyone would really
> > care about that much.
>
> Turning of an AP is one way making the AP vanish.
>
> Sitting into a fork-lift and driving throught a ware-house hall
> is another way to accomplish the same.

It's not actually the same, and you didn't explain that well. You care
about the disappear case, but you made it sound like you cared about the
_reappear_ case.

However, I still don't believe that you need to change anything in the
kernel, just get wpa_supplicant to handle it properly.

johannes


Attachments:
signature.asc (801.00 B)
This is a digitally signed message part

2009-09-23 07:21:52

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Wed, 2009-09-23 at 09:12 +0200, Holger Schurig wrote:

> There's just one case: if there is no BSS in the scan list.
> Then any app doing a "get scan results" call wouldn't know
> if the last scan is ages ago or if there is really no AP
> in the vincinity, doing an immediate re-scan. This can be
> harmful for battery-driven devices. So maybe a timestamp
> "last scan was at timestamp XXX" besides the individual
> BSS timestamps would be helpful here.
>
> This way apps can synchronize themselfes and, even if
> different apps do scanning, they can say "We don't scan
> more often than every N seconds".

You can monitor nl80211 events for scan completion already, so this
isn't really an issue. In fact, adding a "last scan" thing would not be
a good idea since the scan might have been different, only contained a
subset of channels, etc.

johannes


Attachments:
signature.asc (801.00 B)
This is a digitally signed message part

2009-09-23 07:35:38

by Holger Schurig

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

> You can monitor nl80211 events for scan completion already, so this
> isn't really an issue. In fact, adding a "last scan" thing would not be
> a good idea since the scan might have been different, only contained a
> subset of channels, etc.

Ah, yes.

--
http://www.holgerschurig.de

2009-09-21 07:12:06

by Holger Schurig

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

Hmm, I think I need some more check:

NL80211_CMD_SCAN_TRIGGER is a root-only operation
NL80211_CMD_GET_SCAN is an any-user operation.

I think that a non-root user shouldn't be allowed to specify
NL80211_ATTR_SCAN_EXPIRE that is smaller than
IEEE80211_SCAN_RESULT_EXPIRE, right?

--
http://www.holgerschurig.de

2009-09-23 06:34:38

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Mon, 2009-09-21 at 09:46 +0200, Holger Schurig wrote:

> I hope this now makes more sense.

It does, but I disagree with the solution. IMO we should just add a
"last seen at" timestamp to each BSS so wpa_supplicant can make the
decision which ones to look at and which ones to ignore. They'll all be
used when you don't let wpa_supplicant roam, but that doesn't really
matter much.

johannes


Attachments:
signature.asc (801.00 B)
This is a digitally signed message part

2009-09-21 07:47:08

by Holger Schurig

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

> It's not actually the same, and you didn't explain that well.
> You care about the disappear case, but you made it sound like
> you cared about the _reappear_ case.

Okay, sorry. I thought you read my other mails about
scan-life-time and that thus the context was/is clear.


The base issue is: SCAN_TRIGGER does normally not a "clean scan",
it normally adds entries to the BSS list or updates existing
ones.

Entries in the BSS list are only deleted after 15 seconds.



However, in 15 seconds you can easily leave the range of AP_OLD
and be in the range of a completely AP_NEW. But it can also be
the case that the (now stale!) signal of AP_OLD is higher than
the (real) signal of AP_NEW. In this case wpa_supplicant tries
to associate to AP_OLD, which is out-of-sight. And that takes
unneeded time.


I simple tried to mimick this scenario in the office, by
switching off an AP (just that I didn't really switch it off,
because the boot-times of Cisco-APs are soooooooo sloooooow).

About your "It's not actually the same": I think that my
laboratory experiment very well shows this behavior, e.g. see my
2nd message with subject "Life-time of scan-results?":

1253275108.958746: Trying to authenticate with 00:13:19:80:da:30
(SSID='MNHS' freq=2412 MHz)

Bit this is the "vanished" AP_OLD. With wireshark on a second
WLAN card I saw the attemps of mac80211 to associate to this
now-out-of-sight AP. This takes some tries from mac80211, then a
timeout on wpa_supplicant, than a new scan, then a new attempt.
All of those delays completely unnecessary if there would have
been a way to not get stale data via SCAN_DUMP.



So, clearly I have a visible problem and need to fix that.

I could fix that by making SCAN_TRIGGER always delete all stale
(cached) entries. Then I wouldn't need NL80211_ATTR_SCAN_EXPIRE.

However, a scan because "I want to look what is around" might be
different to a scan because "I need fresh data of APs around for
associating". And so I thought I make that configurable.


I hope this now makes more sense.

2009-09-18 17:11:45

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Fri, 2009-09-18 at 18:49 +0200, Holger Schurig wrote:
> This attribute allows user-space to override or turn of the default
> BSS expiration time for NL80211_CMD_GET_SCAN.
>
> It also allows to set an expiration for NL80211_CMD_TRIGGER_SCAN. Setting
> the expiration to 0 will clean the whole BSS list.

tbh, I don't really understand the need for it. changing your AP
settings doesn't seem like a use case anyone would really care about
that much.

johannes


Attachments:
signature.asc (801.00 B)
This is a digitally signed message part

2009-09-23 07:13:51

by Holger Schurig

[permalink] [raw]
Subject: Re: [RFC] nl80211: introduce NL80211_ATTR_SCAN_EXPIRE

On Wednesday 23 September 2009 01:29:32 Dan Williams wrote:

> So on the supplicant side, this weekend I was discussing with
> Jouni about making the supplicant *not* trigger a completely
> new scan when trying to associate if the scan list was current
> in the past 5 or 10 seconds. The issue here is that NM
> requests a scan, ...

I currently center around a setup without NM. Okay, for the
forklift terminals (they are x86-based), NM would be feasible.
But for the handheld terminals (Intel PXA based) I'm not keen
on NM. So I basically develop a simple program that monitors
signal and triggers a scan when signal level is below some
thresshold. This program happens to be linked into
wpa_supplicant, but it can also be a standalone program.

I'm relying on wpa_supplicant's feature to monitor scan-done
events and looking if there's something a better matching BSS
in the result.



But when you take wpa_supplicant, NM and whatever, then maybe the
timestamp idea from Johannes should be used. Any application
that wants to look if it should roam can quickly get the
scan results. By the timestamp of the entries it can then
see how old the entries are. Only if entries are outdated,
it can fire up a scan.

There's just one case: if there is no BSS in the scan list.
Then any app doing a "get scan results" call wouldn't know
if the last scan is ages ago or if there is really no AP
in the vincinity, doing an immediate re-scan. This can be
harmful for battery-driven devices. So maybe a timestamp
"last scan was at timestamp XXX" besides the individual
BSS timestamps would be helpful here.

This way apps can synchronize themselfes and, even if
different apps do scanning, they can say "We don't scan
more often than every N seconds".


> BTW, 10 years ago I did a forklift deployment too with pre-802.11
> Aironet equipment and Netware. Wasn't that fun to get up and running.
> This was at a paper company too, and guess what huge rolls of paper do?
> They absorb radio waves quite well. Suck. And forklifts can go *fast*.

Oh, and a wholesale company for drinks is even more demanding.
Water-based liquid has the nice property of absorbing microwaves
in the 2.4 MHz range extremely nicely, just see your next
microwave oven for a proof ...


The nice thing about this: when you have a working roaming
(and fast-enought handoff) in a warehouse/fork-lift scenary,
then your can forget about the WLAN problem in other scenarios,
because they are way less demanding. What happens to work in
the forklift case works everywhere else.

--
http://www.holgerschurig.de