From owner-svn-src-head@FreeBSD.ORG Tue Nov 8 04:00:25 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A9B7D106566C; Tue, 8 Nov 2011 04:00:25 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 989FD8FC0A; Tue, 8 Nov 2011 04:00:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pA840PjE012111; Tue, 8 Nov 2011 04:00:25 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pA840PMj012100; Tue, 8 Nov 2011 04:00:25 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201111080400.pA840PMj012100@svn.freebsd.org> From: Adrian Chadd Date: Tue, 8 Nov 2011 04:00:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227331 - head/sys/net80211 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2011 04:00:25 -0000 Author: adrian Date: Tue Nov 8 04:00:24 2011 New Revision: 227331 URL: http://svn.freebsd.org/changeset/base/227331 Log: Add 802.11h quiet time element support into net80211. This supports both station and hostap modes: * Station mode quiet time element support listens to quiet time IE's and modifies the local quiet time configuration as appropriate; * Hostap mode both obeys the locally configured quiet time period and includes it in beacon frames so stations also can obey as needed. Submitted by: Himali Patel Sponsored by: Sibridge Technologies Modified: head/sys/net80211/ieee80211.h head/sys/net80211/ieee80211_dfs.c head/sys/net80211/ieee80211_input.c head/sys/net80211/ieee80211_ioctl.c head/sys/net80211/ieee80211_ioctl.h head/sys/net80211/ieee80211_output.c head/sys/net80211/ieee80211_proto.h head/sys/net80211/ieee80211_scan.h head/sys/net80211/ieee80211_sta.c head/sys/net80211/ieee80211_var.h Modified: head/sys/net80211/ieee80211.h ============================================================================== --- head/sys/net80211/ieee80211.h Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211.h Tue Nov 8 04:00:24 2011 (r227331) @@ -759,6 +759,18 @@ struct ieee80211_country_ie { /* * 802.11h Channel Switch Announcement (CSA). */ +struct ieee80211_quiet_ie { + uint8_t quiet_ie; /* IEEE80211_ELEMID_QUIET */ + uint8_t len; + uint8_t tbttcount; /* quiet start */ + uint8_t period; /* beacon intervals between quiets */ + uint16_t duration; /* TUs of each quiet*/ + uint16_t offset; /* TUs of from TBTT of quiet start */ +} __packed; + +/* + * 802.11h Channel Switch Announcement (CSA). + */ struct ieee80211_csa_ie { uint8_t csa_ie; /* IEEE80211_ELEMID_CHANSWITCHANN */ uint8_t csa_len; Modified: head/sys/net80211/ieee80211_dfs.c ============================================================================== --- head/sys/net80211/ieee80211_dfs.c Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_dfs.c Tue Nov 8 04:00:24 2011 (r227331) @@ -64,6 +64,12 @@ SYSCTL_INT(_net_wlan, OID_AUTO, cac_time &ieee80211_cac_timeout, 0, "CAC timeout (secs)"); #define CAC_TIMEOUT msecs_to_ticks(ieee80211_cac_timeout*1000) +static int +null_set_quiet(struct ieee80211_node *ni, u_int8_t *quiet_elm) +{ + return ENOSYS; +} + void ieee80211_dfs_attach(struct ieee80211com *ic) { @@ -71,6 +77,8 @@ ieee80211_dfs_attach(struct ieee80211com callout_init_mtx(&dfs->nol_timer, IEEE80211_LOCK_OBJ(ic), 0); callout_init_mtx(&dfs->cac_timer, IEEE80211_LOCK_OBJ(ic), 0); + + ic->ic_set_quiet = null_set_quiet; } void Modified: head/sys/net80211/ieee80211_input.c ============================================================================== --- head/sys/net80211/ieee80211_input.c Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_input.c Tue Nov 8 04:00:24 2011 (r227331) @@ -522,6 +522,9 @@ ieee80211_parse_beacon(struct ieee80211_ case IEEE80211_ELEMID_CSA: scan->csa = frm; break; + case IEEE80211_ELEMID_QUIET: + scan->quiet = frm; + break; case IEEE80211_ELEMID_FHPARMS: if (ic->ic_phytype == IEEE80211_T_FH) { scan->fhdwell = LE_READ_2(&frm[2]); Modified: head/sys/net80211/ieee80211_ioctl.c ============================================================================== --- head/sys/net80211/ieee80211_ioctl.c Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_ioctl.c Tue Nov 8 04:00:24 2011 (r227331) @@ -972,6 +972,21 @@ ieee80211_ioctl_get80211(struct ieee8021 case IEEE80211_IOC_PUREG: ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0; break; + case IEEE80211_IOC_QUIET: + ireq->i_val = vap->iv_quiet; + break; + case IEEE80211_IOC_QUIET_COUNT: + ireq->i_val = vap->iv_quiet_count; + break; + case IEEE80211_IOC_QUIET_PERIOD: + ireq->i_val = vap->iv_quiet_period; + break; + case IEEE80211_IOC_QUIET_DUR: + ireq->i_val = vap->iv_quiet_duration; + break; + case IEEE80211_IOC_QUIET_OFFSET: + ireq->i_val = vap->iv_quiet_offset; + break; case IEEE80211_IOC_BGSCAN: ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0; break; @@ -2939,6 +2954,24 @@ ieee80211_ioctl_set80211(struct ieee8021 if (isvap11g(vap)) error = ENETRESET; break; + case IEEE80211_IOC_QUIET: + vap->iv_quiet= ireq->i_val; + break; + case IEEE80211_IOC_QUIET_COUNT: + vap->iv_quiet_count=ireq->i_val; + break; + case IEEE80211_IOC_QUIET_PERIOD: + vap->iv_quiet_period=ireq->i_val; + break; + case IEEE80211_IOC_QUIET_OFFSET: + vap->iv_quiet_offset=ireq->i_val; + break; + case IEEE80211_IOC_QUIET_DUR: + if(ireq->i_val < vap->iv_bss->ni_intval) + vap->iv_quiet_duration = ireq->i_val; + else + error = EINVAL; + break; case IEEE80211_IOC_BGSCAN: if (ireq->i_val) { if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0) Modified: head/sys/net80211/ieee80211_ioctl.h ============================================================================== --- head/sys/net80211/ieee80211_ioctl.h Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_ioctl.h Tue Nov 8 04:00:24 2011 (r227331) @@ -715,6 +715,11 @@ struct ieee80211req { #define IEEE80211_IOC_TDMA_SLOTLEN 203 /* TDMA: slot length (usecs) */ #define IEEE80211_IOC_TDMA_BINTERVAL 204 /* TDMA: beacon intvl (slots) */ +#define IEEE80211_IOC_QUIET 205 /* Quiet Enable/Disable */ +#define IEEE80211_IOC_QUIET_PERIOD 206 /* Quiet Period */ +#define IEEE80211_IOC_QUIET_OFFSET 207 /* Quiet Offset */ +#define IEEE80211_IOC_QUIET_DUR 208 /* Quiet Duration */ +#define IEEE80211_IOC_QUIET_COUNT 209 /* Quiet Count */ /* * Parameters for controlling a scan requested with * IEEE80211_IOC_SCAN_REQ. Modified: head/sys/net80211/ieee80211_output.c ============================================================================== --- head/sys/net80211/ieee80211_output.c Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_output.c Tue Nov 8 04:00:24 2011 (r227331) @@ -1661,6 +1661,33 @@ ieee80211_add_supportedchannels(uint8_t } /* + * Add an 11h Quiet time element to a frame. + */ +static uint8_t * +ieee80211_add_quiet(uint8_t *frm, struct ieee80211vap *vap) +{ + struct ieee80211_quiet_ie *quiet = (struct ieee80211_quiet_ie *) frm; + + quiet->quiet_ie = IEEE80211_ELEMID_QUIET; + quiet->len = 6; + if (vap->iv_quiet_count_value == 1) + vap->iv_quiet_count_value = vap->iv_quiet_count; + else if (vap->iv_quiet_count_value > 1) + vap->iv_quiet_count_value--; + + if (vap->iv_quiet_count_value == 0) { + /* value 0 is reserved as per 802.11h standerd */ + vap->iv_quiet_count_value = 1; + } + + quiet->tbttcount = vap->iv_quiet_count_value; + quiet->period = vap->iv_quiet_period; + quiet->duration = htole16(vap->iv_quiet_duration); + quiet->offset = htole16(vap->iv_quiet_offset); + return frm + sizeof(*quiet); +} + +/* * Add an 11h Channel Switch Announcement element to a frame. * Note that we use the per-vap CSA count to adjust the global * counter so we can use this routine to form probe response @@ -2253,6 +2280,7 @@ ieee80211_alloc_proberesp(struct ieee802 + IEEE80211_COUNTRY_MAX_SIZE + 3 + sizeof(struct ieee80211_csa_ie) + + sizeof(struct ieee80211_quiet_ie) + 3 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_ie_wpa) @@ -2319,6 +2347,13 @@ ieee80211_alloc_proberesp(struct ieee802 if (ic->ic_flags & IEEE80211_F_CSAPENDING) frm = ieee80211_add_csa(frm, vap); } + if (vap->iv_flags & IEEE80211_F_DOTH) { + if (IEEE80211_IS_CHAN_DFS(ic->ic_bsschan) && + (vap->iv_flags_ext & IEEE80211_FEXT_DFS)) { + if (vap->iv_quiet) + frm = ieee80211_add_quiet(frm, vap); + } + } if (IEEE80211_IS_CHAN_ANYG(bss->ni_chan)) frm = ieee80211_add_erp(frm, ic); frm = ieee80211_add_xrates(frm, rs); @@ -2617,9 +2652,20 @@ ieee80211_beacon_construct(struct mbuf * frm = ieee80211_add_powerconstraint(frm, vap); bo->bo_csa = frm; if (ic->ic_flags & IEEE80211_F_CSAPENDING) - frm = ieee80211_add_csa(frm, vap); + frm = ieee80211_add_csa(frm, vap); } else bo->bo_csa = frm; + + 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) + frm = ieee80211_add_quiet(frm,vap); + } + } else + bo->bo_quiet = frm; + if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) { bo->bo_erp = frm; frm = ieee80211_add_erp(frm, ic); @@ -2733,7 +2779,8 @@ ieee80211_beacon_alloc(struct ieee80211_ + 2 + 4 + vap->iv_tim_len /* DTIM/IBSSPARMS */ + IEEE80211_COUNTRY_MAX_SIZE /* country */ + 2 + 1 /* power control */ - + sizeof(struct ieee80211_csa_ie) /* CSA */ + + sizeof(struct ieee80211_csa_ie) /* CSA */ + + sizeof(struct ieee80211_quiet_ie) /* Quiet */ + 2 + 1 /* ERP */ + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + (vap->iv_caps & IEEE80211_C_WPA ? /* WPA 1+2 */ @@ -2953,6 +3000,7 @@ ieee80211_beacon_update(struct ieee80211 bo->bo_appie += adjust; bo->bo_wme += adjust; bo->bo_csa += adjust; + bo->bo_quiet += adjust; bo->bo_tim_len = timlen; /* update information element */ @@ -3006,6 +3054,7 @@ ieee80211_beacon_update(struct ieee80211 #endif bo->bo_appie += sizeof(*csa); bo->bo_csa_trailer_len += sizeof(*csa); + bo->bo_quiet += sizeof(*csa); bo->bo_tim_trailer_len += sizeof(*csa); m->m_len += sizeof(*csa); m->m_pkthdr.len += sizeof(*csa); @@ -3016,6 +3065,11 @@ ieee80211_beacon_update(struct ieee80211 vap->iv_csa_count++; /* NB: don't clear IEEE80211_BEACON_CSA */ } + if (IEEE80211_IS_CHAN_DFS(ic->ic_bsschan) && + (vap->iv_flags_ext & IEEE80211_FEXT_DFS) ){ + if (vap->iv_quiet) + ieee80211_add_quiet(bo->bo_quiet, vap); + } if (isset(bo->bo_flags, IEEE80211_BEACON_ERP)) { /* * ERP element needs updating. Modified: head/sys/net80211/ieee80211_proto.h ============================================================================== --- head/sys/net80211/ieee80211_proto.h Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_proto.h Tue Nov 8 04:00:24 2011 (r227331) @@ -344,6 +344,7 @@ struct ieee80211_beacon_offsets { uint16_t bo_appie_len; /* AppIE length in bytes */ uint16_t bo_csa_trailer_len; uint8_t *bo_csa; /* start of CSA element */ + uint8_t *bo_quiet; /* start of Quiet element */ uint8_t *bo_meshconf; /* start of MESHCONF element */ uint8_t *bo_spare[3]; }; Modified: head/sys/net80211/ieee80211_scan.h ============================================================================== --- head/sys/net80211/ieee80211_scan.h Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_scan.h Tue Nov 8 04:00:24 2011 (r227331) @@ -213,6 +213,7 @@ struct ieee80211_scanparams { uint8_t *ath; uint8_t *tdma; uint8_t *csa; + uint8_t *quiet; uint8_t *meshid; uint8_t *meshconf; uint8_t *spare[3]; Modified: head/sys/net80211/ieee80211_sta.c ============================================================================== --- head/sys/net80211/ieee80211_sta.c Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_sta.c Tue Nov 8 04:00:24 2011 (r227331) @@ -1347,6 +1347,8 @@ sta_recv_mgmt(struct ieee80211_node *ni, scan.htcap, scan.htinfo); /* XXX state changes? */ } + if (scan.quiet) + ic->ic_set_quiet(ni, scan.quiet); if (scan.tim != NULL) { struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) scan.tim; Modified: head/sys/net80211/ieee80211_var.h ============================================================================== --- head/sys/net80211/ieee80211_var.h Tue Nov 8 02:54:08 2011 (r227330) +++ head/sys/net80211/ieee80211_var.h Tue Nov 8 04:00:24 2011 (r227331) @@ -242,6 +242,10 @@ struct ieee80211com { int (*ic_setregdomain)(struct ieee80211com *, struct ieee80211_regdomain *, int, struct ieee80211_channel []); + + int (*ic_set_quiet)(struct ieee80211_node *, + u_int8_t *quiet_elm); + /* send/recv 802.11 management frame */ int (*ic_send_mgmt)(struct ieee80211_node *, int, int); @@ -403,6 +407,12 @@ struct ieee80211vap { uint8_t iv_dtim_period; /* DTIM period */ uint8_t iv_dtim_count; /* DTIM count from last bcn */ /* set/unset aid pwrsav state */ + uint8_t iv_quiet; /* Quiet Element */ + uint8_t iv_quiet_count; /* constant count for Quiet Element */ + uint8_t iv_quiet_count_value; /* variable count for Quiet Element */ + uint8_t iv_quiet_period; /* period for Quiet Element */ + uint16_t iv_quiet_duration; /* duration for Quiet Element */ + uint16_t iv_quiet_offset; /* offset for Quiet Element */ int iv_csa_count; /* count for doing CSA */ struct ieee80211_node *iv_bss; /* information for this node */