📄 ieee80211_proto.c.svn-base
字号:
i++; } if (okrate == 0 || error != 0 || ((flags & IEEE80211_F_DOFRATE) && fixedrate != vap->iv_fixed_rate)) return badrate | IEEE80211_RATE_BASIC; else return RV(okrate);#undef RV}/* * Reset 11g-related state. */voidieee80211_reset_erp(struct ieee80211com *ic, enum ieee80211_phymode mode){#define IS_11G(m) \ ((m) == IEEE80211_MODE_11G || (m) == IEEE80211_MODE_TURBO_G) ic->ic_flags &= ~IEEE80211_F_USEPROT; /* * Preserve the long slot and nonerp station count if * switching between 11g and turboG. Otherwise, inactivity * will cause the turbo station to disassociate and possibly * try to leave the network. * XXX not right if really trying to reset state */ if (IS_11G(mode) ^ IS_11G(ic->ic_curmode)) { ic->ic_nonerpsta = 0; ic->ic_longslotsta = 0; } /* * Short slot time is enabled only when operating in 11g * and not in an IBSS. We must also honor whether or not * the driver is capable of doing it. */ ieee80211_set_shortslottime(ic, IEEE80211_IS_CHAN_A(ic->ic_curchan) || (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && ic->ic_opmode == IEEE80211_M_HOSTAP && (ic->ic_caps & IEEE80211_C_SHSLOT))); /* * Set short preamble and ERP barker-preamble flags. */ if (IEEE80211_IS_CHAN_A(ic->ic_curchan) || (ic->ic_caps & IEEE80211_C_SHPREAMBLE)) { ic->ic_flags |= IEEE80211_F_SHPREAMBLE; ic->ic_flags &= ~IEEE80211_F_USEBARKER; } else { ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; ic->ic_flags |= IEEE80211_F_USEBARKER; }#undef IS_11G}/* * Set the short slot time state and notify the driver. */voidieee80211_set_shortslottime(struct ieee80211com *ic, int onoff){ if (onoff) ic->ic_flags |= IEEE80211_F_SHSLOT; else ic->ic_flags &= ~IEEE80211_F_SHSLOT; /* notify driver */ if (ic->ic_updateslot != NULL) ic->ic_updateslot(ic->ic_dev);}/* * Check if the specified rate set supports ERP. * NB: the rate set is assumed to be sorted. */intieee80211_iserp_rateset(struct ieee80211com *ic, struct ieee80211_rateset *rs){ static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 }; int i, j; if (rs->rs_nrates < ARRAY_SIZE(rates)) return 0; for (i = 0; i < ARRAY_SIZE(rates); i++) { for (j = 0; j < rs->rs_nrates; j++) { int r = rs->rs_rates[j] & IEEE80211_RATE_VAL; if (rates[i] == r) goto next; if (r > rates[i]) return 0; } return 0; next: ; } return 1;}static const struct ieee80211_rateset basic11g[IEEE80211_MODE_MAX] = { { 0 }, /* IEEE80211_MODE_AUTO */ { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */ { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */ { 0 }, /* IEEE80211_MODE_FH */ { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_TURBO_A */ { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_TURBO_G (mixed b/g) */};/* * Mark the basic rates for the 11g rate table based on the * specified mode. For 11b compatibility we mark only 11b * rates. There's also a pseudo 11a-mode used to mark only * the basic OFDM rates; this is used to exclude 11b stations * from an 11g bss. */voidieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode){ int i, j; KASSERT(mode < IEEE80211_MODE_MAX, ("invalid mode %u", mode)); for (i = 0; i < rs->rs_nrates; i++) { rs->rs_rates[i] &= IEEE80211_RATE_VAL; for (j = 0; j < basic11g[mode].rs_nrates; j++) if (basic11g[mode].rs_rates[j] == rs->rs_rates[i]) { rs->rs_rates[i] |= IEEE80211_RATE_BASIC; break; } }}/* * Deduce the 11g setup by examining the rates * that are marked basic. */enum ieee80211_phymodeieee80211_get11gbasicrates(struct ieee80211_rateset *rs){ struct ieee80211_rateset basic; int i; memset(&basic, 0, sizeof(basic)); for (i = 0; i < rs->rs_nrates; i++) if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) basic.rs_rates[basic.rs_nrates++] = rs->rs_rates[i] & IEEE80211_RATE_VAL; for (i = 0; i < IEEE80211_MODE_MAX; i++) if (memcmp(&basic, &basic11g[i], sizeof(basic)) == 0) return i; return IEEE80211_MODE_AUTO;}voidieee80211_wme_initparams(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; IEEE80211_LOCK_IRQ(ic); ieee80211_wme_initparams_locked(vap); IEEE80211_UNLOCK_IRQ(ic);}voidieee80211_wme_initparams_locked(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_wme_state *wme = &ic->ic_wme; struct phyParamType { u_int8_t aifsn; u_int8_t logcwmin; u_int8_t logcwmax; u_int16_t txopLimit; u_int8_t acm; }; enum ieee80211_phymode mode; struct phyParamType *pPhyParam, *pBssPhyParam; static struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11A */ { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_11B */ { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_11G */ { 3, 4, 6, 0, 0 }, /* IEEE80211_MODE_FH */ { 3, 5, 7, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 3, 5, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 3, 5, 0, 0 }}; static struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_11B */ { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_11G */ { 7, 4, 10, 0, 0 }, /* IEEE80211_MODE_FH */ { 7, 5, 10, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 7, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 7, 3, 10, 0, 0 }}; static struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_11B */ { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_11G */ { 1, 3, 4, 94, 0 }, /* IEEE80211_MODE_FH */ { 1, 4, 5, 188, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 3, 94, 0 }}; static struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_11B */ { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_11G */ { 1, 2, 3, 47, 0 }, /* IEEE80211_MODE_FH */ { 1, 3, 4, 102, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 2, 47, 0 }}; static struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11A */ { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_11B */ { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_11G */ { 3, 4, 10, 0, 0 }, /* IEEE80211_MODE_FH */ { 3, 5, 10, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 3, 10, 0, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 3, 10, 0, 0 }}; static struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11A */ { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_11B */ { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_11G */ { 2, 3, 4, 94, 0 }, /* IEEE80211_MODE_FH */ { 2, 4, 5, 188, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 2, 3, 94, 0 }, /* IEEE80211_MODE_TURBO */ { 2, 2, 3, 94, 0 }}; static struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11A */ { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_11B */ { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_11G */ { 2, 2, 3, 47, 0 }, /* IEEE80211_MODE_FH */ { 2, 3, 4, 102, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 2, 47, 0 }, /* IEEE80211_MODE_TURBO */ { 1, 2, 2, 47, 0 }}; int i; IEEE80211_LOCK_ASSERT(ic); if ((ic->ic_caps & IEEE80211_C_WME) == 0) return; /* * Select mode; we can be called early in which case we * always use auto mode. We know we'll be called when * entering the RUN state with bsschan setup properly * so state will eventually get set correctly */ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) mode = ieee80211_chan2mode(ic->ic_bsschan); else mode = IEEE80211_MODE_AUTO; for (i = 0; i < WME_NUM_AC; i++) { switch (i) { case WME_AC_BK: pPhyParam = &phyParamForAC_BK[mode]; pBssPhyParam = &phyParamForAC_BK[mode]; break; case WME_AC_VI: pPhyParam = &phyParamForAC_VI[mode]; pBssPhyParam = &bssPhyParamForAC_VI[mode]; break; case WME_AC_VO: pPhyParam = &phyParamForAC_VO[mode]; pBssPhyParam = &bssPhyParamForAC_VO[mode]; break; case WME_AC_BE: default: pPhyParam = &phyParamForAC_BE[mode]; pBssPhyParam = &bssPhyParamForAC_BE[mode]; break; } if (ic->ic_opmode == IEEE80211_M_HOSTAP) { wme->wme_wmeChanParams.cap_wmeParams[i].wmep_acm = pPhyParam->acm; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_aifsn = pPhyParam->aifsn; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmin = pPhyParam->logcwmin; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmax = pPhyParam->logcwmax; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_txopLimit = pPhyParam->txopLimit; } else { wme->wme_wmeChanParams.cap_wmeParams[i].wmep_acm = pBssPhyParam->acm; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_aifsn = pBssPhyParam->aifsn; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmin = pBssPhyParam->logcwmin; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmax = pBssPhyParam->logcwmax; wme->wme_wmeChanParams.cap_wmeParams[i].wmep_txopLimit = pBssPhyParam->txopLimit; } wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_acm = pBssPhyParam->acm; wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_aifsn = pBssPhyParam->aifsn; wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_logcwmin = pBssPhyParam->logcwmin; wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_logcwmax = pBssPhyParam->logcwmax; wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_txopLimit = pBssPhyParam->txopLimit; } /* NB: check ic_bss to avoid NULL deref on initial attach */ if (vap->iv_bss != NULL) { /* * Calculate aggressive mode switching threshold based * on beacon interval. */ wme->wme_hipri_switch_thresh = (HIGH_PRI_SWITCH_THRESH * vap->iv_bss->ni_intval) / 100; ieee80211_wme_updateparams_locked(vap); }}/* * Update WME parameters for ourself and the BSS. */voidieee80211_wme_updateparams_locked(struct ieee80211vap *vap){ static const struct { u_int8_t aifsn; u_int8_t logcwmin; u_int8_t logcwmax; u_int16_t txopLimit;} phyParam[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ { 2, 4, 10, 64 }, /* IEEE80211_MODE_11A */ { 2, 4, 10, 64 }, /* IEEE80211_MODE_11B */ { 2, 5, 10, 64 }, /* IEEE80211_MODE_11G */ { 2, 4, 10, 64 }, /* IEEE80211_MODE_FH */ { 2, 5, 10, 64 }, /* IEEE80211_MODE_TURBO */ { 1, 3, 10, 64 }}; struct ieee80211com *ic = vap->iv_ic; struct ieee80211_wme_state *wme = &ic->ic_wme; enum ieee80211_phymode mode; int i; IEEE80211_LOCK_ASSERT(vap->iv_ic); /* set up the channel access parameters for the physical device */ for (i = 0; i < WME_NUM_AC; i++) { wme->wme_chanParams.cap_wmeParams[i].wmep_aifsn = wme->wme_wmeChanParams.cap_wmeParams[i].wmep_aifsn; wme->wme_chanParams.cap_wmeParams[i].wmep_logcwmin = wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmin; wme->wme_chanParams.cap_wmeParams[i].wmep_logcwmax = wme->wme_wmeChanParams.cap_wmeParams[i].wmep_logcwmax; wme->wme_chanParams.cap_wmeParams[i].wmep_txopLimit = wme->wme_wmeChanParams.cap_wmeParams[i].wmep_txopLimit; wme->wme_bssChanParams.cap_wmeParams[i].wmep_aifsn = wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_aifsn; wme->wme_bssChanParams.cap_wmeParams[i].wmep_logcwmin = wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_logcwmin; wme->wme_bssChanParams.cap_wmeParams[i].wmep_logcwmax = wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_logcwmax; wme->wme_bssChanParams.cap_wmeParams[i].wmep_txopLimit = wme->wme_wmeBssChanParams.cap_wmeParams[i].wmep_txopLimit; } /* * Select mode; we can be called early in which case we * always use auto mode. We know we'll be called when * entering the RUN state with bsschan setup properly * so state will eventually get set correctly */ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) mode = ieee80211_chan2mode(ic->ic_bsschan); else mode = IEEE80211_MODE_AUTO; if ((vap->iv_opmode == IEEE80211_M_HOSTAP && (wme->wme_flags & WME_F_AGGRMODE) != 0) || (vap->iv_opmode != IEEE80211_M_HOSTAP && (vap->iv_bss->ni_flags & IEEE80211_NODE_QOS) == 0) || (vap->iv_flags & IEEE80211_F_WME) == 0) { struct ieee80211vap *tmpvap; u_int8_t burstEnabled = 0; /* check if bursting enabled on at least one vap */ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { if (tmpvap->iv_ath_cap & IEEE80211_ATHC_BURST) { burstEnabled = 1; break; } } wme->wme_chanParams.cap_wmeParams[WME_AC_BE].wmep_aifsn = phyParam[mode].aifsn; wme->wme_chanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmin = phyParam[mode].logcwmin; wme->wme_chanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmax = phyParam[mode].logcwmax; wme->wme_chanParams.cap_wmeParams[WME_AC_BE].wmep_txopLimit = burstEnabled ? phyParam[mode].txopLimit : 0; wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE].wmep_aifsn = phyParam[mode].aifsn; wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmin = phyParam[mode].logcwmin; wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmax = phyParam[mode].logcwmax; wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE].wmep_txopLimit = burstEnabled ? phyParam[mode].txopLimit : 0; } if (ic->ic_opmode == IEEE80211_M_HOSTAP && ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) { static const u_int8_t logCwMin[IEEE80211_MODE_MAX] = { /* IEEE80211_MODE_AUTO */ 3, /* IEEE80211_MODE_11A */ 3, /* IEEE80211_MODE_11B */ 4, /* IEEE80211_MODE_11G */ 3, /* IEEE80211_MODE_FH */ 4, /* IEEE80211_MODE_TURBO_A */ 3, /* IEEE80211_MODE_TURBO_G */ 3 }; wme->wme_chanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmin = wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE].wmep_logcwmin = logCwMin[mode]; } if (vap->iv_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */ /* * Arrange for a beacon update and bump the parameter * set number so associated stations load the new values. */ wme->wme_bssChanParams.cap_info_count = (wme->wme_bssChanParams.cap_info_count + 1) & WME_QOSINFO_COUNT; vap->iv_flags |= IEEE80211_F_WMEUPDATE; } wme->wme_update(ic); IEEE80211_DPRINTF(vap, IEEE80211_MSG_WME, "%s: WME params updated, cap_info 0x%x\n", __func__, vap->iv_opmode == IEEE80211_M_STA ? wme->wme_wmeChanParams.cap_info_count : wme->wme_bssChanParams.cap_info_count);}EXPORT_SYMBOL(ieee80211_wme_updateparams);voidieee80211_wme_updateparams(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; if (ic->ic_caps & IEEE80211_C_WME) { IEEE80211_LOCK_IRQ(ic); ieee80211_wme_updateparams_locked(vap); IEEE80211_UNLOCK_IRQ(ic); }}/* * Start a vap. If this is the first vap running on the * underlying device then we first bring it up. */intieee80211_init(struct net_device *dev, int forcescan){#define IS_RUNNING(_dev) \ ((_dev->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP)) struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct net_device *parent = ic->ic_dev; IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, "start running (state=%d)\n", vap->iv_state); if ((dev->flags & IFF_RUNNING) == 0) { if (ic->ic_nopened++ == 0 && (parent->flags & IFF_RUNNING) == 0) dev_open(parent); /* * Mark us running. Note that we do this after * opening the parent device to avoid recursion. */ dev->flags |= IFF_RUNNING; /* mark us running */ } /* * If the parent is up and running, then kick the * 802.11 state machine as appropriate. * XXX parent should always be up+running */ if (IS_RUNNING(ic->ic_dev)) { if (vap->iv_opmode == IEEE80211_M_STA) { if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) { /* Try to be intelligent about clocking the * state machine. If we're currently in RUN * state then we should be able to apply any * new state/parameters simply by * re-associating. Otherwise we need to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -