summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2007-09-17 19:07:24 +0000
committersam <sam@FreeBSD.org>2007-09-17 19:07:24 +0000
commitd2e6b6eac7970920eccfe2d65f03d9ca3c6542ae (patch)
treedd53d98ae592f4e1d6caa3458fddec6956ad9dd5 /sys/net80211
parentb6c4c36f72b670e2821f1e630182572a7b96337c (diff)
downloadFreeBSD-src-d2e6b6eac7970920eccfe2d65f03d9ca3c6542ae.zip
FreeBSD-src-d2e6b6eac7970920eccfe2d65f03d9ca3c6542ae.tar.gz
Update beacon handling to sync w/ vap code base:
o add driver callback to handle notification of beacon changes; this is required for devices that manage beacon frames themselves (devices must override the default handler which does nothing) o move beacon update-related flags from ieee80211com to the beacon offsets storage (or handle however a driver wants) o expand beacon offsets structure with members needed for 11h/dfs and appie's o change calling convention for ieee80211_beacon_alloc and ieee80211_beacon_update o add overlapping bss support for 11g; requires driver to pass beacon frames from overlapping bss up to net80211 which is not presently done by any driver o move HT beacon contents update to a routine in the HT code area Reviewed by: avatar, thompsa, sephe Approved by: re (blanket wireless)
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_ht.c36
-rw-r--r--sys/net80211/ieee80211_ht.h3
-rw-r--r--sys/net80211/ieee80211_node.c129
-rw-r--r--sys/net80211/ieee80211_node.h5
-rw-r--r--sys/net80211/ieee80211_output.c42
-rw-r--r--sys/net80211/ieee80211_power.c3
-rw-r--r--sys/net80211/ieee80211_proto.c8
-rw-r--r--sys/net80211/ieee80211_proto.h42
-rw-r--r--sys/net80211/ieee80211_var.h18
9 files changed, 207 insertions, 79 deletions
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 285e666..efef383 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -136,6 +136,8 @@ ieee80211_ht_attach(struct ieee80211com *ic)
ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_RX;
if (ic->ic_htcaps & IEEE80211_HTC_AMSDU)
ic->ic_flags_ext |= IEEE80211_FEXT_AMSDU_TX;
+
+ ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE;
}
}
@@ -1408,6 +1410,36 @@ ieee80211_set_basic_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs)
}
/*
+ * Update the HTINFO ie for a beacon frame.
+ */
+void
+ieee80211_ht_update_beacon(struct ieee80211com *ic,
+ struct ieee80211_beacon_offsets *bo)
+{
+#define PROTMODE (IEEE80211_HTINFO_OPMODE|IEEE80211_HTINFO_NONHT_PRESENT)
+ struct ieee80211_ie_htinfo *ht =
+ (struct ieee80211_ie_htinfo *) bo->bo_htinfo;
+
+ /* XXX only update on channel change */
+ ht->hi_ctrlchannel = ieee80211_chan2ieee(ic, ic->ic_bsschan);
+ ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PROH;
+ if (IEEE80211_IS_CHAN_HT40U(ic->ic_bsschan))
+ ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_ABOVE;
+ else if (IEEE80211_IS_CHAN_HT40D(ic->ic_bsschan))
+ ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_BELOW;
+ else
+ ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_NONE;
+ if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan))
+ ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040;
+
+ /* protection mode */
+ ht->hi_byte2 = (ht->hi_byte2 &~ PROTMODE) | ic->ic_curhtprotmode;
+
+ /* XXX propagate to vendor ie's */
+#undef PROTMODE
+}
+
+/*
* Add body of an HTINFO information element.
*/
static uint8_t *
@@ -1431,9 +1463,7 @@ ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni)
if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan))
frm[0] |= IEEE80211_HTINFO_TXWIDTH_2040;
- frm[1] = (ic->ic_flags_ext & IEEE80211_FEXT_PUREN) ?
- IEEE80211_HTINFO_OPMODE_PURE : IEEE80211_HTINFO_OPMODE_MIXED;
- /* XXX IEEE80211_HTINFO_NONHT_PRESENT */
+ frm[1] = ic->ic_curhtprotmode;
frm += 5;
diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h
index fc87f1f..5f2689b 100644
--- a/sys/net80211/ieee80211_ht.h
+++ b/sys/net80211/ieee80211_ht.h
@@ -110,4 +110,7 @@ uint8_t *ieee80211_add_htcap(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htcap_vendor(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htinfo(uint8_t *, struct ieee80211_node *);
uint8_t *ieee80211_add_htinfo_vendor(uint8_t *, struct ieee80211_node *);
+struct ieee80211_beacon_offsets;
+void ieee80211_ht_update_beacon(struct ieee80211com *,
+ struct ieee80211_beacon_offsets *);
#endif /* _NET80211_IEEE80211_HT_H_ */
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index ccabaed..fc62e28 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -76,6 +76,7 @@ static void ieee80211_node_table_init(struct ieee80211com *ic,
int inact, int keymaxix);
static void ieee80211_node_table_reset(struct ieee80211_node_table *);
static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
+static void ieee80211_erp_timeout(struct ieee80211com *);
MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
@@ -1571,6 +1572,10 @@ ieee80211_node_timeout(void *arg)
ieee80211_scan_timeout(ic);
ieee80211_timeout_stations(&ic->ic_sta);
+ IEEE80211_LOCK(ic);
+ ieee80211_erp_timeout(ic);
+ IEEE80211_UNLOCK(ic);
+
callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
ieee80211_node_timeout, ic);
}
@@ -1637,6 +1642,13 @@ ieee80211_dump_nodes(struct ieee80211_node_table *nt)
(ieee80211_iter_func *) ieee80211_dump_node, nt);
}
+void
+ieee80211_notify_erp(struct ieee80211com *ic)
+{
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ ieee80211_beacon_notify(ic, IEEE80211_BEACON_ERP);
+}
+
/*
* Handle a station joining an 11g network.
*/
@@ -1653,9 +1665,9 @@ ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
*/
if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
ic->ic_longslotsta++;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "[%s] station needs long slot time, count %d\n",
- ether_sprintf(ni->ni_macaddr), ic->ic_longslotsta);
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "station needs long slot time, count %d",
+ ic->ic_longslotsta);
/* XXX vap's w/ conflicting needs won't work */
if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
/*
@@ -1673,30 +1685,30 @@ ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
*/
if (!ieee80211_iserp_rateset(ic, &ni->ni_rates)) {
ic->ic_nonerpsta++;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "[%s] station is !ERP, %d non-ERP stations associated\n",
- ether_sprintf(ni->ni_macaddr), ic->ic_nonerpsta);
- /*
- * If protection is configured, enable it.
- */
- if (ic->ic_protmode != IEEE80211_PROT_NONE) {
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "%s: enable use of protection\n", __func__);
- ic->ic_flags |= IEEE80211_F_USEPROT;
- }
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "station is !ERP, %d non-ERP stations associated",
+ ic->ic_nonerpsta);
/*
* If station does not support short preamble
* then we must enable use of Barker preamble.
*/
if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) {
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "[%s] station needs long preamble\n",
- ether_sprintf(ni->ni_macaddr));
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "%s", "station needs long preamble");
ic->ic_flags |= IEEE80211_F_USEBARKER;
ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
}
- if (ic->ic_nonerpsta == 1)
- ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ /*
+ * If protection is configured, enable it.
+ */
+ if (ic->ic_protmode != IEEE80211_PROT_NONE &&
+ ic->ic_nonerpsta == 1 &&
+ (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+ "%s: enable use of protection\n", __func__);
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ ieee80211_notify_erp(ic);
+ }
} else
ni->ni_flags |= IEEE80211_NODE_ERP;
}
@@ -1734,9 +1746,9 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
} else
newassoc = 0;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG,
- "[%s] station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s\n",
- ether_sprintf(ni->ni_macaddr), newassoc ? "" : "re",
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
+ "station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s",
+ newassoc ? "" : "re",
IEEE80211_NODE_AID(ni),
ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
@@ -1760,6 +1772,23 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
ieee80211_notify_node_join(ic, ni, newassoc);
}
+static void
+disable_protection(struct ieee80211com *ic)
+{
+ KASSERT(ic->ic_nonerpsta == 0 &&
+ (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0,
+ ("%d non ERP stations, flags 0x%x", ic->ic_nonerpsta,
+ ic->ic_flags_ext));
+
+ ic->ic_flags &= ~IEEE80211_F_USEPROT;
+ /* XXX verify mode? */
+ if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
+ ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
+ ic->ic_flags &= ~IEEE80211_F_USEBARKER;
+ }
+ ieee80211_notify_erp(ic);
+}
+
/*
* Handle a station leaving an 11g network.
*/
@@ -1778,9 +1807,9 @@ ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
KASSERT(ic->ic_longslotsta > 0,
("bogus long slot station count %d", ic->ic_longslotsta));
ic->ic_longslotsta--;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "[%s] long slot time station leaves, count now %d\n",
- ether_sprintf(ni->ni_macaddr), ic->ic_longslotsta);
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "long slot time station leaves, count now %d",
+ ic->ic_longslotsta);
if (ic->ic_longslotsta == 0) {
/*
* Re-enable use of short slot time if supported
@@ -1802,27 +1831,44 @@ ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
KASSERT(ic->ic_nonerpsta > 0,
("bogus non-ERP station count %d", ic->ic_nonerpsta));
ic->ic_nonerpsta--;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "[%s] non-ERP station leaves, count now %d\n",
- ether_sprintf(ni->ni_macaddr), ic->ic_nonerpsta);
- if (ic->ic_nonerpsta == 0) {
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
+ "non-ERP station leaves, count now %d%s", ic->ic_nonerpsta,
+ (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) ?
+ " (non-ERP sta present)" : "");
+ if (ic->ic_nonerpsta == 0 &&
+ (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
"%s: disable use of protection\n", __func__);
- ic->ic_flags &= ~IEEE80211_F_USEPROT;
- /* XXX verify mode? */
- if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
- "%s: re-enable use of short preamble\n",
- __func__);
- ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
- ic->ic_flags &= ~IEEE80211_F_USEBARKER;
- }
- ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+ disable_protection(ic);
}
}
}
/*
+ * Time out presence of an overlapping bss with non-ERP
+ * stations. When operating in hostap mode we listen for
+ * beacons from other stations and if we identify a non-ERP
+ * station is present we enable protection. To identify
+ * when all non-ERP stations are gone we time out this
+ * condition.
+ */
+static void
+ieee80211_erp_timeout(struct ieee80211com *ic)
+{
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
+ time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+ "%s\n", "age out non-ERP sta present on channel");
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR;
+ if (ic->ic_nonerpsta == 0)
+ disable_protection(ic);
+ }
+}
+
+/*
* Handle bookkeeping for station deauthentication/disassociation
* when operating as an ap.
*/
@@ -1831,9 +1877,8 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
{
struct ieee80211_node_table *nt = ni->ni_table;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG,
- "[%s] station with aid %d leaves\n",
- ether_sprintf(ni->ni_macaddr), IEEE80211_NODE_AID(ni));
+ IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
+ "station with aid %d leaves", IEEE80211_NODE_AID(ni));
KASSERT(ic->ic_opmode != IEEE80211_M_STA,
("unexpected operating mode %u", ic->ic_opmode));
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index cb960d1..ccdf6a9 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -55,6 +55,9 @@
#define IEEE80211_TRANS_WAIT 2 /* mgt frame tx timer (secs) */
+/* threshold for aging overlapping non-ERP bss */
+#define IEEE80211_NONERP_PRESENT_AGE msecs_to_ticks(60*1000)
+
#define IEEE80211_NODE_HASHSIZE 32
/* simple hash is enough for variation of macaddr */
#define IEEE80211_NODE_HASH(addr) \
@@ -307,6 +310,8 @@ void ieee80211_dump_node(struct ieee80211_node_table *,
struct ieee80211_node *);
void ieee80211_dump_nodes(struct ieee80211_node_table *);
+void ieee80211_notify_erp(struct ieee80211com *);
+
struct ieee80211_node *ieee80211_fakeup_adhoc_node(
struct ieee80211_node_table *, const uint8_t macaddr[]);
struct ieee80211_scanparams;
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 5041ac5..ea159f8 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -2004,9 +2004,10 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
* Allocate a beacon frame and fillin the appropriate bits.
*/
struct mbuf *
-ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni,
+ieee80211_beacon_alloc(struct ieee80211_node *ni,
struct ieee80211_beacon_offsets *bo)
{
+ struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_frame *wh;
struct mbuf *m;
@@ -2103,14 +2104,13 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni,
frm += sizeof(struct ieee80211_tim_ie);
bo->bo_tim_len = 1;
}
- bo->bo_trailer = frm;
+ bo->bo_tim_trailer = frm;
if (ic->ic_flags & IEEE80211_F_DOTH)
frm = ieee80211_add_countryie(frm, ic,
ic->ic_countrycode, ic->ic_location);
if (ic->ic_flags & IEEE80211_F_WME) {
bo->bo_wme = frm;
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
- ic->ic_flags &= ~IEEE80211_F_WMEUPDATE;
} else
bo->bo_wme = NULL;
if (ic->ic_flags & IEEE80211_F_WPA)
@@ -2131,7 +2131,7 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni,
}
} else
bo->bo_htinfo = NULL;
- bo->bo_trailer_len = frm - bo->bo_trailer;
+ bo->bo_tim_trailer_len = frm - bo->bo_tim_trailer;
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
@@ -2153,9 +2153,10 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni,
* Update the dynamic parts of a beacon frame based on the current state.
*/
int
-ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
+ieee80211_beacon_update(struct ieee80211_node *ni,
struct ieee80211_beacon_offsets *bo, struct mbuf *m, int mcast)
{
+ struct ieee80211com *ic = ni->ni_ic;
int len_changed = 0;
uint16_t capinfo;
@@ -2199,25 +2200,21 @@ ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
wme->wme_hipri_traffic =
wme->wme_hipri_switch_hysteresis;
}
- if (ic->ic_flags & IEEE80211_F_WMEUPDATE) {
+ if (isset(bo->bo_flags, IEEE80211_BEACON_WME)) {
(void) ieee80211_add_wme_param(bo->bo_wme, wme);
- ic->ic_flags &= ~IEEE80211_F_WMEUPDATE;
+ clrbit(bo->bo_flags, IEEE80211_BEACON_WME);
}
}
- if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) {
- struct ieee80211_ie_htinfo *ht =
- (struct ieee80211_ie_htinfo *) bo->bo_htinfo;
- if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan))
- ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040;
- else
- ht->hi_byte1 &= ~IEEE80211_HTINFO_TXWIDTH_2040;
+ if (isset(bo->bo_flags, IEEE80211_BEACON_HTINFO)) {
+ ieee80211_ht_update_beacon(ic, bo);
+ clrbit(bo->bo_flags, IEEE80211_BEACON_HTINFO);
}
if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* NB: no IBSS support*/
struct ieee80211_tim_ie *tie =
(struct ieee80211_tim_ie *) bo->bo_tim;
- if (ic->ic_flags & IEEE80211_F_TIMUPDATE) {
+ if (isset(bo->bo_flags, IEEE80211_BEACON_TIM)) {
u_int timlen, timoff, i;
/*
* ATIM/DTIM needs updating. If it fits in the
@@ -2254,10 +2251,11 @@ ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
if (timlen != bo->bo_tim_len) {
/* copy up/down trailer */
int adjust = tie->tim_bitmap+timlen
- - bo->bo_trailer;
- ovbcopy(bo->bo_trailer, bo->bo_trailer+adjust,
- bo->bo_trailer_len);
- bo->bo_trailer += adjust;
+ - bo->bo_tim_trailer;
+ ovbcopy(bo->bo_tim_trailer,
+ bo->bo_tim_trailer+adjust,
+ bo->bo_tim_trailer_len);
+ bo->bo_tim_trailer += adjust;
bo->bo_wme += adjust;
bo->bo_erp += adjust;
bo->bo_htinfo += adjust;
@@ -2271,7 +2269,7 @@ ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
memcpy(tie->tim_bitmap, ic->ic_tim_bitmap + timoff,
bo->bo_tim_len);
- ic->ic_flags &= ~IEEE80211_F_TIMUPDATE;
+ clrbit(bo->bo_flags, IEEE80211_BEACON_TIM);
IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
"%s: TIM updated, pending %u, off %u, len %u\n",
@@ -2287,12 +2285,12 @@ ieee80211_beacon_update(struct ieee80211com *ic, struct ieee80211_node *ni,
tie->tim_bitctl |= 1;
else
tie->tim_bitctl &= ~1;
- if (ic->ic_flags_ext & IEEE80211_FEXT_ERPUPDATE) {
+ if (isset(bo->bo_flags, IEEE80211_BEACON_ERP)) {
/*
* ERP element needs updating.
*/
(void) ieee80211_add_erp(bo->bo_erp, ic);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_ERPUPDATE;
+ clrbit(bo->bo_flags, IEEE80211_BEACON_ERP);
}
}
IEEE80211_BEACON_UNLOCK(ic);
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 2064807..e764e1f 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -163,7 +163,8 @@ ieee80211_set_tim(struct ieee80211_node *ni, int set)
clrbit(ic->ic_tim_bitmap, aid);
ic->ic_ps_pending--;
}
- ic->ic_flags |= IEEE80211_F_TIMUPDATE;
+ /* NB: we know ic is in RUN state so no need to check */
+ ic->ic_update_beacon(ic, IEEE80211_BEACON_TIM);
}
IEEE80211_BEACON_UNLOCK(ic);
}
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index dd7d478..6084516 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -93,6 +93,11 @@ const char *ieee80211_wme_acnames[] = {
static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
+static void
+null_update_beacon(struct ieee80211com *ic, int item)
+{
+}
+
void
ieee80211_proto_attach(struct ieee80211com *ic)
{
@@ -118,6 +123,7 @@ ieee80211_proto_attach(struct ieee80211com *ic)
/* protocol state change handler */
ic->ic_newstate = ieee80211_newstate;
+ ic->ic_update_beacon = null_update_beacon;
/* initialize management frame handlers */
ic->ic_recv_mgmt = ieee80211_recv_mgmt;
@@ -859,7 +865,7 @@ ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
*/
wme->wme_bssChanParams.cap_info =
(wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
- ic->ic_flags |= IEEE80211_F_WMEUPDATE;
+ ieee80211_beacon_notify(ic, IEEE80211_BEACON_WME);
}
wme->wme_update(ic);
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index 1a2926a..41ed3ba 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -246,20 +246,48 @@ extern const char *ieee80211_wme_acnames[];
* can update the frame later w/ minimal overhead.
*/
struct ieee80211_beacon_offsets {
+ uint8_t bo_flags[4]; /* update/state flags */
uint16_t *bo_caps; /* capabilities */
+ uint8_t *bo_cfp; /* start of CFParms element */
uint8_t *bo_tim; /* start of atim/dtim */
uint8_t *bo_wme; /* start of WME parameters */
- uint8_t *bo_trailer; /* start of fixed-size trailer */
+ uint8_t *bo_tim_trailer;/* start of fixed-size trailer */
uint16_t bo_tim_len; /* atim/dtim length in bytes */
- uint16_t bo_trailer_len; /* trailer length in bytes */
+ uint16_t bo_tim_trailer_len;/* tim trailer length in bytes */
uint8_t *bo_erp; /* start of ERP element */
uint8_t *bo_htinfo; /* start of HT info element */
+ uint8_t *bo_appie; /* start of AppIE element */
+ uint16_t bo_appie_len; /* AppIE length in bytes */
+ uint16_t bo_csa_trailer_len;;
+ uint8_t *bo_csa; /* start of CSA element */
};
-struct mbuf *ieee80211_beacon_alloc(struct ieee80211com *,
- struct ieee80211_node *, struct ieee80211_beacon_offsets *);
-int ieee80211_beacon_update(struct ieee80211com *,
- struct ieee80211_node *, struct ieee80211_beacon_offsets *,
- struct mbuf *, int broadcast);
+struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *,
+ struct ieee80211_beacon_offsets *);
+
+/*
+ * Beacon frame updates are signaled through calls to ic_update_beacon
+ * with one of the IEEE80211_BEACON_* tokens defined below. For devices
+ * that construct beacon frames on the host this can trigger a rebuild
+ * or defer the processing. For devices that offload beacon frame
+ * handling this callback can be used to signal a rebuild. The bo_flags
+ * array in the ieee80211_beacon_offsets structure is intended to record
+ * deferred processing requirements; ieee80211_beacon_update uses the
+ * state to optimize work. Since this structure is owned by the driver
+ * and not visible to the 802.11 layer drivers must supply an ic_update_beacon
+ * callback that marks the flag bits and schedules (as necessary) an update.
+ */
+enum {
+ IEEE80211_BEACON_CAPS = 0, /* capabilities */
+ IEEE80211_BEACON_TIM = 1, /* DTIM/ATIM */
+ IEEE80211_BEACON_WME = 2,
+ IEEE80211_BEACON_ERP = 3, /* Extended Rate Phy */
+ IEEE80211_BEACON_HTINFO = 4, /* HT Information */
+ IEEE80211_BEACON_APPIE = 5, /* Application IE's */
+ IEEE80211_BEACON_CFP = 6, /* CFParms */
+ IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */
+};
+int ieee80211_beacon_update(struct ieee80211_node *,
+ struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
/*
* Notification methods called from the 802.11 state machine.
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index d4d3897..d66198b 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -175,6 +175,8 @@ struct ieee80211com {
uint16_t ic_nonerpsta; /* # non-ERP stations */
uint16_t ic_longslotsta; /* # long slot time stations */
uint16_t ic_sta_assoc; /* stations associated */
+ uint8_t ic_curhtprotmode;/* HTINFO bss state */
+ int ic_lastnonerp; /* last time non-ERP sta noted*/
struct ifqueue ic_mgtq;
enum ieee80211_state ic_state; /* 802.11 state */
@@ -237,6 +239,8 @@ struct ieee80211com {
const struct ieee80211_bpf_params *);
/* reset device state after 802.11 parameter/state change */
int (*ic_reset)(struct ifnet *);
+ /* [schedule] beacon frame update */
+ void (*ic_update_beacon)(struct ieee80211com *, int);
/* update device state for 802.11 slot time change */
void (*ic_updateslot)(struct ifnet *);
/* new station association callback/notification */
@@ -313,7 +317,6 @@ struct ieee80211com {
#define IEEE80211_F_DATAPAD 0x00080000 /* CONF: do alignment pad */
#define IEEE80211_F_USEPROT 0x00100000 /* STATUS: protection enabled */
#define IEEE80211_F_USEBARKER 0x00200000 /* STATUS: use barker preamble*/
-#define IEEE80211_F_TIMUPDATE 0x00400000 /* STATUS: update beacon tim */
#define IEEE80211_F_WPA1 0x00800000 /* CONF: WPA enabled */
#define IEEE80211_F_WPA2 0x01000000 /* CONF: WPA2 enabled */
#define IEEE80211_F_WPA 0x01800000 /* CONF: WPA/WPA2 enabled */
@@ -321,7 +324,6 @@ struct ieee80211com {
#define IEEE80211_F_COUNTERM 0x04000000 /* CONF: TKIP countermeasures */
#define IEEE80211_F_HIDESSID 0x08000000 /* CONF: hide SSID in beacon */
#define IEEE80211_F_NOBRIDGE 0x10000000 /* CONF: dis. internal bridge */
-#define IEEE80211_F_WMEUPDATE 0x20000000 /* STATUS: update beacon wme */
#define IEEE80211_F_DOTH 0x40000000 /* CONF: 11h enabled */
/* Atheros protocol-specific flags */
@@ -336,7 +338,7 @@ struct ieee80211com {
#define IEEE80211_FEXT_INACT 0x00000002 /* CONF: sta inact handling */
/* 0x00000006 reserved */
#define IEEE80211_FEXT_BGSCAN 0x00000008 /* STATUS: complete bgscan */
-#define IEEE80211_FEXT_ERPUPDATE 0x00000200 /* STATUS: update ERP element */
+#define IEEE80211_FEXT_NONERP_PR 0x00000200 /* STATUS: non-ERP sta present*/
#define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: do bmiss in s/w */
#define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/
#define IEEE80211_FEXT_HT 0x00080000 /* CONF: HT supported */
@@ -460,6 +462,16 @@ ieee80211_anyhdrspace(struct ieee80211com *ic, const void *data)
return size;
}
+/*
+ * Notify a driver that beacon state has been updated.
+ */
+static __inline void
+ieee80211_beacon_notify(struct ieee80211com *ic, int what)
+{
+ if (ic->ic_state == IEEE80211_S_RUN)
+ ic->ic_update_beacon(ic, what);
+}
+
#define IEEE80211_MSG_11N 0x80000000 /* 11n mode debug */
#define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */
#define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalant */
OpenPOWER on IntegriCloud