diff options
author | adrian <adrian@FreeBSD.org> | 2015-05-10 22:07:53 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2015-05-10 22:07:53 +0000 |
commit | a4b25580a84b5ce3dd1b738792209f9e7f11cb66 (patch) | |
tree | 1c50a63e0ec564e87d4fcd4a4a7e6dc0dfa45189 | |
parent | ba9d713de764ef16cf2436b4c221a6a69eb6e631 (diff) | |
download | FreeBSD-src-a4b25580a84b5ce3dd1b738792209f9e7f11cb66.zip FreeBSD-src-a4b25580a84b5ce3dd1b738792209f9e7f11cb66.tar.gz |
Prepare for supporting driver-overridden curchan when submitting scan
results.
Right now the scan infrastructure assumes the channel is under net80211
control, and that when receiving beacon frames for scanning, the
current channel is indeed what ic_curchan is set to.
But firmware NICs with firmware scan support need more than this -
they can do background scans whilst hiding the off-channel behaviour
from net80211. Ie, net80211 still thinks everything is associated
and on the main channel, but it's getting scan results from all the
background traffic.
However sta_add() pays attention to ic_curchan and discards scan
results that aren't on the right channel. CCK beacon frames can be
decoded from adjacent channels so the receive path and sta_add
discard these as appropriate. This is fine for software scanning
like for ath(4), but not for firmware NICs. So with those, the
whole concept of background firmware scanning won't work without
major hacks (eg, overriding ic_curchan before calling the beacon
input / scan add.)
As part of my scan overhaul, modify sta_add() and the scan_add()
APIs to take an explicit current channel. The normal RX path
will set it to ic_curchan so it's a no-op. However, drivers may
decide to (eventually!) override the scan method to set the
"right" current channel based on what the firmware reports the
scan state is.
So for example, iwn, rsu and other NICs will eventually do this:
* driver issues scan start firmware command;
* firmware sends a "scan start on channel X" notify;
* firmware sends a bunch of beacon RX's as part of
the scan results;
* .. and the driver will replace scan_add() curchan with channel X,
so scan results are correct.
* firmware sends a "scan start on channel Y" notify;
* firmware sends more beacons...
* .. the driver replaces scan_add() curchan with channel Y.
Note:
* Eventually, net80211 should eventually grow the idea of a per-packet
current channel. It's possible in various modes (eg WAVE, P2P, etc)
that individual frames can come in from different channels and that
is under firmware control rather than driver/net80211 control, so
we should support that.
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_adhoc.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_hostap.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_mesh.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan.c | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan.h | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sta.c | 7 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sw.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_scan_sw.h | 1 | ||||
-rw-r--r-- | sys/net80211/ieee80211_sta.c | 7 |
10 files changed, 22 insertions, 12 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 8f23527..c066483 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -3316,7 +3316,7 @@ done: DPRINTF(("scan: bssid %s chan %dMHz (%d/%d) rssi %d\n", ether_sprintf(wb->nwbx_macaddr), freq, sp.bchan, chanflag, rssi)); - ieee80211_add_scan(vap, &sp, &wh, 0, rssi, noise); + ieee80211_add_scan(vap, ic->ic_curchan, &sp, &wh, 0, rssi, noise); wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); } free(bl, M_DEVBUF); diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index fa83cf9..a3d4e51 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -735,7 +735,8 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, ieee80211_probe_curchan(vap, 1); ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN; } - ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); + ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh, + subtype, rssi, nf); return; } if (scan.capinfo & IEEE80211_CAPINFO_IBSS) { diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 32eec45..8c7b8f5 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -1737,7 +1737,8 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, ieee80211_probe_curchan(vap, 1); ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN; } - ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); + ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh, + subtype, rssi, nf); return; } /* diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index de9d60b..2c2151f 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1906,7 +1906,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, ieee80211_probe_curchan(vap, 1); ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN; } - ieee80211_add_scan(vap, &scan, wh, + ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh, subtype, rssi, nf); return; } diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c index 4a0fde8..6c950d6 100644 --- a/sys/net80211/ieee80211_scan.c +++ b/sys/net80211/ieee80211_scan.c @@ -562,12 +562,14 @@ ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew, */ void ieee80211_add_scan(struct ieee80211vap *vap, + struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise) { - return (ieee80211_swscan_add_scan(vap, sp, wh, subtype, rssi, noise)); + return (ieee80211_swscan_add_scan(vap, curchan, sp, wh, subtype, + rssi, noise)); } /* diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h index 69daf60..8b54186 100644 --- a/sys/net80211/ieee80211_scan.h +++ b/sys/net80211/ieee80211_scan.h @@ -148,6 +148,7 @@ struct ieee80211_channel *ieee80211_scan_pickchannel(struct ieee80211com *, int) struct ieee80211_scanparams; void ieee80211_add_scan(struct ieee80211vap *, + struct ieee80211_channel *, const struct ieee80211_scanparams *, const struct ieee80211_frame *, int subtype, int rssi, int noise); @@ -273,6 +274,7 @@ struct ieee80211_scanner { struct ieee80211_scan_state *, int); /* add an entry to the cache */ int (*scan_add)(struct ieee80211_scan_state *, + struct ieee80211_channel *, const struct ieee80211_scanparams *, const struct ieee80211_frame *, int subtype, int rssi, int noise); diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 1e87e35..1fb45b0 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -228,6 +228,7 @@ sta_flush_table(struct sta_table *st) */ static int sta_add(struct ieee80211_scan_state *ss, + struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise) @@ -310,15 +311,15 @@ found: * IEEE80211_BPARSE_OFFCHAN. */ c = ieee80211_find_channel_byieee(ic, sp->chan, - ic->ic_curchan->ic_flags); + curchan->ic_flags); if (c != NULL) { ise->se_chan = c; } else if (ise->se_chan == NULL) { /* should not happen, pick something */ - ise->se_chan = ic->ic_curchan; + ise->se_chan = curchan; } } else - ise->se_chan = ic->ic_curchan; + ise->se_chan = curchan; if (IEEE80211_IS_CHAN_HT(ise->se_chan) && sp->htcap == NULL) { /* Demote legacy networks to a non-HT channel. */ c = ieee80211_find_channel(ic, ise->se_chan->ic_freq, diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c index 2904bca..70b4673 100644 --- a/sys/net80211/ieee80211_scan_sw.c +++ b/sys/net80211/ieee80211_scan_sw.c @@ -900,6 +900,7 @@ done: */ void ieee80211_swscan_add_scan(struct ieee80211vap *vap, + struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise) @@ -922,7 +923,7 @@ ieee80211_swscan_add_scan(struct ieee80211vap *vap, ieee80211_scan_dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi); #endif if (ss->ss_ops != NULL && - ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise)) { + ss->ss_ops->scan_add(ss, curchan, sp, wh, subtype, rssi, noise)) { /* * If we've reached the min dwell time terminate * the timer so we'll switch to the next channel. diff --git a/sys/net80211/ieee80211_scan_sw.h b/sys/net80211/ieee80211_scan_sw.h index 95fe482..7bb0cc3 100644 --- a/sys/net80211/ieee80211_scan_sw.h +++ b/sys/net80211/ieee80211_scan_sw.h @@ -53,6 +53,7 @@ extern void ieee80211_swscan_scan_done(struct ieee80211vap *vap); extern void ieee80211_swscan_probe_curchan(struct ieee80211vap *vap, int force); extern void ieee80211_swscan_add_scan(struct ieee80211vap *vap, + struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise); diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index c3c2bc9..5a21747 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -1484,8 +1484,8 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, * our ap. */ if (ic->ic_flags & IEEE80211_F_SCAN) { - ieee80211_add_scan(vap, &scan, wh, - subtype, rssi, nf); + ieee80211_add_scan(vap, ic->ic_curchan, + &scan, wh, subtype, rssi, nf); } else if (contbgscan(vap)) { ieee80211_bg_scan(vap, 0); } else if (startbgscan(vap)) { @@ -1529,7 +1529,8 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, ieee80211_probe_curchan(vap, 1); ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN; } - ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); + ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh, + subtype, rssi, nf); return; } break; |