aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-04-16 07:17:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:57:16 -0400
commitd91f36db51661018f6d54ff5966e283bcec4c545 (patch)
treecde91cde0e6478c3c8cb256786eb61f3c48842c4 /net/mac80211/util.c
parent10f644a47b76d3e61b98f2d02ce9690b94c51ee5 (diff)
mac80211: implement beacon filtering in software
Regardless of whether the hardware implements beacon filtering, there's no need to process all beacons in software all the time throughout the stack (mac80211 does a lot, then cfg80211, then in the future possibly userspace). This patch implements the "best possible" beacon filtering in mac80211. "Best possible" means that it can look for changes in all requested information elements, and distinguish vendor IEs by their OUI. In the future, we will add nl80211 API for userspace to request information elements and vendor IE OUIs to watch -- drivers can then implement the best they can do while software implements it fully. It is unclear whether or not this actually saves CPU time, but the data is all in the cache already so it should be fairly cheap. The additional _testing_, however, has great benefit; Without this, and on hardware that doesn't implement beacon filtering, wrong assumptions about, for example, scan result updates could quickly creep into code. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b361e2acfce..3dd490fa4b6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -20,6 +20,7 @@
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/wireless.h> 21#include <linux/wireless.h>
22#include <linux/bitmap.h> 22#include <linux/bitmap.h>
23#include <linux/crc32.h>
23#include <net/net_namespace.h> 24#include <net/net_namespace.h>
24#include <net/cfg80211.h> 25#include <net/cfg80211.h>
25#include <net/rtnetlink.h> 26#include <net/rtnetlink.h>
@@ -537,8 +538,16 @@ EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
537void ieee802_11_parse_elems(u8 *start, size_t len, 538void ieee802_11_parse_elems(u8 *start, size_t len,
538 struct ieee802_11_elems *elems) 539 struct ieee802_11_elems *elems)
539{ 540{
541 ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
542}
543
544u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
545 struct ieee802_11_elems *elems,
546 u64 filter, u32 crc)
547{
540 size_t left = len; 548 size_t left = len;
541 u8 *pos = start; 549 u8 *pos = start;
550 bool calc_crc = filter != 0;
542 551
543 memset(elems, 0, sizeof(*elems)); 552 memset(elems, 0, sizeof(*elems));
544 elems->ie_start = start; 553 elems->ie_start = start;
@@ -552,7 +561,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
552 left -= 2; 561 left -= 2;
553 562
554 if (elen > left) 563 if (elen > left)
555 return; 564 break;
565
566 if (calc_crc && id < 64 && (filter & BIT(id)))
567 crc = crc32_be(crc, pos - 2, elen + 2);
556 568
557 switch (id) { 569 switch (id) {
558 case WLAN_EID_SSID: 570 case WLAN_EID_SSID:
@@ -587,15 +599,20 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
587 elems->challenge = pos; 599 elems->challenge = pos;
588 elems->challenge_len = elen; 600 elems->challenge_len = elen;
589 break; 601 break;
590 case WLAN_EID_WPA: 602 case WLAN_EID_VENDOR_SPECIFIC:
591 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && 603 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
592 pos[2] == 0xf2) { 604 pos[2] == 0xf2) {
593 /* Microsoft OUI (00:50:F2) */ 605 /* Microsoft OUI (00:50:F2) */
606
607 if (calc_crc)
608 crc = crc32_be(crc, pos - 2, elen + 2);
609
594 if (pos[3] == 1) { 610 if (pos[3] == 1) {
595 /* OUI Type 1 - WPA IE */ 611 /* OUI Type 1 - WPA IE */
596 elems->wpa = pos; 612 elems->wpa = pos;
597 elems->wpa_len = elen; 613 elems->wpa_len = elen;
598 } else if (elen >= 5 && pos[3] == 2) { 614 } else if (elen >= 5 && pos[3] == 2) {
615 /* OUI Type 2 - WMM IE */
599 if (pos[4] == 0) { 616 if (pos[4] == 0) {
600 elems->wmm_info = pos; 617 elems->wmm_info = pos;
601 elems->wmm_info_len = elen; 618 elems->wmm_info_len = elen;
@@ -680,6 +697,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
680 left -= elen; 697 left -= elen;
681 pos += elen; 698 pos += elen;
682 } 699 }
700
701 return crc;
683} 702}
684 703
685void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 704void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)