Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_node.c
Show First 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | ieee80211_node_set_chan(struct ieee80211_node *ni, | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
enum ieee80211_phymode mode; | enum ieee80211_phymode mode; | ||||
KASSERT(chan != IEEE80211_CHAN_ANYC, ("no channel")); | KASSERT(chan != IEEE80211_CHAN_ANYC, ("no channel")); | ||||
ni->ni_chan = chan; | ni->ni_chan = chan; | ||||
mode = ieee80211_chan2mode(chan); | mode = ieee80211_chan2mode(chan); | ||||
if (IEEE80211_IS_CHAN_VHT(chan)) { | |||||
/* Install VHT rate set. */ | |||||
ni->ni_vhtrates = *ieee80211_get_supvhtrates(ic); | |||||
} | |||||
if (IEEE80211_IS_CHAN_HT(chan)) { | if (IEEE80211_IS_CHAN_HT(chan)) { | ||||
/* | /* | ||||
* We must install the legacy rate est in ni_rates and the | * We must install the legacy rate est in ni_rates and the | ||||
* HT rate set in ni_htrates. | * HT rate set in ni_htrates. | ||||
*/ | */ | ||||
ni->ni_htrates = *ieee80211_get_suphtrates(ic, chan); | ni->ni_htrates = *ieee80211_get_suphtrates(ic); | ||||
/* | /* | ||||
* Setup bss tx parameters based on operating mode. We | * Setup bss tx parameters based on operating mode. We | ||||
* use legacy rates when operating in a mixed HT+non-HT bss | * use legacy rates when operating in a mixed HT+non-HT bss | ||||
* and non-ERP rates in 11g for mixed ERP+non-ERP bss. | * and non-ERP rates in 11g for mixed ERP+non-ERP bss. | ||||
*/ | */ | ||||
if (mode == IEEE80211_MODE_11NA && | if (mode == IEEE80211_MODE_11NA && | ||||
(vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | ||||
mode = IEEE80211_MODE_11A; | mode = IEEE80211_MODE_11A; | ||||
else if (mode == IEEE80211_MODE_11NG && | else if (mode == IEEE80211_MODE_11NG && | ||||
(vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | (vap->iv_flags_ht & IEEE80211_FHT_PUREN) == 0) | ||||
mode = IEEE80211_MODE_11G; | mode = IEEE80211_MODE_11G; | ||||
if (mode == IEEE80211_MODE_11G && | if (mode == IEEE80211_MODE_11G && | ||||
(vap->iv_flags & IEEE80211_F_PUREG) == 0) | (vap->iv_flags & IEEE80211_F_PUREG) == 0) | ||||
mode = IEEE80211_MODE_11B; | mode = IEEE80211_MODE_11B; | ||||
} | } | ||||
ni->ni_txparms = &vap->iv_txparms[mode]; | ni->ni_txparms = &vap->iv_txparms[mode]; | ||||
ni->ni_rates = *ieee80211_get_suprates(ic, chan); | ni->ni_rates = *ic->ic_sup_rates[mode]; | ||||
} | } | ||||
static __inline void | static __inline void | ||||
copy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss) | copy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss) | ||||
{ | { | ||||
/* propagate useful state */ | /* propagate useful state */ | ||||
nbss->ni_authmode = obss->ni_authmode; | nbss->ni_authmode = obss->ni_authmode; | ||||
nbss->ni_txpower = obss->ni_txpower; | nbss->ni_txpower = obss->ni_txpower; | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Test a node for suitability/compatibility. | * Test a node for suitability/compatibility. | ||||
*/ | */ | ||||
static int | static int | ||||
check_bss(struct ieee80211vap *vap, struct ieee80211_node *ni) | check_bss(struct ieee80211vap *vap, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
uint8_t rate; | int ret; | ||||
if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) | if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) | ||||
return 0; | return 0; | ||||
if (vap->iv_opmode == IEEE80211_M_IBSS) { | if (vap->iv_opmode == IEEE80211_M_IBSS) { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) | ||||
return 0; | return 0; | ||||
} | } | ||||
if (vap->iv_flags & IEEE80211_F_PRIVACY) { | if (vap->iv_flags & IEEE80211_F_PRIVACY) { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
/* XXX does this mean privacy is supported or required? */ | /* XXX does this mean privacy is supported or required? */ | ||||
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) | if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) | ||||
return 0; | return 0; | ||||
} | } | ||||
rate = ieee80211_fix_rate(ni, &ni->ni_rates, | ret = ieee80211_fix_rate(ni, &ni->ni_rates, | ||||
IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE); | IEEE80211_F_JOIN | IEEE80211_F_DONEGO | | ||||
if (rate & IEEE80211_RATE_BASIC) | IEEE80211_F_DOFIXED | IEEE80211_F_RATE_LEGACY); | ||||
if (ret & IEEE80211_F_RATESET_ERROR) | |||||
return 0; | return 0; | ||||
if (vap->iv_des_nssid != 0 && | if (vap->iv_des_nssid != 0 && | ||||
!match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid)) | !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid)) | ||||
return 0; | return 0; | ||||
if ((vap->iv_flags & IEEE80211_F_DESBSSID) && | if ((vap->iv_flags & IEEE80211_F_DESBSSID) && | ||||
!IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid)) | !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid)) | ||||
return 0; | return 0; | ||||
return 1; | return 1; | ||||
} | } | ||||
#ifdef IEEE80211_DEBUG | #ifdef IEEE80211_DEBUG | ||||
/* | /* | ||||
* Display node suitability/compatibility. | * Display node suitability/compatibility. | ||||
*/ | */ | ||||
static void | static void | ||||
check_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni) | check_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
uint8_t rate; | int ret, fail; | ||||
int fail; | |||||
fail = 0; | fail = 0; | ||||
if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) | if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) | ||||
fail |= 0x01; | fail |= 0x01; | ||||
if (vap->iv_opmode == IEEE80211_M_IBSS) { | if (vap->iv_opmode == IEEE80211_M_IBSS) { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) | ||||
fail |= 0x02; | fail |= 0x02; | ||||
} else { | } else { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) | ||||
fail |= 0x02; | fail |= 0x02; | ||||
} | } | ||||
if (vap->iv_flags & IEEE80211_F_PRIVACY) { | if (vap->iv_flags & IEEE80211_F_PRIVACY) { | ||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) | if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) | ||||
fail |= 0x04; | fail |= 0x04; | ||||
} else { | } else { | ||||
/* XXX does this mean privacy is supported or required? */ | /* XXX does this mean privacy is supported or required? */ | ||||
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) | if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) | ||||
fail |= 0x04; | fail |= 0x04; | ||||
} | } | ||||
rate = ieee80211_fix_rate(ni, &ni->ni_rates, | ret = ieee80211_fix_rate(ni, &ni->ni_rates, | ||||
IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE); | IEEE80211_F_JOIN | IEEE80211_F_DONEGO | | ||||
if (rate & IEEE80211_RATE_BASIC) | IEEE80211_F_DOFIXED | IEEE80211_F_RATE_LEGACY); | ||||
if (ret & IEEE80211_F_RATESET_ERROR) { | |||||
fail |= 0x08; | fail |= 0x08; | ||||
ret &= ~IEEE80211_F_RATESET_ERROR; /* for printf */ | |||||
} | |||||
if (vap->iv_des_nssid != 0 && | if (vap->iv_des_nssid != 0 && | ||||
!match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid)) | !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid)) | ||||
fail |= 0x10; | fail |= 0x10; | ||||
if ((vap->iv_flags & IEEE80211_F_DESBSSID) && | if ((vap->iv_flags & IEEE80211_F_DESBSSID) && | ||||
!IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid)) | !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid)) | ||||
fail |= 0x20; | fail |= 0x20; | ||||
printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr)); | printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr)); | ||||
printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' '); | printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' '); | ||||
printf(" %3d%c", | printf(" %3d%c", | ||||
ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' '); | ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' '); | ||||
printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2, | if (ret != IEEE80211_RATE_NONEXISTENT) | ||||
printf(" %2dM%c", ieee80211_convert_to_legacy_rate(ret) / 2, | |||||
fail & 0x08 ? '!' : ' '); | fail & 0x08 ? '!' : ' '); | ||||
else | |||||
printf(" <no rate>%c", fail & 0x08 ? '!' : ' '); | |||||
printf(" %4s%c", | printf(" %4s%c", | ||||
(ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : | (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : | ||||
(ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : | (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : | ||||
"????", | "????", | ||||
fail & 0x02 ? '!' : ' '); | fail & 0x02 ? '!' : ' '); | ||||
printf(" %3s%c ", | printf(" %3s%c ", | ||||
(ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" : "no", | (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" : "no", | ||||
fail & 0x04 ? '!' : ' '); | fail & 0x04 ? '!' : ' '); | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | ieee80211_sync_curchan(struct ieee80211com *ic) | ||||
struct ieee80211_channel *c; | struct ieee80211_channel *c; | ||||
c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, gethtadjustflags(ic)); | c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, gethtadjustflags(ic)); | ||||
c = ieee80211_vht_adjust_channel(ic, c, getvhtadjustflags(ic)); | c = ieee80211_vht_adjust_channel(ic, c, getvhtadjustflags(ic)); | ||||
if (c != ic->ic_curchan) { | if (c != ic->ic_curchan) { | ||||
ic->ic_curchan = c; | ic->ic_curchan = c; | ||||
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); | ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); | ||||
ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); | ic->ic_rt = ieee80211_get_ratetable(ic->ic_curmode); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
ic->ic_set_channel(ic); | ic->ic_set_channel(ic); | ||||
ieee80211_radiotap_chan_change(ic); | ieee80211_radiotap_chan_change(ic); | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
Show All 24 Lines | ieee80211_setupcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) | ||||
if (ic->ic_vhtcaps != 0) { | if (ic->ic_vhtcaps != 0) { | ||||
int flags = getvhtadjustflags(ic); | int flags = getvhtadjustflags(ic); | ||||
if (flags > ieee80211_vhtchanflags(c)) | if (flags > ieee80211_vhtchanflags(c)) | ||||
c = ieee80211_vht_adjust_channel(ic, c, flags); | c = ieee80211_vht_adjust_channel(ic, c, flags); | ||||
} | } | ||||
ic->ic_bsschan = ic->ic_curchan = c; | ic->ic_bsschan = ic->ic_curchan = c; | ||||
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); | ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); | ||||
ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); | ic->ic_rt = ieee80211_get_ratetable(ic->ic_curmode); | ||||
} | } | ||||
/* | /* | ||||
* Change the current channel. The channel change is guaranteed to have | * Change the current channel. The channel change is guaranteed to have | ||||
* happened before the next state change. | * happened before the next state change. | ||||
*/ | */ | ||||
void | void | ||||
ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) | ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (obss != NULL) { | ||||
obss = NULL; /* NB: guard against later use */ | obss = NULL; /* NB: guard against later use */ | ||||
} | } | ||||
/* | /* | ||||
* Delete unusable rates; we've already checked | * Delete unusable rates; we've already checked | ||||
* that the negotiated rate set is acceptable. | * that the negotiated rate set is acceptable. | ||||
*/ | */ | ||||
ieee80211_fix_rate(vap->iv_bss, &vap->iv_bss->ni_rates, | ieee80211_fix_rate(vap->iv_bss, &vap->iv_bss->ni_rates, | ||||
IEEE80211_F_DODEL | IEEE80211_F_JOIN); | IEEE80211_F_DODEL | IEEE80211_F_JOIN | | ||||
IEEE80211_F_RATE_LEGACY); | |||||
ieee80211_setcurchan(ic, selbs->ni_chan); | ieee80211_setcurchan(ic, selbs->ni_chan); | ||||
/* | /* | ||||
* Set the erp state (mostly the slot time) to deal with | * Set the erp state (mostly the slot time) to deal with | ||||
* the auto-select case; this should be redundant if the | * the auto-select case; this should be redundant if the | ||||
* mode is locked. | * mode is locked. | ||||
*/ | */ | ||||
ieee80211_reset_erp(ic); | ieee80211_reset_erp(ic); | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | if (ni->ni_ies.vhtopmode_ie != NULL && | ||||
} | } | ||||
} | } | ||||
/* Finally do the node channel change */ | /* Finally do the node channel change */ | ||||
if (do_ht) { | if (do_ht) { | ||||
ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, | ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, | ||||
ni->ni_ies.htinfo_ie); | ni->ni_ies.htinfo_ie); | ||||
ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie, | ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie, | ||||
IEEE80211_F_JOIN | IEEE80211_F_DOBRS); | IEEE80211_F_JOIN); | ||||
ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie); | ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie); | ||||
} | } | ||||
/* XXX else check for ath FF? */ | /* XXX else check for ath FF? */ | ||||
/* XXX QoS? Difficult given that WME config is specific to a master */ | /* XXX QoS? Difficult given that WME config is specific to a master */ | ||||
ieee80211_node_setuptxparms(ni); | ieee80211_node_setuptxparms(ni); | ||||
ieee80211_ratectl_node_init(ni); | ieee80211_ratectl_node_init(ni); | ||||
▲ Show 20 Lines • Show All 376 Lines • ▼ Show 20 Lines | #endif | ||||
ieee80211_add_node_nt(nt, ni); | ieee80211_add_node_nt(nt, ni); | ||||
ni->ni_vap = vap; | ni->ni_vap = vap; | ||||
ni->ni_ic = ic; | ni->ni_ic = ic; | ||||
IEEE80211_NODE_UNLOCK(nt); | IEEE80211_NODE_UNLOCK(nt); | ||||
IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni, | IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni, | ||||
"%s: inact_reload %u", __func__, ni->ni_inact_reload); | "%s: inact_reload %u", __func__, ni->ni_inact_reload); | ||||
ieee80211_ratectl_node_init(ni); | |||||
return ni; | return ni; | ||||
} | } | ||||
/* | /* | ||||
* Craft a temporary node suitable for sending a management frame | * Craft a temporary node suitable for sending a management frame | ||||
* to the specified station. We craft only as much state as we | * to the specified station. We craft only as much state as we | ||||
* need to do the work since the node will be immediately reclaimed | * need to do the work since the node will be immediately reclaimed | ||||
* once the send completes. | * once the send completes. | ||||
▲ Show 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | if ((ni->ni_ies.vhtcap_ie != NULL) && | ||||
(ni->ni_vap->iv_flags_vht & IEEE80211_FVHT_VHT)) { | (ni->ni_vap->iv_flags_vht & IEEE80211_FVHT_VHT)) { | ||||
do_vht_setup = 1; | do_vht_setup = 1; | ||||
} | } | ||||
} | } | ||||
/* NB: must be after ni_chan is setup */ | /* NB: must be after ni_chan is setup */ | ||||
ieee80211_setup_rates(ni, sp->rates, sp->xrates, | ieee80211_setup_rates(ni, sp->rates, sp->xrates, | ||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | | IEEE80211_F_DOSORT | IEEE80211_F_DOFIXED | | ||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL); | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); | ||||
/* | /* | ||||
* If the neighbor is HT compatible, flip that on. | * If the neighbor is HT compatible, flip that on. | ||||
*/ | */ | ||||
if (do_ht_setup) { | if (do_ht_setup) { | ||||
IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC, | IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC, | ||||
"%s: doing HT setup\n", __func__); | "%s: doing HT setup\n", __func__); | ||||
Show All 20 Lines | if (do_ht_setup) { | ||||
} | } | ||||
/* | /* | ||||
* Finally do the channel upgrade/change based | * Finally do the channel upgrade/change based | ||||
* on the HT/VHT configuration. | * on the HT/VHT configuration. | ||||
*/ | */ | ||||
ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, | ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, | ||||
ni->ni_ies.htinfo_ie); | ni->ni_ies.htinfo_ie); | ||||
ieee80211_setup_htrates(ni, | ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie, | ||||
ni->ni_ies.htcap_ie, | IEEE80211_F_JOIN); | ||||
IEEE80211_F_JOIN | IEEE80211_F_DOBRS); | |||||
ieee80211_setup_basic_htrates(ni, | ieee80211_setup_basic_htrates(ni, | ||||
ni->ni_ies.htinfo_ie); | ni->ni_ies.htinfo_ie); | ||||
ieee80211_node_setuptxparms(ni); | ieee80211_node_setuptxparms(ni); | ||||
ieee80211_ratectl_node_init(ni); | ieee80211_ratectl_node_init(ni); | ||||
/* Reassociate; we're now 11n/11ac */ | /* Reassociate; we're now 11n/11ac */ | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 1,220 Lines • Show Last 20 Lines |