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)
This commit is contained in:
Sam Leffler 2007-09-17 19:07:24 +00:00
parent 2badb3db3c
commit b105a06908
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172211
14 changed files with 236 additions and 87 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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));

View File

@ -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;
}
}
@ -1407,6 +1409,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.
*/
@ -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;

View File

@ -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_ */

View File

@ -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,26 +1831,43 @@ 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));

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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.

View File

@ -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 */