Home | History | Annotate | Download | only in net80211
      1   3147  xc151355 /*
      2   8594       Fei  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      3   3147  xc151355  * Use is subject to license terms.
      4   3147  xc151355  */
      5   3147  xc151355 
      6   3147  xc151355 /*
      7   3147  xc151355  * Copyright (c) 2001 Atsushi Onoe
      8   8594       Fei  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      9   3147  xc151355  * All rights reserved.
     10   3147  xc151355  *
     11   3147  xc151355  * Redistribution and use in source and binary forms, with or without
     12   3147  xc151355  * modification, are permitted provided that the following conditions
     13   3147  xc151355  * are met:
     14   3147  xc151355  * 1. Redistributions of source code must retain the above copyright
     15   3147  xc151355  *    notice, this list of conditions and the following disclaimer.
     16   3147  xc151355  * 2. Redistributions in binary form must reproduce the above copyright
     17   3147  xc151355  *    notice, this list of conditions and the following disclaimer in the
     18   3147  xc151355  *    documentation and/or other materials provided with the distribution.
     19   3147  xc151355  * 3. The name of the author may not be used to endorse or promote products
     20   3147  xc151355  *    derived from this software without specific prior written permission.
     21   3147  xc151355  *
     22   3147  xc151355  * Alternatively, this software may be distributed under the terms of the
     23   3147  xc151355  * GNU General Public License ("GPL") version 2 as published by the Free
     24   3147  xc151355  * Software Foundation.
     25   3147  xc151355  *
     26   3147  xc151355  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     27   3147  xc151355  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     28   3147  xc151355  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29   3147  xc151355  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     30   3147  xc151355  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     31   3147  xc151355  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     32   3147  xc151355  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     33   3147  xc151355  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34   3147  xc151355  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     35   3147  xc151355  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36   3147  xc151355  */
     37   3147  xc151355 
     38   3147  xc151355 /*
     39   3147  xc151355  * IEEE 802.11 protocol support
     40   3147  xc151355  */
     41   3147  xc151355 
     42   3147  xc151355 #include "net80211_impl.h"
     43   3147  xc151355 
     44  10266    Quaker /* tunables */
     45  10266    Quaker #define	AGGRESSIVE_MODE_SWITCH_HYSTERESIS	3	/* pkts / 100ms */
     46  10266    Quaker #define	HIGH_PRI_SWITCH_THRESH			10	/* pkts / 100ms */
     47  10266    Quaker 
     48  10266    Quaker #define	IEEE80211_RATE2MBS(r)	(((r) & IEEE80211_RATE_VAL) / 2)
     49  10266    Quaker 
     50   3147  xc151355 const char *ieee80211_mgt_subtype_name[] = {
     51   3147  xc151355 	"assoc_req",	"assoc_resp",	"reassoc_req",	"reassoc_resp",
     52   3147  xc151355 	"probe_req",	"probe_resp",	"reserved#6",	"reserved#7",
     53   3147  xc151355 	"beacon",	"atim",		"disassoc",	"auth",
     54   3147  xc151355 	"deauth",	"reserved#13",	"reserved#14",	"reserved#15"
     55   3147  xc151355 };
     56   3147  xc151355 const char *ieee80211_ctl_subtype_name[] = {
     57   3147  xc151355 	"reserved#0",	"reserved#1",	"reserved#2",	"reserved#3",
     58   3147  xc151355 	"reserved#3",	"reserved#5",	"reserved#6",	"reserved#7",
     59   3147  xc151355 	"reserved#8",	"reserved#9",	"ps_poll",	"rts",
     60   3147  xc151355 	"cts",		"ack",		"cf_end",	"cf_end_ack"
     61   3147  xc151355 };
     62   3147  xc151355 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
     63   3147  xc151355 	"INIT",		/* IEEE80211_S_INIT */
     64   3147  xc151355 	"SCAN",		/* IEEE80211_S_SCAN */
     65   3147  xc151355 	"AUTH",		/* IEEE80211_S_AUTH */
     66   3147  xc151355 	"ASSOC",	/* IEEE80211_S_ASSOC */
     67   3147  xc151355 	"RUN"		/* IEEE80211_S_RUN */
     68   3147  xc151355 };
     69  10266    Quaker const char *ieee80211_wme_acnames[] = {
     70  10266    Quaker 	"WME_AC_BE",
     71  10266    Quaker 	"WME_AC_BK",
     72  10266    Quaker 	"WME_AC_VI",
     73  10266    Quaker 	"WME_AC_VO",
     74  10266    Quaker 	"WME_UPSD",
     75  10266    Quaker };
     76   3147  xc151355 
     77   3147  xc151355 static int ieee80211_newstate(ieee80211com_t *, enum ieee80211_state, int);
     78   3147  xc151355 
     79   3147  xc151355 /*
     80   3147  xc151355  * Initialize the interface softc, ic, with protocol management
     81   3147  xc151355  * related data structures and functions.
     82   3147  xc151355  */
     83   3147  xc151355 void
     84   3147  xc151355 ieee80211_proto_attach(ieee80211com_t *ic)
     85   3147  xc151355 {
     86   3147  xc151355 	struct ieee80211_impl *im = ic->ic_private;
     87   3147  xc151355 
     88   3147  xc151355 	ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
     89   3147  xc151355 	ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
     90   3147  xc151355 	ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
     91   3147  xc151355 	ic->ic_protmode = IEEE80211_PROT_CTSONLY;
     92   3147  xc151355 	im->im_bmiss_max = IEEE80211_BMISS_MAX;
     93  10266    Quaker 
     94  10266    Quaker 	ic->ic_wme.wme_hipri_switch_hysteresis =
     95  10266    Quaker 	    AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
     96   3147  xc151355 
     97   3147  xc151355 	/* protocol state change handler */
     98   3147  xc151355 	ic->ic_newstate = ieee80211_newstate;
     99   3147  xc151355 
    100   3147  xc151355 	/* initialize management frame handlers */
    101   3147  xc151355 	ic->ic_recv_mgmt = ieee80211_recv_mgmt;
    102   3147  xc151355 	ic->ic_send_mgmt = ieee80211_send_mgmt;
    103   3147  xc151355 }
    104   3147  xc151355 
    105   3147  xc151355 /*
    106   3147  xc151355  * Print a 802.11 frame header
    107   3147  xc151355  */
    108   3147  xc151355 void
    109   3147  xc151355 ieee80211_dump_pkt(const uint8_t *buf, int32_t len, int32_t rate, int32_t rssi)
    110   3147  xc151355 {
    111   3147  xc151355 	struct ieee80211_frame *wh;
    112   3147  xc151355 	int8_t buf1[100];
    113   3147  xc151355 	int8_t buf2[25];
    114   3147  xc151355 	int i;
    115   3147  xc151355 
    116   3147  xc151355 	bzero(buf1, sizeof (buf1));
    117   3147  xc151355 	bzero(buf2, sizeof (buf2));
    118   3147  xc151355 	wh = (struct ieee80211_frame *)buf;
    119   3147  xc151355 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
    120   3147  xc151355 	case IEEE80211_FC1_DIR_NODS:
    121   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "NODS %s",
    122   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr2));
    123   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    124   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "->%s",
    125   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr1));
    126   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    127   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "(%s)",
    128   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr3));
    129   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    130   3147  xc151355 		break;
    131   3147  xc151355 	case IEEE80211_FC1_DIR_TODS:
    132   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "TODS %s",
    133   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr2));
    134   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    135   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "->%s",
    136   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr3));
    137   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    138   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "(%s)",
    139   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr1));
    140   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    141   3147  xc151355 		break;
    142   3147  xc151355 	case IEEE80211_FC1_DIR_FROMDS:
    143   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "FRDS %s",
    144   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr3));
    145   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    146   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "->%s",
    147   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr1));
    148   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    149   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "(%s)",
    150   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr2));
    151   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    152   3147  xc151355 		break;
    153   3147  xc151355 	case IEEE80211_FC1_DIR_DSTODS:
    154   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "DSDS %s",
    155   8594       Fei 		    ieee80211_macaddr_sprintf((uint8_t *)&wh[1]));
    156   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    157   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "->%s  ",
    158   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr3));
    159   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    160   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "%s",
    161   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr2));
    162   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    163   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "->%s",
    164   8594       Fei 		    ieee80211_macaddr_sprintf(wh->i_addr1));
    165   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    166   3147  xc151355 		break;
    167   3147  xc151355 	}
    168   3147  xc151355 	ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s", buf1);
    169   3147  xc151355 	bzero(buf1, sizeof (buf1));
    170   3147  xc151355 
    171   3147  xc151355 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
    172   3147  xc151355 	case IEEE80211_FC0_TYPE_DATA:
    173   3147  xc151355 		(void) sprintf(buf2, "data");
    174   3147  xc151355 		break;
    175   3147  xc151355 	case IEEE80211_FC0_TYPE_MGT:
    176   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "%s",
    177   8594       Fei 		    ieee80211_mgt_subtype_name[
    178   8594       Fei 		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
    179   8594       Fei 		    >> IEEE80211_FC0_SUBTYPE_SHIFT]);
    180   3147  xc151355 		break;
    181   3147  xc151355 	default:
    182   3147  xc151355 		(void) snprintf(buf2, sizeof (buf2), "type#%d",
    183   8594       Fei 		    wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
    184   3147  xc151355 		break;
    185   3147  xc151355 	}
    186   3147  xc151355 	(void) strncat(buf1, buf2, sizeof (buf2));
    187   3147  xc151355 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
    188   3147  xc151355 		(void) sprintf(buf2, " WEP");
    189   3147  xc151355 		(void) strcat(buf1, buf2);
    190   3147  xc151355 	}
    191   3147  xc151355 	if (rate >= 0) {
    192   3147  xc151355 		(void) snprintf(buf2,  sizeof (buf2), " %dM", rate / 2);
    193   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    194   3147  xc151355 	}
    195   3147  xc151355 	if (rssi >= 0) {
    196   3147  xc151355 		(void) snprintf(buf2,  sizeof (buf2), " +%d", rssi);
    197   3147  xc151355 		(void) strncat(buf1, buf2, sizeof (buf2));
    198   3147  xc151355 	}
    199   3147  xc151355 	ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s", buf1);
    200   3147  xc151355 	bzero(buf1, sizeof (buf1));
    201   3147  xc151355 
    202   3147  xc151355 	if (len > 0) {
    203   3147  xc151355 		for (i = 0; i < (len > 40 ? 40 : len); i++) {
    204   3147  xc151355 			if ((i & 0x03) == 0)
    205   3147  xc151355 				(void) strcat(buf1, " ");
    206   3147  xc151355 			(void) snprintf(buf2, 3, "%02x", buf[i]);
    207   3147  xc151355 			(void) strncat(buf1, buf2, 3);
    208   3147  xc151355 		}
    209   3147  xc151355 		ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s",
    210   8594       Fei 		    buf1);
    211   3147  xc151355 	}
    212   3147  xc151355 }
    213   3147  xc151355 
    214   3147  xc151355 /*
    215   3147  xc151355  * Adjust/Fix the specified node's rate table
    216   3147  xc151355  *
    217   3147  xc151355  * in   node
    218   3147  xc151355  * flag IEEE80211_F_DOSORT : sort the node's rate table
    219   3147  xc151355  *      IEEE80211_F_DONEGO : mark a rate as basic rate if it is
    220   3147  xc151355  *                           a device's basic rate
    221   3147  xc151355  *      IEEE80211_F_DODEL  : delete rates not supported by the device
    222   3147  xc151355  *      IEEE80211_F_DOFRATE: check if the fixed rate is supported by
    223   3147  xc151355  *                           the device
    224   3147  xc151355  *
    225   3147  xc151355  * The highest bit of returned rate value is set to 1 on failure.
    226   3147  xc151355  */
    227   3147  xc151355 int
    228  10266    Quaker ieee80211_fix_rate(ieee80211_node_t *in,
    229  10266    Quaker     struct ieee80211_rateset *nrs, int flags)
    230   3147  xc151355 {
    231   3147  xc151355 	ieee80211com_t *ic = in->in_ic;
    232   3147  xc151355 	struct ieee80211_rateset *srs;
    233   3147  xc151355 	boolean_t ignore;
    234   3147  xc151355 	int i;
    235   3147  xc151355 	int okrate;
    236   3147  xc151355 	int badrate;
    237   3147  xc151355 	int fixedrate;
    238   3147  xc151355 	uint8_t r;
    239   3147  xc151355 
    240   3147  xc151355 	/*
    241   3147  xc151355 	 * If the fixed rate check was requested but no
    242   3147  xc151355 	 * fixed has been defined then just remove it.
    243   3147  xc151355 	 */
    244   3147  xc151355 	if ((flags & IEEE80211_F_DOFRATE) &&
    245   3147  xc151355 	    (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)) {
    246   3147  xc151355 		flags &= ~IEEE80211_F_DOFRATE;
    247   6629  zf162725 	}
    248   6629  zf162725 	if (in->in_chan == IEEE80211_CHAN_ANYC) {
    249   6629  zf162725 		return (IEEE80211_RATE_BASIC);
    250   3147  xc151355 	}
    251   3147  xc151355 	okrate = badrate = fixedrate = 0;
    252   3147  xc151355 	srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, in->in_chan)];
    253   3147  xc151355 	for (i = 0; i < nrs->ir_nrates; ) {
    254   3147  xc151355 		int j;
    255   3147  xc151355 
    256   3147  xc151355 		ignore = B_FALSE;
    257   3147  xc151355 		if (flags & IEEE80211_F_DOSORT) {
    258   3147  xc151355 			/*
    259   3147  xc151355 			 * Sort rates.
    260   3147  xc151355 			 */
    261   3147  xc151355 			for (j = i + 1; j < nrs->ir_nrates; j++) {
    262   3147  xc151355 				if (IEEE80211_RV(nrs->ir_rates[i]) >
    263   3147  xc151355 				    IEEE80211_RV(nrs->ir_rates[j])) {
    264   3147  xc151355 					r = nrs->ir_rates[i];
    265   3147  xc151355 					nrs->ir_rates[i] = nrs->ir_rates[j];
    266   3147  xc151355 					nrs->ir_rates[j] = r;
    267   3147  xc151355 				}
    268   3147  xc151355 			}
    269   3147  xc151355 		}
    270   3147  xc151355 		r = IEEE80211_RV(nrs->ir_rates[i]);
    271   3147  xc151355 		badrate = r;
    272   3147  xc151355 
    273   3147  xc151355 		/*
    274   3147  xc151355 		 * Check against supported rates.
    275   3147  xc151355 		 */
    276   3147  xc151355 		for (j = 0; j < srs->ir_nrates; j++) {
    277   3147  xc151355 			if (r == IEEE80211_RV(srs->ir_rates[j])) {
    278   3147  xc151355 				/*
    279   3147  xc151355 				 * Overwrite with the supported rate
    280   3147  xc151355 				 * value so any basic rate bit is set.
    281   3147  xc151355 				 * This insures that response we send
    282   3147  xc151355 				 * to stations have the necessary basic
    283   3147  xc151355 				 * rate bit set.
    284   3147  xc151355 				 */
    285   3147  xc151355 				if (flags & IEEE80211_F_DONEGO)
    286   3147  xc151355 					nrs->ir_rates[i] = srs->ir_rates[j];
    287   3147  xc151355 				break;
    288   3147  xc151355 			}
    289   3147  xc151355 		}
    290   3147  xc151355 		if (j == srs->ir_nrates) {
    291   3147  xc151355 			/*
    292   3147  xc151355 			 * A rate in the node's rate set is not
    293   3147  xc151355 			 * supported. We just discard/ignore the rate.
    294   3147  xc151355 			 * Note that this is important for 11b stations
    295   3147  xc151355 			 * when they want to associate with an 11g AP.
    296   3147  xc151355 			 */
    297   3147  xc151355 			ignore = B_TRUE;
    298   3147  xc151355 		}
    299   3147  xc151355 
    300   3147  xc151355 		if (flags & IEEE80211_F_DODEL) {
    301   3147  xc151355 			/*
    302   3147  xc151355 			 * Delete unacceptable rates.
    303   3147  xc151355 			 */
    304   3147  xc151355 			if (ignore) {
    305   3147  xc151355 				nrs->ir_nrates--;
    306   3147  xc151355 				for (j = i; j < nrs->ir_nrates; j++)
    307   3147  xc151355 					nrs->ir_rates[j] = nrs->ir_rates[j + 1];
    308   3147  xc151355 				nrs->ir_rates[j] = 0;
    309   3147  xc151355 				continue;
    310   3147  xc151355 			}
    311   3147  xc151355 		}
    312   3147  xc151355 		if (flags & IEEE80211_F_DOFRATE) {
    313   3147  xc151355 			/*
    314   3147  xc151355 			 * Check any fixed rate is included.
    315   3147  xc151355 			 */
    316   3147  xc151355 			if (r == ic->ic_fixed_rate)
    317   3147  xc151355 				fixedrate = r;
    318   3147  xc151355 		}
    319   3147  xc151355 		if (!ignore)
    320   3147  xc151355 			okrate = nrs->ir_rates[i];
    321   3147  xc151355 		i++;
    322   3147  xc151355 	}
    323   3147  xc151355 	if (okrate == 0 || ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
    324   3147  xc151355 		return (badrate | IEEE80211_RATE_BASIC);
    325   3147  xc151355 	else
    326   3147  xc151355 		return (IEEE80211_RV(okrate));
    327   3147  xc151355 }
    328   3147  xc151355 
    329   3147  xc151355 /*
    330   3147  xc151355  * Reset 11g-related state.
    331   3147  xc151355  */
    332   3147  xc151355 void
    333   3147  xc151355 ieee80211_reset_erp(ieee80211com_t *ic)
    334   3147  xc151355 {
    335   3147  xc151355 	ic->ic_flags &= ~IEEE80211_F_USEPROT;
    336   3147  xc151355 	/*
    337   3147  xc151355 	 * Short slot time is enabled only when operating in 11g
    338   3147  xc151355 	 * and not in an IBSS.  We must also honor whether or not
    339   3147  xc151355 	 * the driver is capable of doing it.
    340   3147  xc151355 	 */
    341   3147  xc151355 	ieee80211_set_shortslottime(ic,
    342   8594       Fei 	    ic->ic_curmode == IEEE80211_MODE_11A);
    343   3147  xc151355 	/*
    344   3147  xc151355 	 * Set short preamble and ERP barker-preamble flags.
    345   3147  xc151355 	 */
    346   3147  xc151355 	if (ic->ic_curmode == IEEE80211_MODE_11A ||
    347   3147  xc151355 	    (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
    348   3147  xc151355 		ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
    349   3147  xc151355 		ic->ic_flags &= ~IEEE80211_F_USEBARKER;
    350   3147  xc151355 	} else {
    351   3147  xc151355 		ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
    352   3147  xc151355 		ic->ic_flags |= IEEE80211_F_USEBARKER;
    353   3147  xc151355 	}
    354   3147  xc151355 }
    355   3147  xc151355 
    356   3147  xc151355 /*
    357   3147  xc151355  * Change current channel to be the next available channel
    358   3147  xc151355  */
    359   3147  xc151355 void
    360   3147  xc151355 ieee80211_reset_chan(ieee80211com_t *ic)
    361   3147  xc151355 {
    362   3147  xc151355 	struct ieee80211_channel *ch = ic->ic_curchan;
    363   3147  xc151355 
    364   3147  xc151355 	IEEE80211_LOCK(ic);
    365   3147  xc151355 	do {
    366   3147  xc151355 		if (++ch > &ic->ic_sup_channels[IEEE80211_CHAN_MAX])
    367   3147  xc151355 			ch = &ic->ic_sup_channels[0];
    368   3147  xc151355 		if (ieee80211_isset(ic->ic_chan_active,
    369   3147  xc151355 		    ieee80211_chan2ieee(ic, ch))) {
    370   3147  xc151355 			break;
    371   3147  xc151355 		}
    372   3147  xc151355 	} while (ch != ic->ic_curchan);
    373   3147  xc151355 	ic->ic_curchan = ch;
    374   3147  xc151355 	IEEE80211_UNLOCK(ic);
    375   3147  xc151355 }
    376   3147  xc151355 
    377   3147  xc151355 /*
    378   3147  xc151355  * Set the short slot time state and notify the driver.
    379   3147  xc151355  */
    380   3147  xc151355 void
    381   3147  xc151355 ieee80211_set_shortslottime(ieee80211com_t *ic, boolean_t on)
    382   3147  xc151355 {
    383   3147  xc151355 	if (on)
    384   3147  xc151355 		ic->ic_flags |= IEEE80211_F_SHSLOT;
    385   3147  xc151355 	else
    386   3147  xc151355 		ic->ic_flags &= ~IEEE80211_F_SHSLOT;
    387   3147  xc151355 	/* notify driver */
    388   3147  xc151355 	if (ic->ic_set_shortslot != NULL)
    389   3147  xc151355 		ic->ic_set_shortslot(ic, on);
    390   3147  xc151355 }
    391   3147  xc151355 
    392   3147  xc151355 /*
    393   3147  xc151355  * Mark the basic rates for the 11g rate table based on the
    394   3147  xc151355  * operating mode.  For real 11g we mark all the 11b rates
    395   3147  xc151355  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
    396   3147  xc151355  * 11b rates.  There's also a pseudo 11a-mode used to mark only
    397   3147  xc151355  * the basic OFDM rates.
    398   3147  xc151355  */
    399   3147  xc151355 void
    400   3147  xc151355 ieee80211_setbasicrates(struct ieee80211_rateset *rs,
    401   3147  xc151355     enum ieee80211_phymode mode)
    402   3147  xc151355 {
    403   3147  xc151355 	static const struct ieee80211_rateset basic[] = {
    404   3147  xc151355 		{ 0 },			/* IEEE80211_MODE_AUTO */
    405   3147  xc151355 		{ 3, { 12, 24, 48 } },	/* IEEE80211_MODE_11A */
    406   3147  xc151355 		{ 2, { 2, 4} },		/* IEEE80211_MODE_11B */
    407   3147  xc151355 		{ 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G mixed b/g */
    408   3147  xc151355 		{ 0 },			/* IEEE80211_MODE_FH */
    409   3147  xc151355 		{ 3, { 12, 24, 48 } },	/* IEEE80211_MODE_TURBO_A */
    410  10266    Quaker 		{ 4, { 2, 4, 11, 22 } },
    411  10266    Quaker 					/* IEEE80211_MODE_TURBO_G (mixed b/g) */
    412  10266    Quaker 		{ 0 },			/* IEEE80211_MODE_STURBO_A */
    413  10266    Quaker 		{ 3, { 12, 24, 48 } },	/* IEEE80211_MODE_11NA */
    414  10266    Quaker 					/* IEEE80211_MODE_11NG (mixed b/g) */
    415  10266    Quaker 		{ 7, { 2, 4, 11, 22, 12, 24, 48 } }
    416   3147  xc151355 	};
    417   3147  xc151355 	int i, j;
    418   3147  xc151355 
    419   3147  xc151355 	ASSERT(mode < IEEE80211_MODE_MAX);
    420   3147  xc151355 	for (i = 0; i < rs->ir_nrates; i++) {
    421   3147  xc151355 		rs->ir_rates[i] &= IEEE80211_RATE_VAL;
    422   3147  xc151355 		for (j = 0; j < basic[mode].ir_nrates; j++) {
    423   3147  xc151355 			if (basic[mode].ir_rates[j] == rs->ir_rates[i]) {
    424   3147  xc151355 				rs->ir_rates[i] |= IEEE80211_RATE_BASIC;
    425   3147  xc151355 				break;
    426   3147  xc151355 			}
    427   3147  xc151355 		}
    428   3147  xc151355 	}
    429  10266    Quaker }
    430  10266    Quaker 
    431  10266    Quaker /*
    432  10266    Quaker  * WME protocol support.  The following parameters come from the spec.
    433  10266    Quaker  */
    434  10266    Quaker typedef struct phyParamType {
    435  10266    Quaker 	uint8_t aifsn;
    436  10266    Quaker 	uint8_t logcwmin;
    437  10266    Quaker 	uint8_t logcwmax;
    438  10266    Quaker 	uint16_t txopLimit;
    439  10266    Quaker 	uint8_t acm;
    440  10266    Quaker } paramType;
    441  10266    Quaker 
    442  10266    Quaker static const paramType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
    443  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_AUTO */
    444  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_11A */
    445  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_11B */
    446  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_11G */
    447  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_FH */
    448  10266    Quaker 	{ 2, 3,  5,  0, 0 },	/* IEEE80211_MODE_TURBO_A */
    449  10266    Quaker 	{ 2, 3,  5,  0, 0 },	/* IEEE80211_MODE_TURBO_G */
    450  10266    Quaker 	{ 2, 3,  5,  0, 0 },	/* IEEE80211_MODE_STURBO_A */
    451  10266    Quaker 	{ 3, 4,  6,  0, 0 },	/* IEEE80211_MODE_11NA */
    452  10266    Quaker 	{ 3, 4,  6,  0, 0 }	/* IEEE80211_MODE_11NG */
    453  10266    Quaker };
    454  10266    Quaker static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
    455  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_AUTO */
    456  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_11A */
    457  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_11B */
    458  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_11G */
    459  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_FH */
    460  10266    Quaker 	{ 7, 3, 10,  0, 0 },	/* IEEE80211_MODE_TURBO_A */
    461  10266    Quaker 	{ 7, 3, 10,  0, 0 },	/* IEEE80211_MODE_TURBO_G */
    462  10266    Quaker 	{ 7, 3, 10,  0, 0 },	/* IEEE80211_MODE_STURBO_A */
    463  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_11NA */
    464  10266    Quaker 	{ 7, 4, 10,  0, 0 },	/* IEEE80211_MODE_11NG */
    465  10266    Quaker };
    466  10266    Quaker static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
    467  10266    Quaker 	{ 1, 3, 4,  94, 0 },	/* IEEE80211_MODE_AUTO */
    468  10266    Quaker 	{ 1, 3, 4,  94, 0 },	/* IEEE80211_MODE_11A */
    469  10266    Quaker 	{ 1, 3, 4, 188, 0 },	/* IEEE80211_MODE_11B */
    470  10266    Quaker 	{ 1, 3, 4,  94, 0 },	/* IEEE80211_MODE_11G */
    471  10266    Quaker 	{ 1, 3, 4, 188, 0 },	/* IEEE80211_MODE_FH */
    472  10266    Quaker 	{ 1, 2, 3,  94, 0 },	/* IEEE80211_MODE_TURBO_A */
    473  10266    Quaker 	{ 1, 2, 3,  94, 0 },	/* IEEE80211_MODE_TURBO_G */
    474  10266    Quaker 	{ 1, 2, 3,  94, 0 },	/* IEEE80211_MODE_STURBO_A */
    475  10266    Quaker 	{ 1, 3, 4,  94, 0 },	/* IEEE80211_MODE_11NA */
    476  10266    Quaker 	{ 1, 3, 4,  94, 0 },	/* IEEE80211_MODE_11NG */
    477  10266    Quaker };
    478  10266    Quaker static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
    479  10266    Quaker 	{ 1, 2, 3,  47, 0 },	/* IEEE80211_MODE_AUTO */
    480  10266    Quaker 	{ 1, 2, 3,  47, 0 },	/* IEEE80211_MODE_11A */
    481  10266    Quaker 	{ 1, 2, 3, 102, 0 },	/* IEEE80211_MODE_11B */
    482  10266    Quaker 	{ 1, 2, 3,  47, 0 },	/* IEEE80211_MODE_11G */
    483  10266    Quaker 	{ 1, 2, 3, 102, 0 },	/* IEEE80211_MODE_FH */
    484  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_TURBO_A */
    485  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_TURBO_G */
    486  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_STURBO_A */
    487  10266    Quaker 	{ 1, 2, 3,  47, 0 },	/* IEEE80211_MODE_11NA */
    488  10266    Quaker 	{ 1, 2, 3,  47, 0 },	/* IEEE80211_MODE_11NG */
    489  10266    Quaker };
    490  10266    Quaker 
    491  10266    Quaker static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
    492  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_AUTO */
    493  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_11A */
    494  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_11B */
    495  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_11G */
    496  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_FH */
    497  10266    Quaker 	{ 2, 3, 10,  0, 0 },	/* IEEE80211_MODE_TURBO_A */
    498  10266    Quaker 	{ 2, 3, 10,  0, 0 },	/* IEEE80211_MODE_TURBO_G */
    499  10266    Quaker 	{ 2, 3, 10,  0, 0 },	/* IEEE80211_MODE_STURBO_A */
    500  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_11NA */
    501  10266    Quaker 	{ 3, 4, 10,  0, 0 },	/* IEEE80211_MODE_11NG */
    502  10266    Quaker };
    503  10266    Quaker static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
    504  10266    Quaker 	{ 2, 3, 4,  94, 0 },	/* IEEE80211_MODE_AUTO */
    505  10266    Quaker 	{ 2, 3, 4,  94, 0 },	/* IEEE80211_MODE_11A */
    506  10266    Quaker 	{ 2, 3, 4, 188, 0 },	/* IEEE80211_MODE_11B */
    507  10266    Quaker 	{ 2, 3, 4,  94, 0 },	/* IEEE80211_MODE_11G */
    508  10266    Quaker 	{ 2, 3, 4, 188, 0 },	/* IEEE80211_MODE_FH */
    509  10266    Quaker 	{ 2, 2, 3,  94, 0 },	/* IEEE80211_MODE_TURBO_A */
    510  10266    Quaker 	{ 2, 2, 3,  94, 0 },	/* IEEE80211_MODE_TURBO_G */
    511  10266    Quaker 	{ 2, 2, 3,  94, 0 },	/* IEEE80211_MODE_STURBO_A */
    512  10266    Quaker 	{ 2, 3, 4,  94, 0 },	/* IEEE80211_MODE_11NA */
    513  10266    Quaker 	{ 2, 3, 4,  94, 0 },	/* IEEE80211_MODE_11NG */
    514  10266    Quaker };
    515  10266    Quaker static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
    516  10266    Quaker 	{ 2, 2, 3,  47, 0 },	/* IEEE80211_MODE_AUTO */
    517  10266    Quaker 	{ 2, 2, 3,  47, 0 },	/* IEEE80211_MODE_11A */
    518  10266    Quaker 	{ 2, 2, 3, 102, 0 },	/* IEEE80211_MODE_11B */
    519  10266    Quaker 	{ 2, 2, 3,  47, 0 },	/* IEEE80211_MODE_11G */
    520  10266    Quaker 	{ 2, 2, 3, 102, 0 },	/* IEEE80211_MODE_FH */
    521  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_TURBO_A */
    522  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_TURBO_G */
    523  10266    Quaker 	{ 1, 2, 2,  47, 0 },	/* IEEE80211_MODE_STURBO_A */
    524  10266    Quaker 	{ 2, 2, 3,  47, 0 },	/* IEEE80211_MODE_11NA */
    525  10266    Quaker 	{ 2, 2, 3,  47, 0 },	/* IEEE80211_MODE_11NG */
    526  10266    Quaker };
    527  10266    Quaker 
    528  10266    Quaker void
    529  10266    Quaker ieee80211_wme_initparams(struct ieee80211com *ic)
    530  10266    Quaker {
    531  10266    Quaker 	struct ieee80211_wme_state *wme = &ic->ic_wme;
    532  10266    Quaker 	const paramType *pPhyParam, *pBssPhyParam;
    533  10266    Quaker 	struct wmeParams *wmep;
    534  10266    Quaker 	enum ieee80211_phymode mode;
    535  10266    Quaker 	int i;
    536  10266    Quaker 
    537  10266    Quaker 	if ((ic->ic_caps & IEEE80211_C_WME) == 0)
    538  10266    Quaker 		return;
    539  10266    Quaker 
    540  10266    Quaker 	/*
    541  10266    Quaker 	 * Select mode; we can be called early in which case we
    542  10266    Quaker 	 * always use auto mode.  We know we'll be called when
    543  10266    Quaker 	 * entering the RUN state with bsschan setup properly
    544  10266    Quaker 	 * so state will eventually get set correctly
    545  10266    Quaker 	 */
    546  10266    Quaker 	if (ic->ic_curchan != IEEE80211_CHAN_ANYC)
    547  10266    Quaker 		mode = ieee80211_chan2mode(ic, ic->ic_curchan);
    548  10266    Quaker 	else
    549  10266    Quaker 		mode = IEEE80211_MODE_AUTO;
    550  10266    Quaker 	for (i = 0; i < WME_NUM_AC; i++) {
    551  10266    Quaker 		switch (i) {
    552  10266    Quaker 		case WME_AC_BK:
    553  10266    Quaker 			pPhyParam = &phyParamForAC_BK[mode];
    554  10266    Quaker 			pBssPhyParam = &phyParamForAC_BK[mode];
    555  10266    Quaker 			break;
    556  10266    Quaker 		case WME_AC_VI:
    557  10266    Quaker 			pPhyParam = &phyParamForAC_VI[mode];
    558  10266    Quaker 			pBssPhyParam = &bssPhyParamForAC_VI[mode];
    559  10266    Quaker 			break;
    560  10266    Quaker 		case WME_AC_VO:
    561  10266    Quaker 			pPhyParam = &phyParamForAC_VO[mode];
    562  10266    Quaker 			pBssPhyParam = &bssPhyParamForAC_VO[mode];
    563  10266    Quaker 			break;
    564  10266    Quaker 		case WME_AC_BE:
    565  10266    Quaker 		default:
    566  10266    Quaker 			pPhyParam = &phyParamForAC_BE[mode];
    567  10266    Quaker 			pBssPhyParam = &bssPhyParamForAC_BE[mode];
    568  10266    Quaker 			break;
    569  10266    Quaker 		}
    570  10266    Quaker 
    571  10266    Quaker 		wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
    572  10266    Quaker 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    573  10266    Quaker 			wmep->wmep_acm = pPhyParam->acm;
    574  10266    Quaker 			wmep->wmep_aifsn = pPhyParam->aifsn;
    575  10266    Quaker 			wmep->wmep_logcwmin = pPhyParam->logcwmin;
    576  10266    Quaker 			wmep->wmep_logcwmax = pPhyParam->logcwmax;
    577  10266    Quaker 			wmep->wmep_txopLimit = pPhyParam->txopLimit;
    578  10266    Quaker 		} else {
    579  10266    Quaker 			wmep->wmep_acm = pBssPhyParam->acm;
    580  10266    Quaker 			wmep->wmep_aifsn = pBssPhyParam->aifsn;
    581  10266    Quaker 			wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
    582  10266    Quaker 			wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
    583  10266    Quaker 			wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
    584  10266    Quaker 
    585  10266    Quaker 		}
    586  10266    Quaker 		ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_initparams: "
    587  10266    Quaker 		    "%s chan [acm %u aifsn %u log2(cwmin) %u "
    588  10266    Quaker 		    "log2(cwmax) %u txpoLimit %u]\n",
    589  10266    Quaker 		    ieee80211_wme_acnames[i],
    590  10266    Quaker 		    wmep->wmep_acm,
    591  10266    Quaker 		    wmep->wmep_aifsn,
    592  10266    Quaker 		    wmep->wmep_logcwmin,
    593  10266    Quaker 		    wmep->wmep_logcwmax,
    594  10266    Quaker 		    wmep->wmep_txopLimit);
    595  10266    Quaker 
    596  10266    Quaker 		wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
    597  10266    Quaker 		wmep->wmep_acm = pBssPhyParam->acm;
    598  10266    Quaker 		wmep->wmep_aifsn = pBssPhyParam->aifsn;
    599  10266    Quaker 		wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
    600  10266    Quaker 		wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
    601  10266    Quaker 		wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
    602  10266    Quaker 		ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_initparams: "
    603  10266    Quaker 		    "%s  bss [acm %u aifsn %u log2(cwmin) %u "
    604  10266    Quaker 		    "log2(cwmax) %u txpoLimit %u]\n",
    605  10266    Quaker 		    ieee80211_wme_acnames[i],
    606  10266    Quaker 		    wmep->wmep_acm,
    607  10266    Quaker 		    wmep->wmep_aifsn,
    608  10266    Quaker 		    wmep->wmep_logcwmin,
    609  10266    Quaker 		    wmep->wmep_logcwmax,
    610  10266    Quaker 		    wmep->wmep_txopLimit);
    611  10266    Quaker 	}
    612  10266    Quaker 	/* NB: check ic_bss to avoid NULL deref on initial attach */
    613  10266    Quaker 	if (ic->ic_bss != NULL) {
    614  10266    Quaker 		/*
    615  10266    Quaker 		 * Calculate agressive mode switching threshold based
    616  10266    Quaker 		 * on beacon interval.  This doesn't need locking since
    617  10266    Quaker 		 * we're only called before entering the RUN state at
    618  10266    Quaker 		 * which point we start sending beacon frames.
    619  10266    Quaker 		 */
    620  10266    Quaker 		wme->wme_hipri_switch_thresh =
    621  10266    Quaker 		    (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->in_intval) / 100;
    622  10266    Quaker 		ieee80211_wme_updateparams(ic);
    623  10266    Quaker 	}
    624  10266    Quaker }
    625  10266    Quaker 
    626  10266    Quaker /*
    627  10266    Quaker  * Update WME parameters for ourself and the BSS.
    628  10266    Quaker  */
    629  10266    Quaker void
    630  10266    Quaker ieee80211_wme_updateparams(struct ieee80211com *ic)
    631  10266    Quaker {
    632  10266    Quaker 	static const paramType phyParam[IEEE80211_MODE_MAX] = {
    633  10266    Quaker 		{ 2, 4, 10, 64, 0 },	/* IEEE80211_MODE_AUTO */
    634  10266    Quaker 		{ 2, 4, 10, 64, 0 },	/* IEEE80211_MODE_11A */
    635  10266    Quaker 		{ 2, 5, 10, 64, 0 },	/* IEEE80211_MODE_11B */
    636  10266    Quaker 		{ 2, 4, 10, 64, 0 },	/* IEEE80211_MODE_11G */
    637  10266    Quaker 		{ 2, 5, 10, 64, 0 },	/* IEEE80211_MODE_FH */
    638  10266    Quaker 		{ 1, 3, 10, 64, 0 },	/* IEEE80211_MODE_TURBO_A */
    639  10266    Quaker 		{ 1, 3, 10, 64, 0 },	/* IEEE80211_MODE_TURBO_G */
    640  10266    Quaker 		{ 1, 3, 10, 64, 0 },	/* IEEE80211_MODE_STURBO_A */
    641  10266    Quaker 		{ 2, 4, 10, 64, 0 },	/* IEEE80211_MODE_11NA */
    642  10266    Quaker 		{ 2, 4, 10, 64, 0 },	/* IEEE80211_MODE_11NG */
    643  10266    Quaker 	};
    644  10266    Quaker 	struct ieee80211_wme_state *wme = &ic->ic_wme;
    645  10266    Quaker 	const struct wmeParams *wmep;
    646  10266    Quaker 	struct wmeParams *chanp, *bssp;
    647  10266    Quaker 	enum ieee80211_phymode mode;
    648  10266    Quaker 	int i;
    649  10266    Quaker 
    650  10266    Quaker 	if ((ic->ic_caps & IEEE80211_C_WME) == 0)
    651  10266    Quaker 		return;
    652  10266    Quaker 
    653  10266    Quaker 	/* set up the channel access parameters for the physical device */
    654  10266    Quaker 	for (i = 0; i < WME_NUM_AC; i++) {
    655  10266    Quaker 		chanp = &wme->wme_chanParams.cap_wmeParams[i];
    656  10266    Quaker 		wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
    657  10266    Quaker 		chanp->wmep_aifsn = wmep->wmep_aifsn;
    658  10266    Quaker 		chanp->wmep_logcwmin = wmep->wmep_logcwmin;
    659  10266    Quaker 		chanp->wmep_logcwmax = wmep->wmep_logcwmax;
    660  10266    Quaker 		chanp->wmep_txopLimit = wmep->wmep_txopLimit;
    661  10266    Quaker 
    662  10266    Quaker 		chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
    663  10266    Quaker 		wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
    664  10266    Quaker 		chanp->wmep_aifsn = wmep->wmep_aifsn;
    665  10266    Quaker 		chanp->wmep_logcwmin = wmep->wmep_logcwmin;
    666  10266    Quaker 		chanp->wmep_logcwmax = wmep->wmep_logcwmax;
    667  10266    Quaker 		chanp->wmep_txopLimit = wmep->wmep_txopLimit;
    668  10266    Quaker 	}
    669  10266    Quaker 
    670  10266    Quaker 	/*
    671  10266    Quaker 	 * Select mode; we can be called early in which case we
    672  10266    Quaker 	 * always use auto mode.  We know we'll be called when
    673  10266    Quaker 	 * entering the RUN state with bsschan setup properly
    674  10266    Quaker 	 * so state will eventually get set correctly
    675  10266    Quaker 	 */
    676  10266    Quaker 	if (ic->ic_curchan != IEEE80211_CHAN_ANYC)
    677  10266    Quaker 		mode = ieee80211_chan2mode(ic, ic->ic_curchan);
    678  10266    Quaker 	else
    679  10266    Quaker 		mode = IEEE80211_MODE_AUTO;
    680  10266    Quaker 
    681  10266    Quaker 	/*
    682  10266    Quaker 	 * This implements agressive mode as found in certain
    683  10266    Quaker 	 * vendors' AP's.  When there is significant high
    684  10266    Quaker 	 * priority (VI/VO) traffic in the BSS throttle back BE
    685  10266    Quaker 	 * traffic by using conservative parameters.  Otherwise
    686  10266    Quaker 	 * BE uses agressive params to optimize performance of
    687  10266    Quaker 	 * legacy/non-QoS traffic.
    688  10266    Quaker 	 */
    689  10266    Quaker 	if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
    690  10266    Quaker 	    (wme->wme_flags & WME_F_AGGRMODE) != 0) ||
    691  10266    Quaker 	    (ic->ic_opmode == IEEE80211_M_STA &&
    692  10266    Quaker 	    (ic->ic_bss->in_flags & IEEE80211_NODE_QOS) == 0) ||
    693  10266    Quaker 	    (ic->ic_flags & IEEE80211_F_WME) == 0) {
    694  10266    Quaker 		chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
    695  10266    Quaker 		bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
    696  10266    Quaker 
    697  10266    Quaker 		chanp->wmep_aifsn = bssp->wmep_aifsn = phyParam[mode].aifsn;
    698  10266    Quaker 		chanp->wmep_logcwmin = bssp->wmep_logcwmin =
    699  10266    Quaker 		    phyParam[mode].logcwmin;
    700  10266    Quaker 		chanp->wmep_logcwmax = bssp->wmep_logcwmax =
    701  10266    Quaker 		    phyParam[mode].logcwmax;
    702  10266    Quaker 		chanp->wmep_txopLimit = bssp->wmep_txopLimit =
    703  10266    Quaker 		    (ic->ic_flags & IEEE80211_F_BURST) ?
    704  10266    Quaker 		    phyParam[mode].txopLimit : 0;
    705  10266    Quaker 		ieee80211_dbg(IEEE80211_MSG_WME,
    706  10266    Quaker 		    "ieee80211_wme_updateparams_locked: "
    707  10266    Quaker 		    "%s [acm %u aifsn %u log2(cwmin) %u "
    708  10266    Quaker 		    "log2(cwmax) %u txpoLimit %u]\n",
    709  10266    Quaker 		    ieee80211_wme_acnames[WME_AC_BE],
    710  10266    Quaker 		    chanp->wmep_acm,
    711  10266    Quaker 		    chanp->wmep_aifsn,
    712  10266    Quaker 		    chanp->wmep_logcwmin,
    713  10266    Quaker 		    chanp->wmep_logcwmax,
    714  10266    Quaker 		    chanp->wmep_txopLimit);
    715  10266    Quaker 	}
    716  10266    Quaker 
    717  10266    Quaker 	wme->wme_update(ic);
    718  10266    Quaker 
    719  10266    Quaker 	ieee80211_dbg(IEEE80211_MSG_WME, "ieee80211_wme_updateparams(): "
    720  10266    Quaker 	    "%s: WME params updated, cap_info 0x%x\n",
    721  10266    Quaker 	    ic->ic_opmode == IEEE80211_M_STA ?
    722  10266    Quaker 	    wme->wme_wmeChanParams.cap_info :
    723  10266    Quaker 	    wme->wme_bssChanParams.cap_info);
    724   3147  xc151355 }
    725   3147  xc151355 
    726   3147  xc151355 /*
    727   3147  xc151355  * Process STA mode beacon miss events. Send a direct probe request
    728   3147  xc151355  * frame to the current ap bmiss_max times (w/o answer) before
    729   3147  xc151355  * scanning for a new ap.
    730   3147  xc151355  */
    731   3147  xc151355 void
    732   3147  xc151355 ieee80211_beacon_miss(ieee80211com_t *ic)
    733   3147  xc151355 {
    734   3147  xc151355 	ieee80211_impl_t *im = ic->ic_private;
    735   3147  xc151355 
    736   3147  xc151355 	if (ic->ic_flags & IEEE80211_F_SCAN)
    737   3147  xc151355 		return;
    738   3147  xc151355 	ieee80211_dbg(IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
    739   8594       Fei 	    "%s\n", "beacon miss");
    740   3147  xc151355 
    741   3147  xc151355 	/*
    742   3147  xc151355 	 * Our handling is only meaningful for stations that are
    743   3147  xc151355 	 * associated; any other conditions else will be handled
    744   3147  xc151355 	 * through different means (e.g. the tx timeout on mgt frames).
    745   3147  xc151355 	 */
    746   3147  xc151355 	if (ic->ic_opmode != IEEE80211_M_STA ||
    747   3147  xc151355 	    ic->ic_state != IEEE80211_S_RUN) {
    748   3147  xc151355 		return;
    749   3147  xc151355 	}
    750   3147  xc151355 
    751   3147  xc151355 	IEEE80211_LOCK(ic);
    752   3147  xc151355 	if (++im->im_bmiss_count < im->im_bmiss_max) {
    753   3147  xc151355 		/*
    754   3147  xc151355 		 * Send a directed probe req before falling back to a scan;
    755   3147  xc151355 		 * if we receive a response ic_bmiss_count will be reset.
    756   3147  xc151355 		 * Some cards mistakenly report beacon miss so this avoids
    757   3147  xc151355 		 * the expensive scan if the ap is still there.
    758   3147  xc151355 		 */
    759   3147  xc151355 		IEEE80211_UNLOCK(ic);
    760   3147  xc151355 		(void) ieee80211_send_probereq(ic->ic_bss, ic->ic_macaddr,
    761   8594       Fei 		    ic->ic_bss->in_bssid, ic->ic_bss->in_bssid,
    762   8594       Fei 		    ic->ic_bss->in_essid, ic->ic_bss->in_esslen,
    763   8594       Fei 		    ic->ic_opt_ie, ic->ic_opt_ie_len);
    764   3147  xc151355 		return;
    765   3147  xc151355 	}
    766   3147  xc151355 	im->im_bmiss_count = 0;
    767   3147  xc151355 	IEEE80211_UNLOCK(ic);
    768   3147  xc151355 	ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
    769   3147  xc151355 }
    770   3147  xc151355 
    771   3147  xc151355 /*
    772   3147  xc151355  * Manage state transition between INIT | AUTH | ASSOC | RUN.
    773   3147  xc151355  */
    774   3147  xc151355 static int
    775   3147  xc151355 ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
    776   3147  xc151355 {
    777   3147  xc151355 	struct ieee80211_impl *im = ic->ic_private;
    778   3147  xc151355 	ieee80211_node_t *in;
    779   3147  xc151355 	enum ieee80211_state ostate;
    780   3147  xc151355 	wifi_data_t wd = { 0 };
    781   3147  xc151355 
    782   3147  xc151355 	IEEE80211_LOCK(ic);
    783   3147  xc151355 	ostate = ic->ic_state;
    784   3147  xc151355 	ieee80211_dbg(IEEE80211_MSG_STATE, "ieee80211_newstate(): "
    785   8594       Fei 	    "%s -> %s\n",
    786   8594       Fei 	    ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
    787   3147  xc151355 	ic->ic_state = nstate;
    788   3147  xc151355 	in = ic->ic_bss;
    789   3147  xc151355 	im->im_swbmiss_period = 0;	/* Reset software beacon miss period */
    790   3147  xc151355 
    791   3147  xc151355 	switch (nstate) {
    792   3147  xc151355 	case IEEE80211_S_INIT:
    793   3147  xc151355 		IEEE80211_UNLOCK(ic);
    794   3147  xc151355 		switch (ostate) {
    795   3147  xc151355 		case IEEE80211_S_INIT:
    796   3147  xc151355 			return (0);
    797   3147  xc151355 		case IEEE80211_S_SCAN:
    798   3147  xc151355 			ieee80211_cancel_scan(ic);
    799   3147  xc151355 			break;
    800   3147  xc151355 		case IEEE80211_S_AUTH:
    801   3147  xc151355 			break;
    802   3147  xc151355 		case IEEE80211_S_ASSOC:
    803   3147  xc151355 			if (ic->ic_opmode == IEEE80211_M_STA) {
    804   3147  xc151355 				IEEE80211_SEND_MGMT(ic, in,
    805   8594       Fei 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
    806   8594       Fei 				    IEEE80211_REASON_AUTH_LEAVE);
    807   3147  xc151355 			}
    808   3147  xc151355 			break;
    809   3147  xc151355 		case IEEE80211_S_RUN:
    810   8594       Fei 			switch (ic->ic_opmode) {
    811   8594       Fei 			case IEEE80211_M_STA:
    812   3147  xc151355 				IEEE80211_SEND_MGMT(ic, in,
    813  10266    Quaker 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
    814  10266    Quaker 				    IEEE80211_REASON_AUTH_LEAVE);
    815   3147  xc151355 				ieee80211_sta_leave(ic, in);
    816   8594       Fei 				break;
    817   8594       Fei 			case IEEE80211_M_IBSS:
    818   8594       Fei 				ieee80211_notify_node_leave(ic, in);
    819   8594       Fei 				break;
    820   8594       Fei 			default:
    821   8594       Fei 				break;
    822   3147  xc151355 			}
    823   3147  xc151355 			break;
    824   3147  xc151355 		}
    825   3147  xc151355 		IEEE80211_LOCK(ic);
    826   3147  xc151355 		im->im_mgt_timer = 0;
    827   3147  xc151355 		ieee80211_reset_bss(ic);
    828   3147  xc151355 		break;
    829   3147  xc151355 	case IEEE80211_S_SCAN:
    830   3147  xc151355 		switch (ostate) {
    831   3147  xc151355 		case IEEE80211_S_INIT:
    832   8594       Fei 			IEEE80211_UNLOCK(ic);
    833   8594       Fei 			ieee80211_begin_scan(ic, (arg == 0) ? B_FALSE : B_TRUE);
    834   8594       Fei 			return (0);
    835   3147  xc151355 		case IEEE80211_S_SCAN:
    836   3147  xc151355 			/*
    837   3147  xc151355 			 * Scan next. If doing an active scan and the
    838   3147  xc151355 			 * channel is not marked passive-only then send
    839   3147  xc151355 			 * a probe request.  Otherwise just listen for
    840   3147  xc151355 			 * beacons on the channel.
    841   3147  xc151355 			 */
    842   3147  xc151355 			if ((ic->ic_flags & IEEE80211_F_ASCAN) &&
    843   3147  xc151355 			    !IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan)) {
    844   3147  xc151355 				IEEE80211_UNLOCK(ic);
    845   3147  xc151355 				(void) ieee80211_send_probereq(in,
    846   8594       Fei 				    ic->ic_macaddr, wifi_bcastaddr,
    847   8594       Fei 				    wifi_bcastaddr,
    848   8594       Fei 				    ic->ic_des_essid, ic->ic_des_esslen,
    849   8594       Fei 				    ic->ic_opt_ie, ic->ic_opt_ie_len);
    850   3147  xc151355 				return (0);
    851   3147  xc151355 			}
    852   3147  xc151355 			break;
    853   3147  xc151355 		case IEEE80211_S_RUN:
    854   3147  xc151355 			/* beacon miss */
    855   3147  xc151355 			ieee80211_dbg(IEEE80211_MSG_STATE,
    856   8594       Fei 			    "no recent beacons from %s, rescanning\n",
    857   8594       Fei 			    ieee80211_macaddr_sprintf(in->in_macaddr));
    858   3147  xc151355 			IEEE80211_UNLOCK(ic);
    859   3147  xc151355 			ieee80211_sta_leave(ic, in);
    860   3147  xc151355 			IEEE80211_LOCK(ic);
    861   3147  xc151355 			ic->ic_flags &= ~IEEE80211_F_SIBSS;
    862   3147  xc151355 			/* FALLTHRU */
    863   3147  xc151355 		case IEEE80211_S_AUTH:
    864   3147  xc151355 		case IEEE80211_S_ASSOC:
    865   3147  xc151355 			/* timeout restart scan */
    866   3147  xc151355 			in = ieee80211_find_node(&ic->ic_scan,
    867   8594       Fei 			    ic->ic_bss->in_macaddr);
    868   3147  xc151355 			if (in != NULL) {
    869   3147  xc151355 				in->in_fails++;
    870   3147  xc151355 				ieee80211_unref_node(&in);
    871   3147  xc151355 			}
    872   3147  xc151355 			break;
    873   3147  xc151355 		}
    874   3147  xc151355 		break;
    875   3147  xc151355 	case IEEE80211_S_AUTH:
    876   8594       Fei 		ASSERT(ic->ic_opmode == IEEE80211_M_STA);
    877   3147  xc151355 		switch (ostate) {
    878   3147  xc151355 		case IEEE80211_S_INIT:
    879   3147  xc151355 		case IEEE80211_S_SCAN:
    880   3147  xc151355 			IEEE80211_UNLOCK(ic);
    881   3147  xc151355 			IEEE80211_SEND_MGMT(ic, in, IEEE80211_FC0_SUBTYPE_AUTH,
    882   8594       Fei 			    1);
    883   3147  xc151355 			return (0);
    884   3147  xc151355 		case IEEE80211_S_AUTH:
    885   3147  xc151355 		case IEEE80211_S_ASSOC:
    886   3147  xc151355 			switch (arg) {
    887   3147  xc151355 			case IEEE80211_FC0_SUBTYPE_AUTH:
    888   3147  xc151355 				IEEE80211_UNLOCK(ic);
    889   3147  xc151355 				IEEE80211_SEND_MGMT(ic, in,
    890   8594       Fei 				    IEEE80211_FC0_SUBTYPE_AUTH, 2);
    891   3147  xc151355 				return (0);
    892   3147  xc151355 			case IEEE80211_FC0_SUBTYPE_DEAUTH:
    893   3147  xc151355 				/* ignore and retry scan on timeout */
    894   3147  xc151355 				break;
    895   3147  xc151355 			}
    896   3147  xc151355 			break;
    897   3147  xc151355 		case IEEE80211_S_RUN:
    898   3147  xc151355 			switch (arg) {
    899   3147  xc151355 			case IEEE80211_FC0_SUBTYPE_AUTH:
    900   3147  xc151355 				ic->ic_state = ostate;	/* stay RUN */
    901   3147  xc151355 				IEEE80211_UNLOCK(ic);
    902   3147  xc151355 				IEEE80211_SEND_MGMT(ic, in,
    903   8594       Fei 				    IEEE80211_FC0_SUBTYPE_AUTH, 2);
    904   3147  xc151355 				return (0);
    905   3147  xc151355 			case IEEE80211_FC0_SUBTYPE_DEAUTH:
    906   3147  xc151355 				IEEE80211_UNLOCK(ic);
    907   3147  xc151355 				ieee80211_sta_leave(ic, in);
    908   3147  xc151355 				/* try to re-auth */
    909   3147  xc151355 				IEEE80211_SEND_MGMT(ic, in,
    910   8594       Fei 				    IEEE80211_FC0_SUBTYPE_AUTH, 1);
    911   3147  xc151355 				return (0);
    912   3147  xc151355 			}
    913   3147  xc151355 			break;
    914   3147  xc151355 		}
    915   3147  xc151355 		break;
    916   3147  xc151355 	case IEEE80211_S_ASSOC:
    917   8594       Fei 		ASSERT(ic->ic_opmode == IEEE80211_M_STA);
    918   3147  xc151355 		switch (ostate) {
    919   3147  xc151355 		case IEEE80211_S_INIT:
    920   3147  xc151355 		case IEEE80211_S_SCAN:
    921   3147  xc151355 		case IEEE80211_S_ASSOC:
    922   3147  xc151355 			ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_newstate: "
    923   8594       Fei 			    "invalid transition\n");
    924   3147  xc151355 			break;
    925   3147  xc151355 		case IEEE80211_S_AUTH:
    926   3147  xc151355 			IEEE80211_UNLOCK(ic);
    927   3147  xc151355 			IEEE80211_SEND_MGMT(ic, in,
    928   8594       Fei 			    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
    929   3147  xc151355 			return (0);
    930   3147  xc151355 		case IEEE80211_S_RUN:
    931   3147  xc151355 			IEEE80211_UNLOCK(ic);
    932   3147  xc151355 			ieee80211_sta_leave(ic, in);
    933   3147  xc151355 			IEEE80211_SEND_MGMT(ic, in,
    934   8594       Fei 			    IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
    935   3147  xc151355 			return (0);
    936   3147  xc151355 		}
    937   3147  xc151355 		break;
    938   3147  xc151355 	case IEEE80211_S_RUN:
    939   3147  xc151355 		switch (ostate) {
    940   3147  xc151355 		case IEEE80211_S_INIT:
    941   3147  xc151355 			ieee80211_err("ieee80211_newstate: "
    942   8594       Fei 			    "invalid transition\n");
    943   3147  xc151355 			break;
    944   3147  xc151355 		case IEEE80211_S_AUTH:
    945   3147  xc151355 			ieee80211_err("ieee80211_newstate: "
    946   8594       Fei 			    "invalid transition\n");
    947   3147  xc151355 			break;
    948   3147  xc151355 		case IEEE80211_S_SCAN:		/* adhoc/hostap mode */
    949   3147  xc151355 		case IEEE80211_S_ASSOC:		/* infra mode */
    950   3147  xc151355 			ASSERT(in->in_txrate < in->in_rates.ir_nrates);
    951   3147  xc151355 			im->im_mgt_timer = 0;
    952   8594       Fei 			ieee80211_notify_node_join(ic, in);
    953   3147  xc151355 
    954   3147  xc151355 			/*
    955   3147  xc151355 			 * We can send data now; update the fastpath with our
    956   3147  xc151355 			 * current associated BSSID and other relevant settings.
    957   3147  xc151355 			 */
    958   3147  xc151355 			wd.wd_secalloc = ieee80211_crypto_getciphertype(ic);
    959   3147  xc151355 			wd.wd_opmode = ic->ic_opmode;
    960   3147  xc151355 			IEEE80211_ADDR_COPY(wd.wd_bssid, in->in_bssid);
    961  10266    Quaker 			wd.wd_qospad = 0;
    962  10266    Quaker 			if (in->in_flags &
    963  10266    Quaker 			    (IEEE80211_NODE_QOS|IEEE80211_NODE_HT)) {
    964  10266    Quaker 				wd.wd_qospad = 2;
    965  10266    Quaker 				if (ic->ic_flags & IEEE80211_F_DATAPAD) {
    966  10266    Quaker 					wd.wd_qospad = roundup(wd.wd_qospad,
    967  10266    Quaker 					    sizeof (uint32_t));
    968  10266    Quaker 				}
    969  10266    Quaker 			}
    970   3147  xc151355 			(void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd));
    971   3147  xc151355 			break;
    972   3147  xc151355 		}
    973   3147  xc151355 
    974   3147  xc151355 		/*
    975   3147  xc151355 		 * When 802.1x is not in use mark the port authorized
    976   3147  xc151355 		 * at this point so traffic can flow.
    977   3147  xc151355 		 */
    978   3147  xc151355 		if (in->in_authmode != IEEE80211_AUTH_8021X)
    979   3147  xc151355 			ieee80211_node_authorize(in);
    980   3147  xc151355 		/*
    981   3147  xc151355 		 * Enable inactivity processing.
    982   3147  xc151355 		 */
    983   3147  xc151355 		ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT;
    984   3147  xc151355 		ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT;
    985   3147  xc151355 		break;	/* IEEE80211_S_RUN */
    986   3147  xc151355 	} /* switch nstate */
    987   3147  xc151355 	IEEE80211_UNLOCK(ic);
    988   3147  xc151355 
    989   3147  xc151355 	return (0);
    990   3147  xc151355 }
    991