📄 ieee80211_proto.c
字号:
/* * remove 0 rates * they don't make sense and can lead to trouble later */ if (r == 0) { nrs->rs_nrates--; for (j = i; j < nrs->rs_nrates; j++) nrs->rs_rates[j] = nrs->rs_rates[j + 1]; nrs->rs_rates[j] = 0; continue; } /* * Check for fixed rate. */ if (r == vap->iv_fixed_rate) fixedrate = r; if (flags & IEEE80211_F_DONEGO) { /* * Check against supported rates. */ for (j = 0; j < srs->rs_nrates; j++) { if (r == RV(srs->rs_rates[j])) { /* * Overwrite with the supported rate * value so any basic rate bit is set. * This ensures that response we send * to stations have the necessary basic * rate bit set. */ nrs->rs_rates[i] = srs->rs_rates[j]; break; } } if (j == srs->rs_nrates) { /* * A rate in the node's rate set is not * supported. If this is a basic rate and we * are operating as an AP then this is an error. * Otherwise we just discard/ignore the rate. * Note that this is important for 11b stations * when they want to associate with an 11g AP. */ if (vap->iv_opmode == IEEE80211_M_HOSTAP && (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) error++; ignore++; } } if (flags & IEEE80211_F_DODEL) { /* * Delete unacceptable rates. */ if (ignore) { nrs->rs_nrates--; for (j = i; j < nrs->rs_nrates; j++) nrs->rs_rates[j] = nrs->rs_rates[j + 1]; nrs->rs_rates[j] = 0; continue; } } if (!ignore) okrate = nrs->rs_rates[i]; 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){#define N(a) (sizeof(a) / sizeof(a[0])) static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 }; int i, j; if (rs->rs_nrates < N(rates)) return 0; for (i = 0; i < N(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;#undef N}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(ic); ieee80211_wme_initparams_locked(vap); IEEE80211_UNLOCK(ic);}voidieee80211_wme_initparams_locked(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_wme_state *wme = &ic->ic_wme; typedef struct phyParamType { u_int8_t aifsn; u_int8_t logcwmin; u_int8_t logcwmax; u_int16_t txopLimit; u_int8_t acm; } paramType; enum ieee80211_phymode mode; paramType *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; /* 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -