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 <himali.pa...@sibridgetech.com>
  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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to