[net80211] quiet IE handling improvements

* on the station side, only call the quiet time IE method if we have a
  quiet IE - otherwise call the NULL method once, and then don't waste
  time calling NULL

* on the beacon generation side - force a beacon regeneration each time
  quiet time is enabled/disabled.  Without this, enabling/disabling quiet
  time IE would cause the beacon contents to be corrupted since none of
  the "move contents around" logic (like for CSA and TIM handling) is implemented.

This changes the size of ieee80211_node so it requires a kernel recompile,
but no userland recompile.

Tested:

* AR9380, AP mode, enabling/disabling quiet time IE
* AR9380, STA mode, with upcoming driver changes.
This commit is contained in:
Adrian Chadd 2017-02-09 04:07:30 +00:00
parent 4b30cd46a5
commit 4d3dcce5bb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313462
5 changed files with 115 additions and 15 deletions

View File

@ -249,6 +249,11 @@ struct ieee80211_node {
struct ieee80211vap *ni_wdsvap; /* associated WDS vap */
void *ni_rctls; /* private ratectl state */
/* quiet time IE state for the given node */
uint32_t ni_quiet_ie_set; /* Quiet time IE was seen */
struct ieee80211_quiet_ie ni_quiet_ie; /* last seen quiet IE */
uint64_t ni_spare[3];
};
MALLOC_DECLARE(M_80211_NODE);

View File

@ -2128,7 +2128,6 @@ ieee80211_add_qos(uint8_t *frm, const struct ieee80211_node *ni)
* Send a probe request frame with the specified ssid
* and any optional information element data.
*/
/* XXX VHT? */
int
ieee80211_send_probereq(struct ieee80211_node *ni,
const uint8_t sa[IEEE80211_ADDR_LEN],
@ -2438,7 +2437,6 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
/* XXX VHT? */
/*
* asreq frame format
* [2] capability information
@ -2700,7 +2698,6 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
* Space is left to prepend and 802.11 header at the
* front but it's left to the caller to fill in.
*/
/* XXX VHT? */
struct mbuf *
ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy)
{
@ -3035,7 +3032,6 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
}
}
/* XXX VHT? */
static void
ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
struct ieee80211_node *ni)
@ -3163,15 +3159,23 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
} else
bo->bo_csa = frm;
bo->bo_quiet = NULL;
if (vap->iv_flags & IEEE80211_F_DOTH) {
bo->bo_quiet = frm;
if (IEEE80211_IS_CHAN_DFS(ic->ic_bsschan) &&
(vap->iv_flags_ext & IEEE80211_FEXT_DFS)) {
if (vap->iv_quiet)
(vap->iv_flags_ext & IEEE80211_FEXT_DFS) &&
(vap->iv_quiet == 1)) {
/*
* We only insert the quiet IE offset if
* the quiet IE is enabled. Otherwise don't
* put it here or we'll just overwrite
* some other beacon contents.
*/
if (vap->iv_quiet) {
bo->bo_quiet = frm;
frm = ieee80211_add_quiet(frm,vap, 0);
}
}
} else
bo->bo_quiet = frm;
}
if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) {
bo->bo_erp = frm;
@ -3239,7 +3243,6 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
/*
* Allocate a beacon frame and fillin the appropriate bits.
*/
/* XXX VHT? */
struct mbuf *
ieee80211_beacon_alloc(struct ieee80211_node *ni)
{
@ -3251,6 +3254,14 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni)
int pktlen;
uint8_t *frm;
/*
* Update the "We're putting the quiet IE in the beacon" state.
*/
if (vap->iv_quiet == 1)
vap->iv_flags_ext |= IEEE80211_FEXT_QUIET_IE;
else if (vap->iv_quiet == 0)
vap->iv_flags_ext &= ~IEEE80211_FEXT_QUIET_IE;
/*
* beacon frame format
*
@ -3286,7 +3297,6 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni)
* NB: we allocate the max space required for the TIM bitmap.
* XXX how big is this?
*/
/* XXX VHT? */
pktlen = 8 /* time stamp */
+ sizeof(uint16_t) /* beacon interval */
+ sizeof(uint16_t) /* capabilities */
@ -3392,6 +3402,42 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast)
return 1; /* just assume length changed */
}
/*
* Handle the quiet time element being added and removed.
* Again, for now we just cheat and reconstruct the whole
* beacon - that way the gap is provided as appropriate.
*
* So, track whether we have already added the IE versus
* whether we want to be adding the IE.
*/
if ((vap->iv_flags_ext & IEEE80211_FEXT_QUIET_IE) &&
(vap->iv_quiet == 0)) {
/*
* Quiet time beacon IE enabled, but it's disabled;
* recalc
*/
vap->iv_flags_ext &= ~IEEE80211_FEXT_QUIET_IE;
ieee80211_beacon_construct(m,
mtod(m, uint8_t*) + sizeof(struct ieee80211_frame), ni);
/* XXX do WME aggressive mode processing? */
IEEE80211_UNLOCK(ic);
return 1; /* just assume length changed */
}
if (((vap->iv_flags_ext & IEEE80211_FEXT_QUIET_IE) == 0) &&
(vap->iv_quiet == 1)) {
/*
* Quiet time beacon IE disabled, but it's now enabled;
* recalc
*/
vap->iv_flags_ext |= IEEE80211_FEXT_QUIET_IE;
ieee80211_beacon_construct(m,
mtod(m, uint8_t*) + sizeof(struct ieee80211_frame), ni);
/* XXX do WME aggressive mode processing? */
IEEE80211_UNLOCK(ic);
return 1; /* just assume length changed */
}
wh = mtod(m, struct ieee80211_frame *);
/*
@ -3600,10 +3646,17 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast)
vap->iv_csa_count++;
/* NB: don't clear IEEE80211_BEACON_CSA */
}
/*
* Only add the quiet time IE if we've enabled it
* as appropriate.
*/
if (IEEE80211_IS_CHAN_DFS(ic->ic_bsschan) &&
(vap->iv_flags_ext & IEEE80211_FEXT_DFS) ){
if (vap->iv_quiet)
(vap->iv_flags_ext & IEEE80211_FEXT_DFS)) {
if (vap->iv_quiet &&
(vap->iv_flags_ext & IEEE80211_FEXT_QUIET_IE)) {
ieee80211_add_quiet(bo->bo_quiet, vap, 1);
}
}
if (isset(bo->bo_flags, IEEE80211_BEACON_ERP)) {
/*

View File

@ -391,6 +391,8 @@ enum {
IEEE80211_BEACON_TDMA = 9, /* TDMA Info */
IEEE80211_BEACON_ATH = 10, /* ATH parameters */
IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */
IEEE80211_BEACON_QUIET = 12, /* Quiet time IE */
IEEE80211_BEACON_VHTINFO = 13, /* VHT information */
};
int ieee80211_beacon_update(struct ieee80211_node *,
struct mbuf *, int mcast);

View File

@ -1319,6 +1319,27 @@ startbgscan(struct ieee80211vap *vap)
ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)));
}
#ifdef notyet
/*
* Compare two quiet IEs and return if they are equivalent.
*
* The tbttcount isnt checked - that's not part of the configuration.
*/
static int
compare_quiet_ie(const struct ieee80211_quiet_ie *q1,
const struct ieee80211_quiet_ie *q2)
{
if (q1->period != q2->period)
return (0);
if (le16dec(&q1->duration) != le16dec(&q2->duration))
return (0);
if (le16dec(&q1->offset) != le16dec(&q2->offset))
return (0);
return (1);
}
#endif
static void
sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
const struct ieee80211_rx_stats *rxs,
@ -1449,8 +1470,26 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
ht_state_change = 1;
}
if (scan.quiet)
/*
* If we have a quiet time IE then report it up to
* the driver.
*
* Otherwise, inform the driver that the quiet time
* IE has disappeared - only do that once rather than
* spamming it each time.
*/
if (scan.quiet) {
ic->ic_set_quiet(ni, scan.quiet);
ni->ni_quiet_ie_set = 1;
memcpy(&ni->ni_quiet_ie, scan.quiet,
sizeof(struct ieee80211_quiet_ie));
} else {
if (ni->ni_quiet_ie_set == 1)
ic->ic_set_quiet(ni, NULL);
ni->ni_quiet_ie_set = 0;
bzero(&ni->ni_quiet_ie,
sizeof(struct ieee80211_quiet_ie));
}
if (scan.tim != NULL) {
struct ieee80211_tim_ie *tim =

View File

@ -636,12 +636,13 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FEXT_SEQNO_OFFLOAD 0x00100000 /* CONF: driver does seqno insertion/allocation */
#define IEEE80211_FEXT_FRAG_OFFLOAD 0x00200000 /* CONF: hardware does 802.11 fragmentation + assignment */
#define IEEE80211_FEXT_VHT 0x00400000 /* CONF: VHT support */
#define IEEE80211_FEXT_QUIET_IE 0x00800000 /* STATUS: quiet IE in a beacon has been added */
#define IEEE80211_FEXT_BITS \
"\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \
"\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \
"\20BPF\21WDSLEGACY\22PROBECHAN\23UNIQMAC\24SCAN_OFFLOAD\25SEQNO_OFFLOAD" \
"\26VHT"
"\26VHT\27QUIET_IE"
/* ic_flags_ht/iv_flags_ht */
#define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */