diff options
author | sam <sam@FreeBSD.org> | 2007-09-17 19:07:24 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2007-09-17 19:07:24 +0000 |
commit | d2e6b6eac7970920eccfe2d65f03d9ca3c6542ae (patch) | |
tree | dd53d98ae592f4e1d6caa3458fddec6956ad9dd5 /sys | |
parent | b6c4c36f72b670e2821f1e630182572a7b96337c (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/dev/ath/if_ath.c | 16 | ||||
-rw-r--r-- | sys/dev/ral/rt2560.c | 15 | ||||
-rw-r--r-- | sys/dev/ral/rt2661.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/if_rum.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/if_ural.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ht.c | 36 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ht.h | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.c | 129 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 5 | ||||
-rw-r--r-- | sys/net80211/ieee80211_output.c | 42 | ||||
-rw-r--r-- | sys/net80211/ieee80211_power.c | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 8 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.h | 42 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 18 |
14 files changed, 236 insertions, 87 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 5654563..3f74add 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -124,6 +124,7 @@ static void ath_setslottime(struct ath_softc *); static void ath_updateslot(struct ifnet *); static int ath_beaconq_setup(struct ath_hal *); static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); +static void ath_beacon_update(struct ieee80211com *, int item); static void ath_beacon_setup(struct ath_softc *, struct ath_buf *); static void ath_beacon_proc(void *, int); static void ath_bstuck_proc(void *, int); @@ -625,6 +626,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ic->ic_crypto.cs_key_update_begin = ath_key_update_begin; ic->ic_crypto.cs_key_update_end = ath_key_update_end; ic->ic_raw_xmit = ath_raw_xmit; + ic->ic_update_beacon = ath_beacon_update; /* complete initialization */ ieee80211_media_init(ic, ath_media_change, ieee80211_media_status); @@ -2442,7 +2444,6 @@ ath_beaconq_config(struct ath_softc *sc) static int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) { - struct ieee80211com *ic = ni->ni_ic; struct ath_buf *bf; struct mbuf *m; int error; @@ -2458,7 +2459,7 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni) * we assume the mbuf routines will return us something * with this alignment (perhaps should assert). */ - m = ieee80211_beacon_alloc(ic, ni, &sc->sc_boff); + m = ieee80211_beacon_alloc(ni, &sc->sc_boff); if (m == NULL) { DPRINTF(sc, ATH_DEBUG_BEACON, "%s: cannot get mbuf\n", __func__); @@ -2553,6 +2554,15 @@ ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf) #undef USE_SHPREAMBLE } +static void +ath_beacon_update(struct ieee80211com *ic, int item) +{ + struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ieee80211_beacon_offsets *bo = &sc->sc_boff; + + setbit(bo->bo_flags, item); +} + /* * Append the contents of src to dst; both queues * are assumed to be locked. @@ -2626,7 +2636,7 @@ ath_beacon_proc(void *arg, int pending) m = bf->bf_m; nmcastq = sc->sc_mcastq.axq_depth; ncabq = ath_hal_numtxpending(ah, cabq->axq_qnum); - if (ieee80211_beacon_update(ic, bf->bf_node, &sc->sc_boff, m, ncabq+nmcastq)) { + if (ieee80211_beacon_update(bf->bf_node, &sc->sc_boff, m, ncabq+nmcastq)) { /* XXX too conservative? */ bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap); error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m, diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index b3bb76a..b72ca40 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -105,6 +105,7 @@ static void rt2560_tx_intr(struct rt2560_softc *); static void rt2560_prio_intr(struct rt2560_softc *); static void rt2560_decryption_intr(struct rt2560_softc *); static void rt2560_rx_intr(struct rt2560_softc *); +static void rt2560_beacon_update(struct ieee80211com *, int item); static void rt2560_beacon_expire(struct rt2560_softc *); static void rt2560_wakeup_expire(struct rt2560_softc *); static uint8_t rt2560_rxrate(struct rt2560_rx_desc *); @@ -301,6 +302,7 @@ rt2560_attach(device_t dev, int id) sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = rt2560_newstate; ic->ic_raw_xmit = rt2560_raw_xmit; + ic->ic_update_beacon = rt2560_beacon_update; ieee80211_media_init(ic, rt2560_media_change, ieee80211_media_status); bpfattach2(ifp, DLT_IEEE802_11_RADIO, @@ -780,7 +782,7 @@ rt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS) { - m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo); + m = ieee80211_beacon_alloc(ni, &sc->sc_bo); if (m == NULL) { device_printf(sc->sc_dev, "could not allocate beacon\n"); @@ -1277,6 +1279,15 @@ rt2560_rx_intr(struct rt2560_softc *sc) RAL_WRITE(sc, RT2560_SECCSR0, RT2560_KICK_DECRYPT); } +static void +rt2560_beacon_update(struct ieee80211com *ic, int item) +{ + struct rt2560_softc *sc = ic->ic_ifp->if_softc; + struct ieee80211_beacon_offsets *bo = &sc->sc_bo; + + setbit(bo->bo_flags, item); +} + /* * This function is called periodically in IBSS mode when a new beacon must be * sent out. @@ -1301,7 +1312,7 @@ rt2560_beacon_expire(struct rt2560_softc *sc) bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->bcnq.data_dmat, data->map); - ieee80211_beacon_update(ic, data->ni, &sc->sc_bo, data->m, 1); + ieee80211_beacon_update(data->ni, &sc->sc_bo, data->m, 1); if (bpf_peers_present(ic->ic_rawbpf)) bpf_mtap(ic->ic_rawbpf, data->m); diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index b7086f5..60171ee 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -2803,7 +2803,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc) struct mbuf *m0; int rate; - m0 = ieee80211_beacon_alloc(ic, ic->ic_bss, &bo); + m0 = ieee80211_beacon_alloc(ic->ic_bss, &bo); if (m0 == NULL) { device_printf(sc->sc_dev, "could not allocate beacon frame\n"); return ENOBUFS; diff --git a/sys/dev/usb/if_rum.c b/sys/dev/usb/if_rum.c index e2c5a18..aa060f4 100644 --- a/sys/dev/usb/if_rum.c +++ b/sys/dev/usb/if_rum.c @@ -2278,7 +2278,7 @@ rum_prepare_beacon(struct rum_softc *sc) struct mbuf *m0; int rate; - m0 = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo); + m0 = ieee80211_beacon_alloc(ic->ic_bss, &sc->sc_bo); if (m0 == NULL) { return ENOBUFS; } diff --git a/sys/dev/usb/if_ural.c b/sys/dev/usb/if_ural.c index 47de4d7..819a730 100644 --- a/sys/dev/usb/if_ural.c +++ b/sys/dev/usb/if_ural.c @@ -752,7 +752,7 @@ ural_task(void *xarg) if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_IBSS) { - m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo); + m = ieee80211_beacon_alloc(ni, &sc->sc_bo); if (m == NULL) { printf("%s: could not allocate beacon\n", device_get_nameunit(sc->sc_dev)); 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 */ |