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:
parent
2badb3db3c
commit
b105a06908
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172211
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user