2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2 as published by the Free
19 * Software Foundation.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
37 * IEEE 802.11 protocol support.
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
46 #include <sys/socket.h>
49 #include <net/if_media.h>
50 #include <net/ethernet.h> /* XXX for ether_sprintf */
52 #include <net80211/ieee80211_var.h>
55 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
56 #define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */
58 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
60 const char *ieee80211_mgt_subtype_name[] = {
61 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
62 "probe_req", "probe_resp", "reserved#6", "reserved#7",
63 "beacon", "atim", "disassoc", "auth",
64 "deauth", "reserved#13", "reserved#14", "reserved#15"
66 const char *ieee80211_ctl_subtype_name[] = {
67 "reserved#0", "reserved#1", "reserved#2", "reserved#3",
68 "reserved#3", "reserved#5", "reserved#6", "reserved#7",
69 "reserved#8", "reserved#9", "ps_poll", "rts",
70 "cts", "ack", "cf_end", "cf_end_ack"
72 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
73 "INIT", /* IEEE80211_S_INIT */
74 "SCAN", /* IEEE80211_S_SCAN */
75 "AUTH", /* IEEE80211_S_AUTH */
76 "ASSOC", /* IEEE80211_S_ASSOC */
77 "RUN" /* IEEE80211_S_RUN */
79 const char *ieee80211_wme_acnames[] = {
87 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
90 ieee80211_proto_attach(struct ieee80211com *ic)
92 struct ifnet *ifp = ic->ic_ifp;
94 /* XXX room for crypto */
95 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
98 ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
100 ic->ic_rtsthreshold = IEEE80211_RTS_MAX;
102 ic->ic_fragthreshold = 2346; /* XXX not used yet */
103 ic->ic_fixed_rate = -1; /* no fixed rate */
104 ic->ic_protmode = IEEE80211_PROT_CTSONLY;
105 ic->ic_roaming = IEEE80211_ROAMING_AUTO;
107 ic->ic_wme.wme_hipri_switch_hysteresis =
108 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
110 mtx_init(&ic->ic_mgtq.ifq_mtx, ifp->if_xname, "mgmt send q", MTX_DEF);
112 /* protocol state change handler */
113 ic->ic_newstate = ieee80211_newstate;
115 /* initialize management frame handlers */
116 ic->ic_recv_mgmt = ieee80211_recv_mgmt;
117 ic->ic_send_mgmt = ieee80211_send_mgmt;
121 ieee80211_proto_detach(struct ieee80211com *ic)
125 * This should not be needed as we detach when reseting
126 * the state but be conservative here since the
127 * authenticator may do things like spawn kernel threads.
129 if (ic->ic_auth->ia_detach)
130 ic->ic_auth->ia_detach(ic);
132 IF_DRAIN(&ic->ic_mgtq);
133 mtx_destroy(&ic->ic_mgtq.ifq_mtx);
136 * Detach any ACL'ator.
138 if (ic->ic_acl != NULL)
139 ic->ic_acl->iac_detach(ic);
143 * Simple-minded authenticator module support.
146 #define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1)
147 /* XXX well-known names */
148 static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
149 "wlan_internal", /* IEEE80211_AUTH_NONE */
150 "wlan_internal", /* IEEE80211_AUTH_OPEN */
151 "wlan_internal", /* IEEE80211_AUTH_SHARED */
152 "wlan_xauth", /* IEEE80211_AUTH_8021X */
153 "wlan_internal", /* IEEE80211_AUTH_AUTO */
154 "wlan_xauth", /* IEEE80211_AUTH_WPA */
156 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
158 static const struct ieee80211_authenticator auth_internal = {
159 .ia_name = "wlan_internal",
162 .ia_node_join = NULL,
163 .ia_node_leave = NULL,
167 * Setup internal authenticators once; they are never unregistered.
170 ieee80211_auth_setup(void)
172 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
173 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
174 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
176 SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
178 const struct ieee80211_authenticator *
179 ieee80211_authenticator_get(int auth)
181 if (auth >= IEEE80211_AUTH_MAX)
183 if (authenticators[auth] == NULL)
184 ieee80211_load_module(auth_modnames[auth]);
185 return authenticators[auth];
189 ieee80211_authenticator_register(int type,
190 const struct ieee80211_authenticator *auth)
192 if (type >= IEEE80211_AUTH_MAX)
194 authenticators[type] = auth;
198 ieee80211_authenticator_unregister(int type)
201 if (type >= IEEE80211_AUTH_MAX)
203 authenticators[type] = NULL;
207 * Very simple-minded ACL module support.
209 /* XXX just one for now */
210 static const struct ieee80211_aclator *acl = NULL;
213 ieee80211_aclator_register(const struct ieee80211_aclator *iac)
215 printf("wlan: %s acl policy registered\n", iac->iac_name);
220 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
224 printf("wlan: %s acl policy unregistered\n", iac->iac_name);
227 const struct ieee80211_aclator *
228 ieee80211_aclator_get(const char *name)
231 ieee80211_load_module("wlan_acl");
232 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
236 ieee80211_print_essid(const u_int8_t *essid, int len)
241 if (len > IEEE80211_NWID_LEN)
242 len = IEEE80211_NWID_LEN;
243 /* determine printable or not */
244 for (i = 0, p = essid; i < len; i++, p++) {
245 if (*p < ' ' || *p > 0x7e)
250 for (i = 0, p = essid; i < len; i++, p++)
255 for (i = 0, p = essid; i < len; i++, p++)
261 ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi)
263 const struct ieee80211_frame *wh;
266 wh = (const struct ieee80211_frame *)buf;
267 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
268 case IEEE80211_FC1_DIR_NODS:
269 printf("NODS %s", ether_sprintf(wh->i_addr2));
270 printf("->%s", ether_sprintf(wh->i_addr1));
271 printf("(%s)", ether_sprintf(wh->i_addr3));
273 case IEEE80211_FC1_DIR_TODS:
274 printf("TODS %s", ether_sprintf(wh->i_addr2));
275 printf("->%s", ether_sprintf(wh->i_addr3));
276 printf("(%s)", ether_sprintf(wh->i_addr1));
278 case IEEE80211_FC1_DIR_FROMDS:
279 printf("FRDS %s", ether_sprintf(wh->i_addr3));
280 printf("->%s", ether_sprintf(wh->i_addr1));
281 printf("(%s)", ether_sprintf(wh->i_addr2));
283 case IEEE80211_FC1_DIR_DSTODS:
284 printf("DSDS %s", ether_sprintf((const u_int8_t *)&wh[1]));
285 printf("->%s", ether_sprintf(wh->i_addr3));
286 printf("(%s", ether_sprintf(wh->i_addr2));
287 printf("->%s)", ether_sprintf(wh->i_addr1));
290 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
291 case IEEE80211_FC0_TYPE_DATA:
294 case IEEE80211_FC0_TYPE_MGT:
295 printf(" %s", ieee80211_mgt_subtype_name[
296 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
297 >> IEEE80211_FC0_SUBTYPE_SHIFT]);
300 printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
303 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
306 for (i = 0; i < IEEE80211_WEP_IVLEN; i++)
307 printf(" %.02x", buf[sizeof(*wh)+i]);
308 printf(" KID %u]", buf[sizeof(*wh)+i] >> 6);
311 printf(" %dM", rate / 2);
313 printf(" +%d", rssi);
316 for (i = 0; i < len; i++) {
319 printf("%02x", buf[i]);
326 ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags)
328 #define RV(v) ((v) & IEEE80211_RATE_VAL)
329 int i, j, ignore, error;
330 int okrate, badrate, fixedrate;
331 struct ieee80211_rateset *srs, *nrs;
335 * If the fixed rate check was requested but no
336 * fixed has been defined then just remove it.
338 if ((flags & IEEE80211_F_DOFRATE) && ic->ic_fixed_rate < 0)
339 flags &= ~IEEE80211_F_DOFRATE;
341 okrate = badrate = fixedrate = 0;
342 srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
344 for (i = 0; i < nrs->rs_nrates; ) {
346 if (flags & IEEE80211_F_DOSORT) {
350 for (j = i + 1; j < nrs->rs_nrates; j++) {
351 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
352 r = nrs->rs_rates[i];
353 nrs->rs_rates[i] = nrs->rs_rates[j];
354 nrs->rs_rates[j] = r;
358 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
360 if (flags & IEEE80211_F_DOFRATE) {
362 * Check any fixed rate is included.
364 if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
367 if (flags & IEEE80211_F_DONEGO) {
369 * Check against supported rates.
371 for (j = 0; j < srs->rs_nrates; j++) {
372 if (r == RV(srs->rs_rates[j])) {
374 * Overwrite with the supported rate
375 * value so any basic rate bit is set.
376 * This insures that response we send
377 * to stations have the necessary basic
380 nrs->rs_rates[i] = srs->rs_rates[j];
384 if (j == srs->rs_nrates) {
386 * A rate in the node's rate set is not
387 * supported. If this is a basic rate and we
388 * are operating as an AP then this is an error.
389 * Otherwise we just discard/ignore the rate.
390 * Note that this is important for 11b stations
391 * when they want to associate with an 11g AP.
393 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
394 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
399 if (flags & IEEE80211_F_DODEL) {
401 * Delete unacceptable rates.
405 for (j = i; j < nrs->rs_nrates; j++)
406 nrs->rs_rates[j] = nrs->rs_rates[j + 1];
407 nrs->rs_rates[j] = 0;
412 okrate = nrs->rs_rates[i];
415 if (okrate == 0 || error != 0 ||
416 ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
417 return badrate | IEEE80211_RATE_BASIC;
424 * Reset 11g-related state.
427 ieee80211_reset_erp(struct ieee80211com *ic)
429 ic->ic_flags &= ~IEEE80211_F_USEPROT;
430 ic->ic_nonerpsta = 0;
431 ic->ic_longslotsta = 0;
433 * Short slot time is enabled only when operating in 11g
434 * and not in an IBSS. We must also honor whether or not
435 * the driver is capable of doing it.
437 ieee80211_set_shortslottime(ic,
438 ic->ic_curmode == IEEE80211_MODE_11A ||
439 (ic->ic_curmode == IEEE80211_MODE_11G &&
440 ic->ic_opmode == IEEE80211_M_HOSTAP &&
441 (ic->ic_caps & IEEE80211_C_SHSLOT)));
443 * Set short preamble and ERP barker-preamble flags.
445 if (ic->ic_curmode == IEEE80211_MODE_11A ||
446 (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) {
447 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
448 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
450 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
451 ic->ic_flags |= IEEE80211_F_USEBARKER;
456 * Set the short slot time state and notify the driver.
459 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
462 ic->ic_flags |= IEEE80211_F_SHSLOT;
464 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
466 if (ic->ic_updateslot != NULL)
467 ic->ic_updateslot(ic->ic_ifp);
471 * Check if the specified rate set supports ERP.
472 * NB: the rate set is assumed to be sorted.
475 ieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs)
477 #define N(a) (sizeof(a) / sizeof(a[0]))
478 static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
481 if (rs->rs_nrates < N(rates))
483 for (i = 0; i < N(rates); i++) {
484 for (j = 0; j < rs->rs_nrates; j++) {
485 int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
500 * Mark the basic rates for the 11g rate table based on the
501 * operating mode. For real 11g we mark all the 11b rates
502 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only
503 * 11b rates. There's also a pseudo 11a-mode used to mark only
504 * the basic OFDM rates.
507 ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode)
509 static const struct ieee80211_rateset basic[] = {
510 { 0 }, /* IEEE80211_MODE_AUTO */
511 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
512 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */
513 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */
514 { 0 }, /* IEEE80211_MODE_FH */
515 /* IEEE80211_MODE_PUREG (not yet) */
516 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
520 for (i = 0; i < rs->rs_nrates; i++) {
521 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
522 for (j = 0; j < basic[mode].rs_nrates; j++)
523 if (basic[mode].rs_rates[j] == rs->rs_rates[i]) {
524 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
531 * WME protocol support. The following parameters come from the spec.
533 typedef struct phyParamType {
541 static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
542 { 3, 4, 6 }, /* IEEE80211_MODE_AUTO */
543 { 3, 4, 6 }, /* IEEE80211_MODE_11A */
544 { 3, 5, 7 }, /* IEEE80211_MODE_11B */
545 { 3, 4, 6 }, /* IEEE80211_MODE_11G */
546 { 3, 5, 7 }, /* IEEE80211_MODE_FH */
547 { 2, 3, 5 }, /* IEEE80211_MODE_TURBO_A */
548 { 2, 3, 5 }, /* IEEE80211_MODE_TURBO_G */
550 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
551 { 7, 4, 10 }, /* IEEE80211_MODE_AUTO */
552 { 7, 4, 10 }, /* IEEE80211_MODE_11A */
553 { 7, 5, 10 }, /* IEEE80211_MODE_11B */
554 { 7, 4, 10 }, /* IEEE80211_MODE_11G */
555 { 7, 5, 10 }, /* IEEE80211_MODE_FH */
556 { 7, 3, 10 }, /* IEEE80211_MODE_TURBO_A */
557 { 7, 3, 10 }, /* IEEE80211_MODE_TURBO_G */
559 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
560 { 1, 3, 4, 94 }, /* IEEE80211_MODE_AUTO */
561 { 1, 3, 4, 94 }, /* IEEE80211_MODE_11A */
562 { 1, 4, 5, 188 }, /* IEEE80211_MODE_11B */
563 { 1, 3, 4, 94 }, /* IEEE80211_MODE_11G */
564 { 1, 4, 5, 188 }, /* IEEE80211_MODE_FH */
565 { 1, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_A */
566 { 1, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_G */
568 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
569 { 1, 2, 3, 47 }, /* IEEE80211_MODE_AUTO */
570 { 1, 2, 3, 47 }, /* IEEE80211_MODE_11A */
571 { 1, 3, 4, 102 }, /* IEEE80211_MODE_11B */
572 { 1, 2, 3, 47 }, /* IEEE80211_MODE_11G */
573 { 1, 3, 4, 102 }, /* IEEE80211_MODE_FH */
574 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_A */
575 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_G */
578 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
579 { 3, 4, 10 }, /* IEEE80211_MODE_AUTO */
580 { 3, 4, 10 }, /* IEEE80211_MODE_11A */
581 { 3, 5, 10 }, /* IEEE80211_MODE_11B */
582 { 3, 4, 10 }, /* IEEE80211_MODE_11G */
583 { 3, 5, 10 }, /* IEEE80211_MODE_FH */
584 { 2, 3, 10 }, /* IEEE80211_MODE_TURBO_A */
585 { 2, 3, 10 }, /* IEEE80211_MODE_TURBO_G */
587 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
588 { 2, 3, 4, 94 }, /* IEEE80211_MODE_AUTO */
589 { 2, 3, 4, 94 }, /* IEEE80211_MODE_11A */
590 { 2, 4, 5, 188 }, /* IEEE80211_MODE_11B */
591 { 2, 3, 4, 94 }, /* IEEE80211_MODE_11G */
592 { 2, 4, 5, 188 }, /* IEEE80211_MODE_FH */
593 { 2, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_A */
594 { 2, 2, 3, 94 }, /* IEEE80211_MODE_TURBO_G */
596 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
597 { 2, 2, 3, 47 }, /* IEEE80211_MODE_AUTO */
598 { 2, 2, 3, 47 }, /* IEEE80211_MODE_11A */
599 { 2, 3, 4, 102 }, /* IEEE80211_MODE_11B */
600 { 2, 2, 3, 47 }, /* IEEE80211_MODE_11G */
601 { 2, 3, 4, 102 }, /* IEEE80211_MODE_FH */
602 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_A */
603 { 1, 2, 2, 47 }, /* IEEE80211_MODE_TURBO_G */
607 ieee80211_wme_initparams(struct ieee80211com *ic)
609 struct ieee80211_wme_state *wme = &ic->ic_wme;
610 const paramType *pPhyParam, *pBssPhyParam;
611 struct wmeParams *wmep;
614 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
617 for (i = 0; i < WME_NUM_AC; i++) {
620 pPhyParam = &phyParamForAC_BK[ic->ic_curmode];
621 pBssPhyParam = &phyParamForAC_BK[ic->ic_curmode];
624 pPhyParam = &phyParamForAC_VI[ic->ic_curmode];
625 pBssPhyParam = &bssPhyParamForAC_VI[ic->ic_curmode];
628 pPhyParam = &phyParamForAC_VO[ic->ic_curmode];
629 pBssPhyParam = &bssPhyParamForAC_VO[ic->ic_curmode];
633 pPhyParam = &phyParamForAC_BE[ic->ic_curmode];
634 pBssPhyParam = &bssPhyParamForAC_BE[ic->ic_curmode];
638 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
639 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
640 wmep->wmep_acm = pPhyParam->acm;
641 wmep->wmep_aifsn = pPhyParam->aifsn;
642 wmep->wmep_logcwmin = pPhyParam->logcwmin;
643 wmep->wmep_logcwmax = pPhyParam->logcwmax;
644 wmep->wmep_txopLimit = pPhyParam->txopLimit;
646 wmep->wmep_acm = pBssPhyParam->acm;
647 wmep->wmep_aifsn = pBssPhyParam->aifsn;
648 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
649 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
650 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
653 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
654 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
655 "log2(cwmax) %u txpoLimit %u]\n", __func__
656 , ieee80211_wme_acnames[i]
659 , wmep->wmep_logcwmin
660 , wmep->wmep_logcwmax
661 , wmep->wmep_txopLimit
664 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
665 wmep->wmep_acm = pBssPhyParam->acm;
666 wmep->wmep_aifsn = pBssPhyParam->aifsn;
667 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;
668 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;
669 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
670 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
671 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u "
672 "log2(cwmax) %u txpoLimit %u]\n", __func__
673 , ieee80211_wme_acnames[i]
676 , wmep->wmep_logcwmin
677 , wmep->wmep_logcwmax
678 , wmep->wmep_txopLimit
681 /* NB: check ic_bss to avoid NULL deref on initial attach */
682 if (ic->ic_bss != NULL) {
684 * Calculate agressive mode switching threshold based
685 * on beacon interval. This doesn't need locking since
686 * we're only called before entering the RUN state at
687 * which point we start sending beacon frames.
689 wme->wme_hipri_switch_thresh =
690 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
691 ieee80211_wme_updateparams(ic);
696 * Update WME parameters for ourself and the BSS.
699 ieee80211_wme_updateparams_locked(struct ieee80211com *ic)
701 static const paramType phyParam[IEEE80211_MODE_MAX] = {
702 { 2, 4, 10, 64 }, /* IEEE80211_MODE_AUTO */
703 { 2, 4, 10, 64 }, /* IEEE80211_MODE_11A */
704 { 2, 5, 10, 64 }, /* IEEE80211_MODE_11B */
705 { 2, 4, 10, 64 }, /* IEEE80211_MODE_11G */
706 { 2, 5, 10, 64 }, /* IEEE80211_MODE_FH */
707 { 1, 3, 10, 64 }, /* IEEE80211_MODE_TURBO_A */
708 { 1, 3, 10, 64 }, /* IEEE80211_MODE_TURBO_G */
710 struct ieee80211_wme_state *wme = &ic->ic_wme;
711 const struct wmeParams *wmep;
712 struct wmeParams *chanp, *bssp;
715 /* set up the channel access parameters for the physical device */
716 for (i = 0; i < WME_NUM_AC; i++) {
717 chanp = &wme->wme_chanParams.cap_wmeParams[i];
718 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
719 chanp->wmep_aifsn = wmep->wmep_aifsn;
720 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
721 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
722 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
724 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
725 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
726 chanp->wmep_aifsn = wmep->wmep_aifsn;
727 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
728 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
729 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
733 * This implements agressive mode as found in certain
734 * vendors' AP's. When there is significant high
735 * priority (VI/VO) traffic in the BSS throttle back BE
736 * traffic by using conservative parameters. Otherwise
737 * BE uses agressive params to optimize performance of
738 * legacy/non-QoS traffic.
740 if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
741 (wme->wme_flags & WME_F_AGGRMODE) == 0) ||
742 (ic->ic_opmode != IEEE80211_M_HOSTAP &&
743 (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
744 (ic->ic_flags & IEEE80211_F_WME) == 0) {
745 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
746 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
748 chanp->wmep_aifsn = bssp->wmep_aifsn =
749 phyParam[ic->ic_curmode].aifsn;
750 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
751 phyParam[ic->ic_curmode].logcwmin;
752 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
753 phyParam[ic->ic_curmode].logcwmax;
754 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
755 (ic->ic_caps & IEEE80211_C_BURST) ?
756 phyParam[ic->ic_curmode].txopLimit : 0;
757 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
758 "%s: %s [acm %u aifsn %u log2(cwmin) %u "
759 "log2(cwmax) %u txpoLimit %u]\n", __func__
760 , ieee80211_wme_acnames[WME_AC_BE]
763 , chanp->wmep_logcwmin
764 , chanp->wmep_logcwmax
765 , chanp->wmep_txopLimit
769 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
770 ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) == 0) {
771 static const u_int8_t logCwMin[IEEE80211_MODE_MAX] = {
772 3, /* IEEE80211_MODE_AUTO */
773 3, /* IEEE80211_MODE_11A */
774 4, /* IEEE80211_MODE_11B */
775 3, /* IEEE80211_MODE_11G */
776 4, /* IEEE80211_MODE_FH */
777 3, /* IEEE80211_MODE_TURBO_A */
778 3, /* IEEE80211_MODE_TURBO_G */
780 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
781 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
783 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
784 logCwMin[ic->ic_curmode];
785 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
786 "%s: %s log2(cwmin) %u\n", __func__
787 , ieee80211_wme_acnames[WME_AC_BE]
788 , chanp->wmep_logcwmin
791 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */
793 * Arrange for a beacon update and bump the parameter
794 * set number so associated stations load the new values.
796 wme->wme_bssChanParams.cap_info =
797 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
798 ic->ic_flags |= IEEE80211_F_WMEUPDATE;
803 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
804 "%s: WME params updated, cap_info 0x%x\n", __func__,
805 ic->ic_opmode == IEEE80211_M_STA ?
806 wme->wme_wmeChanParams.cap_info :
807 wme->wme_bssChanParams.cap_info);
811 ieee80211_wme_updateparams(struct ieee80211com *ic)
814 if (ic->ic_caps & IEEE80211_C_WME) {
815 IEEE80211_BEACON_LOCK(ic);
816 ieee80211_wme_updateparams_locked(ic);
817 IEEE80211_BEACON_UNLOCK(ic);
822 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
824 struct ifnet *ifp = ic->ic_ifp;
825 struct ieee80211_node_table *nt;
826 struct ieee80211_node *ni;
827 enum ieee80211_state ostate;
829 ostate = ic->ic_state;
830 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
831 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
832 ic->ic_state = nstate; /* state transition */
833 ni = ic->ic_bss; /* NB: no reference held */
835 case IEEE80211_S_INIT:
837 case IEEE80211_S_INIT:
839 case IEEE80211_S_RUN:
840 switch (ic->ic_opmode) {
841 case IEEE80211_M_STA:
842 IEEE80211_SEND_MGMT(ic, ni,
843 IEEE80211_FC0_SUBTYPE_DISASSOC,
844 IEEE80211_REASON_ASSOC_LEAVE);
845 ieee80211_sta_leave(ic, ni);
847 case IEEE80211_M_HOSTAP:
849 IEEE80211_NODE_LOCK(nt);
850 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
851 if (ni->ni_associd == 0)
853 IEEE80211_SEND_MGMT(ic, ni,
854 IEEE80211_FC0_SUBTYPE_DISASSOC,
855 IEEE80211_REASON_ASSOC_LEAVE);
857 IEEE80211_NODE_UNLOCK(nt);
863 case IEEE80211_S_ASSOC:
864 switch (ic->ic_opmode) {
865 case IEEE80211_M_STA:
866 IEEE80211_SEND_MGMT(ic, ni,
867 IEEE80211_FC0_SUBTYPE_DEAUTH,
868 IEEE80211_REASON_AUTH_LEAVE);
870 case IEEE80211_M_HOSTAP:
872 IEEE80211_NODE_LOCK(nt);
873 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
874 IEEE80211_SEND_MGMT(ic, ni,
875 IEEE80211_FC0_SUBTYPE_DEAUTH,
876 IEEE80211_REASON_AUTH_LEAVE);
878 IEEE80211_NODE_UNLOCK(nt);
884 case IEEE80211_S_SCAN:
885 ieee80211_cancel_scan(ic);
887 case IEEE80211_S_AUTH:
889 ic->ic_mgt_timer = 0;
890 IF_DRAIN(&ic->ic_mgtq);
891 ieee80211_reset_bss(ic);
894 if (ic->ic_auth->ia_detach != NULL)
895 ic->ic_auth->ia_detach(ic);
897 case IEEE80211_S_SCAN:
899 case IEEE80211_S_INIT:
900 if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
901 ic->ic_opmode == IEEE80211_M_IBSS ||
902 ic->ic_opmode == IEEE80211_M_AHDEMO) &&
903 ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
905 * AP operation and we already have a channel;
906 * bypass the scan and startup immediately.
908 ieee80211_create_ibss(ic, ic->ic_des_chan);
910 ieee80211_begin_scan(ic, arg);
913 case IEEE80211_S_SCAN:
915 * Scan next. If doing an active scan and the
916 * channel is not marked passive-only then send
917 * a probe request. Otherwise just listen for
918 * beacons on the channel.
920 if ((ic->ic_flags & IEEE80211_F_ASCAN) &&
921 (ni->ni_chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {
922 IEEE80211_SEND_MGMT(ic, ni,
923 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0);
926 case IEEE80211_S_RUN:
928 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE,
929 "no recent beacons from %s; rescanning\n",
930 ether_sprintf(ic->ic_bss->ni_bssid));
931 ieee80211_sta_leave(ic, ni);
932 ic->ic_flags &= ~IEEE80211_F_SIBSS; /* XXX */
934 case IEEE80211_S_AUTH:
935 case IEEE80211_S_ASSOC:
936 /* timeout restart scan */
937 ni = ieee80211_find_node(&ic->ic_scan,
938 ic->ic_bss->ni_macaddr);
941 ieee80211_unref_node(&ni);
943 ieee80211_begin_scan(ic, arg);
947 case IEEE80211_S_AUTH:
949 case IEEE80211_S_INIT:
950 case IEEE80211_S_SCAN:
951 IEEE80211_SEND_MGMT(ic, ni,
952 IEEE80211_FC0_SUBTYPE_AUTH, 1);
954 case IEEE80211_S_AUTH:
955 case IEEE80211_S_ASSOC:
957 case IEEE80211_FC0_SUBTYPE_AUTH:
959 IEEE80211_SEND_MGMT(ic, ni,
960 IEEE80211_FC0_SUBTYPE_AUTH, 2);
962 case IEEE80211_FC0_SUBTYPE_DEAUTH:
963 /* ignore and retry scan on timeout */
967 case IEEE80211_S_RUN:
969 case IEEE80211_FC0_SUBTYPE_AUTH:
970 IEEE80211_SEND_MGMT(ic, ni,
971 IEEE80211_FC0_SUBTYPE_AUTH, 2);
972 ic->ic_state = ostate; /* stay RUN */
974 case IEEE80211_FC0_SUBTYPE_DEAUTH:
976 IEEE80211_SEND_MGMT(ic, ni,
977 IEEE80211_FC0_SUBTYPE_AUTH, 1);
978 ieee80211_sta_leave(ic, ni);
984 case IEEE80211_S_ASSOC:
986 case IEEE80211_S_INIT:
987 case IEEE80211_S_SCAN:
988 case IEEE80211_S_ASSOC:
989 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
990 "%s: invalid transition\n", __func__);
992 case IEEE80211_S_AUTH:
993 IEEE80211_SEND_MGMT(ic, ni,
994 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
996 case IEEE80211_S_RUN:
997 IEEE80211_SEND_MGMT(ic, ni,
998 IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
999 ieee80211_sta_leave(ic, ni);
1003 case IEEE80211_S_RUN:
1004 if (ic->ic_flags & IEEE80211_F_WPA) {
1005 /* XXX validate prerequisites */
1008 case IEEE80211_S_INIT:
1009 if (ic->ic_opmode == IEEE80211_M_MONITOR)
1012 case IEEE80211_S_AUTH:
1013 IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1014 "%s: invalid transition\n", __func__);
1016 case IEEE80211_S_RUN:
1018 case IEEE80211_S_SCAN: /* adhoc/hostap mode */
1019 case IEEE80211_S_ASSOC: /* infra mode */
1020 KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
1021 ("%s: bogus xmit rate %u setup\n", __func__,
1023 #ifdef IEEE80211_DEBUG
1024 if (ieee80211_msg_debug(ic)) {
1025 if (ic->ic_opmode == IEEE80211_M_STA)
1026 if_printf(ifp, "associated ");
1028 if_printf(ifp, "synchronized ");
1029 printf("with %s ssid ",
1030 ether_sprintf(ni->ni_bssid));
1031 ieee80211_print_essid(ic->ic_bss->ni_essid,
1033 printf(" channel %d start %uMb\n",
1034 ieee80211_chan2ieee(ic, ni->ni_chan),
1035 IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
1038 ic->ic_mgt_timer = 0;
1039 if (ic->ic_opmode == IEEE80211_M_STA)
1040 ieee80211_notify_node_join(ic, ni,
1041 arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1042 if_start(ifp); /* XXX not authorized yet */
1046 * Start/stop the authenticator when operating as an
1047 * AP. We delay until here to allow configuration to
1048 * happen out of order.
1050 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
1051 ic->ic_auth->ia_attach != NULL) {
1052 /* XXX check failure */
1053 ic->ic_auth->ia_attach(ic);
1054 } else if (ic->ic_auth->ia_detach != NULL) {
1055 ic->ic_auth->ia_detach(ic);
1058 * When 802.1x is not in use mark the port authorized
1059 * at this point so traffic can flow.
1061 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
1062 ieee80211_node_authorize(ic, ni);
1064 * Enable inactivity processing.
1067 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT;
1068 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT;