Message ID | 200909181849.22302.hs4233@mail.mn-solutions.de (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
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
> > 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 :-)
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?
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
> 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. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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
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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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.
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
> 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.
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,
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 <hs4233@mail.mn-solutions.de> --- 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,