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