Lines Matching +full:switch +full:- +full:freq +full:- +full:select
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
99 (((const uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % STA_HASHSIZE)
112 /* ap-related state */
119 * for use. If non-zero the entry was deemed not suitable and it's
174 TAILQ_INIT(&st->st_entry); in sta_attach()
175 ss->ss_priv = st; in sta_attach()
186 struct sta_table *st = ss->ss_priv; in sta_detach()
194 nrefs--; /* NB: we assume caller locking */ in sta_detach()
200 * Flush all per-scan state.
205 struct sta_table *st = ss->ss_priv; in sta_flush()
210 ss->ss_last = 0; in sta_flush()
222 TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) { in sta_flush_table()
223 TAILQ_REMOVE(&st->st_entry, se, se_list); in sta_flush_table()
225 ieee80211_ies_cleanup(&se->base.se_ies); in sta_flush_table()
228 memset(st->st_maxrssi, 0, sizeof(st->st_maxrssi)); in sta_flush_table()
244 ((ss->ss_flags & (IEEE80211_SCAN_PICK1ST | IEEE80211_SCAN_GOTPICK)) == \ in sta_add()
246 struct sta_table *st = ss->ss_priv; in sta_add()
247 const uint8_t *macaddr = wh->i_addr2; in sta_add()
248 struct ieee80211vap *vap = ss->ss_vap; in sta_add()
249 struct ieee80211com *ic = vap->iv_ic; in sta_add()
258 LIST_FOREACH(se, &st->st_hash[hash], se_hash) in sta_add()
259 if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr)) in sta_add()
267 se->se_scangen = st->st_scaniter-1; in sta_add()
268 se->se_avgrssi = IEEE80211_RSSI_DUMMY_MARKER; in sta_add()
269 IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); in sta_add()
270 TAILQ_INSERT_TAIL(&st->st_entry, se, se_list); in sta_add()
271 LIST_INSERT_HEAD(&st->st_hash[hash], se, se_hash); in sta_add()
273 ise = &se->base; in sta_add()
275 if (sp->ssid[1] != 0 && in sta_add()
276 (ISPROBE(subtype) || ise->se_ssid[1] == 0)) in sta_add()
277 memcpy(ise->se_ssid, sp->ssid, 2+sp->ssid[1]); in sta_add()
278 KASSERT(sp->rates[1] <= IEEE80211_RATE_MAXSIZE, in sta_add()
279 ("rate set too large: %u", sp->rates[1])); in sta_add()
280 memcpy(ise->se_rates, sp->rates, 2+sp->rates[1]); in sta_add()
281 if (sp->xrates != NULL) { in sta_add()
283 KASSERT(sp->xrates[1] <= IEEE80211_RATE_MAXSIZE, in sta_add()
284 ("xrate set too large: %u", sp->xrates[1])); in sta_add()
285 memcpy(ise->se_xrates, sp->xrates, 2+sp->xrates[1]); in sta_add()
287 ise->se_xrates[1] = 0; in sta_add()
288 IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); in sta_add()
289 if ((sp->status & IEEE80211_BPARSE_OFFCHAN) == 0) { in sta_add()
293 * NB: use only on-channel data to insure we get a good in sta_add()
296 IEEE80211_RSSI_LPF(se->se_avgrssi, rssi); in sta_add()
297 ise->se_rssi = IEEE80211_RSSI_GET(se->se_avgrssi); in sta_add()
298 ise->se_noise = noise; in sta_add()
300 memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp)); in sta_add()
301 ise->se_intval = sp->bintval; in sta_add()
302 ise->se_capinfo = sp->capinfo; in sta_add()
304 if (sp->meshid != NULL && sp->meshid[1] != 0) in sta_add()
305 memcpy(ise->se_meshid, sp->meshid, 2+sp->meshid[1]); in sta_add()
309 * off-channel; this can cause us to attempt an in sta_add()
312 if (sp->status & IEEE80211_BPARSE_OFFCHAN) { in sta_add()
314 * Off-channel, locate the home/bss channel for the sta in sta_add()
316 * sp->chan has this value because it's used to calculate in sta_add()
319 c = ieee80211_find_channel_byieee(ic, sp->chan, in sta_add()
320 curchan->ic_flags); in sta_add()
322 ise->se_chan = c; in sta_add()
323 } else if (ise->se_chan == NULL) { in sta_add()
325 ise->se_chan = curchan; in sta_add()
328 ise->se_chan = curchan; in sta_add()
331 if (IEEE80211_IS_CHAN_VHT(ise->se_chan) && sp->vhtcap == NULL) { in sta_add()
333 "%s: demoting VHT->HT %d/0x%08x\n", in sta_add()
334 __func__, ise->se_chan->ic_freq, ise->se_chan->ic_flags); in sta_add()
335 /* Demote legacy networks to a non-VHT channel. */ in sta_add()
336 c = ieee80211_find_channel(ic, ise->se_chan->ic_freq, in sta_add()
337 ise->se_chan->ic_flags & ~IEEE80211_CHAN_VHT); in sta_add()
339 ("no non-VHT channel %u", ise->se_chan->ic_ieee)); in sta_add()
340 ise->se_chan = c; in sta_add()
344 if (IEEE80211_IS_CHAN_HT(ise->se_chan) && sp->htcap == NULL) { in sta_add()
345 /* Demote legacy networks to a non-HT channel. */ in sta_add()
347 "%s: demoting HT->legacy %d/0x%08x\n", in sta_add()
348 __func__, ise->se_chan->ic_freq, ise->se_chan->ic_flags); in sta_add()
349 c = ieee80211_find_channel(ic, ise->se_chan->ic_freq, in sta_add()
350 ise->se_chan->ic_flags & ~IEEE80211_CHAN_HT); in sta_add()
352 ("no legacy channel %u", ise->se_chan->ic_ieee)); in sta_add()
353 ise->se_chan = c; in sta_add()
356 ise->se_fhdwell = sp->fhdwell; in sta_add()
357 ise->se_fhindex = sp->fhindex; in sta_add()
358 ise->se_erp = sp->erp; in sta_add()
359 ise->se_timoff = sp->timoff; in sta_add()
360 if (sp->tim != NULL) { in sta_add()
362 (const struct ieee80211_tim_ie *) sp->tim; in sta_add()
363 ise->se_dtimperiod = tim->tim_period; in sta_add()
365 if (sp->country != NULL) { in sta_add()
367 (const struct ieee80211_country_ie *) sp->country; in sta_add()
377 if ((IEEE80211_IS_CHAN_11D(ise->se_chan) || in sta_add()
378 (vap->iv_flags_ext & IEEE80211_FEXT_DOTD)) && in sta_add()
379 (ic->ic_regdomain.country == CTRY_DEFAULT || in sta_add()
380 !isocmp(cie->cc, ic->ic_regdomain.isocc))) { in sta_add()
382 if (se->se_countrygen != st->st_scangen) { in sta_add()
383 ieee80211_notify_country(vap, ise->se_bssid, in sta_add()
384 cie->cc); in sta_add()
385 se->se_countrygen = st->st_scangen; in sta_add()
388 ise->se_cc[0] = cie->cc[0]; in sta_add()
389 ise->se_cc[1] = cie->cc[1]; in sta_add()
392 (void) ieee80211_ies_init(&ise->se_ies, sp->ies, sp->ies_len); in sta_add()
395 if (se->se_fails && (ticks - se->se_lastfail) > STA_FAILS_AGE*hz) { in sta_add()
396 se->se_fails = 0; in sta_add()
398 "%s: fails %u", __func__, se->se_fails); in sta_add()
401 se->se_lastupdate = ticks; /* update time */ in sta_add()
402 se->se_seen = 1; in sta_add()
403 se->se_notseen = 0; in sta_add()
405 KASSERT(sizeof(sp->bchan) == 1, ("bchan size")); in sta_add()
406 if (rssi > st->st_maxrssi[sp->bchan]) in sta_add()
407 st->st_maxrssi[sp->bchan] = rssi; in sta_add()
416 ss->ss_flags |= IEEE80211_SCAN_GOTPICK; in sta_add()
429 return (isclr(vap->iv_ic->ic_chan_active, c->ic_ieee) || in isexcluded()
430 (vap->iv_des_chan != IEEE80211_CHAN_ANYC && in isexcluded()
431 c->ic_freq != vap->iv_des_chan->ic_freq)); in isexcluded()
435 find11gchannel(struct ieee80211com *ic, int i, int freq) in find11gchannel() argument
445 for (j = i+1; j < ic->ic_nchans; j++) { in find11gchannel()
446 c = &ic->ic_channels[j]; in find11gchannel()
447 if (c->ic_freq == freq && IEEE80211_IS_CHAN_G(c)) in find11gchannel()
451 c = &ic->ic_channels[j]; in find11gchannel()
452 if (c->ic_freq == freq && IEEE80211_IS_CHAN_G(c)) in find11gchannel()
480 enum ieee80211_phymode mode, const uint16_t freq[], int nfreq) in add_channels() argument
482 struct ieee80211com *ic = vap->iv_ic; in add_channels()
490 if (ss->ss_last >= IEEE80211_SCAN_MAX) in add_channels()
493 c = ieee80211_find_channel(ic, freq[i], modeflags); in add_channels()
499 __func__, c->ic_freq, c->ic_flags)); in add_channels()
502 * XXX special-case 11b/g channels so we select in add_channels()
505 if ((cg = find11gchannel(ic, i, c->ic_freq)) != NULL) in add_channels()
508 ss->ss_chans[ss->ss_last++] = c; in add_channels()
523 for (; scan->list != NULL; scan++) { in checktable()
524 for (i = 0; i < scan->count; i++) in checktable()
525 if (scan->list[i] == c->ic_freq) in checktable()
537 for (i = 0; i < ss->ss_last; i++) in onscanlist()
538 if (ss->ss_chans[i] == c) in onscanlist()
547 struct ieee80211com *ic = vap->iv_ic; in sweepchannels()
551 for (i = 0; i < ic->ic_nchans; i++) { in sweepchannels()
552 if (ss->ss_last >= IEEE80211_SCAN_MAX) in sweepchannels()
555 c = &ic->ic_channels[i]; in sweepchannels()
570 if (vap->iv_des_mode != IEEE80211_MODE_AUTO && in sweepchannels()
571 vap->iv_des_mode != ieee80211_chan2mode(c)) in sweepchannels()
590 ss->ss_chans[ss->ss_last++] = c; in sweepchannels()
594 * - not already on the scan list in sweepchannels()
595 * - allowed by any desired mode constraint in sweepchannels()
596 * - there is space in the scan list in sweepchannels()
600 c = vap->iv_des_chan; in sweepchannels()
603 (vap->iv_des_mode == IEEE80211_MODE_AUTO || in sweepchannels()
604 vap->iv_des_mode == ieee80211_chan2mode(c)) && in sweepchannels()
605 ss->ss_last < IEEE80211_SCAN_MAX) in sweepchannels()
606 ss->ss_chans[ss->ss_last++] = c; in sweepchannels()
616 ss->ss_last = 0; in makescanlist()
622 for (scan = table; scan->list != NULL; scan++) { in makescanlist()
623 mode = scan->mode; in makescanlist()
625 switch (mode) { in makescanlist()
627 if (vap->iv_des_mode == IEEE80211_MODE_11B) in makescanlist()
635 * NB: 11b -> AUTO lets add_channels upgrade an in makescanlist()
638 if (vap->iv_des_mode == IEEE80211_MODE_AUTO || in makescanlist()
639 vap->iv_des_mode == IEEE80211_MODE_11G || in makescanlist()
640 vap->iv_des_mode == IEEE80211_MODE_11NG || in makescanlist()
641 vap->iv_des_mode == IEEE80211_MODE_VHT_2GHZ) { in makescanlist()
642 mode = vap->iv_des_mode; in makescanlist()
649 if (vap->iv_des_mode == IEEE80211_MODE_11NA || in makescanlist()
650 vap->iv_des_mode == IEEE80211_MODE_VHT_5GHZ) { in makescanlist()
651 mode = vap->iv_des_mode; in makescanlist()
661 if (vap->iv_des_mode != IEEE80211_MODE_AUTO && in makescanlist()
662 vap->iv_des_mode != mode) in makescanlist()
668 if ((vap->iv_flags & IEEE80211_F_XR) && in makescanlist()
678 add_channels(vap, ss, mode, scan->list, scan->count); in makescanlist()
702 static const uint16_t rcl10[] = /* Added Korean channels 2312-2372 */
744 * Start a station-mode scan by populating the channel list.
749 struct sta_table *st = ss->ss_priv; in sta_start()
753 if (ss->ss_mindwell == 0) in sta_start()
754 ss->ss_mindwell = msecs_to_ticks(20); /* 20ms */ in sta_start()
755 if (ss->ss_maxdwell == 0) in sta_start()
756 ss->ss_maxdwell = msecs_to_ticks(200); /* 200ms */ in sta_start()
758 st->st_scangen++; in sta_start()
759 st->st_newscan = 1; in sta_start()
771 struct sta_table *st = ss->ss_priv; in sta_restart()
773 st->st_newscan = 1; in sta_restart()
796 vap->iv_des_mode == IEEE80211_MODE_AUTO) { in demote11b()
797 c = ieee80211_find_channel(vap->iv_ic, chan->ic_freq, in demote11b()
798 (chan->ic_flags &~ (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_G)) | in demote11b()
810 (const struct ieee80211_ie_htcap *) se->se_ies.htcap_ie; in maxrate()
821 txparams = htcap->hc_mcsset[12]; in maxrate()
829 i = txstream * 8 - 1; in maxrate()
831 for (i = 31; i >= 0 && isclr(htcap->hc_mcsset, i); i--); in maxrate()
833 caps = le16dec(&htcap->hc_cap); in maxrate()
845 for (i = 0; i < se->se_rates[1]; i++) { in maxrate()
846 r = se->se_rates[2+i] & IEEE80211_RATE_VAL; in maxrate()
850 for (i = 0; i < se->se_xrates[1]; i++) { in maxrate()
851 r = se->se_xrates[2+i] & IEEE80211_RATE_VAL; in maxrate()
863 * Used to select the best scan candidate for association in a BSS.
873 return ((_a) & (_what)) ? 1 : -1; \ in sta_compare()
880 PREFER(a->base.se_capinfo, b->base.se_capinfo, in sta_compare()
884 weight = b->se_fails - a->se_fails; in sta_compare()
893 * more desirable (e.g. an 11b-only ap with stronger in sta_compare()
896 rssia = MIN(a->base.se_rssi, STA_RSSI_MAX); in sta_compare()
897 rssib = MIN(b->base.se_rssi, STA_RSSI_MAX); in sta_compare()
898 if (abs(rssib - rssia) < 5) { in sta_compare()
900 maxa = maxrate(&a->base); in sta_compare()
901 maxb = maxrate(&b->base); in sta_compare()
903 return maxa - maxb; in sta_compare()
904 /* XXX use freq for channel preference */ in sta_compare()
906 PREFER(IEEE80211_IS_CHAN_5GHZ(a->base.se_chan), in sta_compare()
907 IEEE80211_IS_CHAN_5GHZ(b->base.se_chan), 1); in sta_compare()
910 return a->base.se_rssi - b->base.se_rssi; in sta_compare()
928 srs = ieee80211_get_suprates(vap->iv_ic, chan); in check_rate()
929 nrs = se->se_rates[1]; in check_rate()
930 rs = se->se_rates+2; in check_rate()
932 ucastrate = vap->iv_txparms[ieee80211_chan2mode(chan)].ucastrate; in check_rate()
946 for (j = 0; j < srs->rs_nrates; j++) in check_rate()
947 if (r == IEEE80211_RV(srs->rs_rates[j])) { in check_rate()
953 if (j == srs->rs_nrates && (rs[i] & IEEE80211_RATE_BASIC)) { in check_rate()
962 if (rs == se->se_rates+2) { in check_rate()
963 /* scan xrates too; sort of an algol68-style for loop */ in check_rate()
964 nrs = se->se_xrates[1]; in check_rate()
965 rs = se->se_xrates+2; in check_rate()
1001 slotcnt = tdma->tdma_slotcnt; in tdma_isfull()
1002 for (slot = slotcnt-1; slot >= 0; slot--) in tdma_isfull()
1003 if (isclr(tdma->tdma_inuse, slot)) in tdma_isfull()
1017 struct ieee80211com *ic = vap->iv_ic; in match_bss()
1018 struct ieee80211_scan_entry *se = &se0->base; in match_bss()
1023 if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan))) in match_bss()
1032 if (vap->iv_des_mode != IEEE80211_MODE_AUTO && in match_bss()
1033 (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) != in match_bss()
1034 chanflags[vap->iv_des_mode]) in match_bss()
1036 if (vap->iv_opmode == IEEE80211_M_IBSS) { in match_bss()
1037 if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0) in match_bss()
1040 } else if (vap->iv_opmode == IEEE80211_M_AHDEMO) { in match_bss()
1046 if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS)) in match_bss()
1053 if (vap->iv_caps & IEEE80211_C_TDMA) { in match_bss()
1055 (const struct ieee80211_tdma_param *)se->se_ies.tdma_ie; in match_bss()
1056 const struct ieee80211_tdma_state *ts = vap->iv_tdma; in match_bss()
1060 else if (tdma->tdma_version != ts->tdma_version) in match_bss()
1062 else if (tdma->tdma_slot != 0) in match_bss()
1067 else if (ieee80211_local_address(se->se_macaddr)) in match_bss()
1073 } else if (vap->iv_opmode == IEEE80211_M_MBSS) { in match_bss()
1074 const struct ieee80211_mesh_state *ms = vap->iv_mesh; in match_bss()
1079 if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS)) in match_bss()
1081 else if (se->se_meshid[0] != IEEE80211_ELEMID_MESHID) in match_bss()
1083 else if (ms->ms_idlen != 0 && in match_bss()
1084 match_id(se->se_meshid, ms->ms_id, ms->ms_idlen)) in match_bss()
1088 if ((se->se_capinfo & IEEE80211_CAPINFO_ESS) == 0) in match_bss()
1099 if ((IEEE80211_IS_CHAN_11D(se->se_chan) || in match_bss()
1100 (vap->iv_flags_ext & IEEE80211_FEXT_DOTD)) && in match_bss()
1101 se->se_cc[0] != 0 && in match_bss()
1102 (ic->ic_regdomain.country == CTRY_DEFAULT || in match_bss()
1103 !isocmp(se->se_cc, ic->ic_regdomain.isocc))) in match_bss()
1106 if (vap->iv_flags & IEEE80211_F_PRIVACY) { in match_bss()
1107 if ((se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) in match_bss()
1111 if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) in match_bss()
1114 se0->se_flags &= ~STA_DEMOTE11B; in match_bss()
1115 rate = check_rate(vap, se->se_chan, se); in match_bss()
1119 * An 11b-only ap will give a rate mismatch if there is an in match_bss()
1123 if (IEEE80211_IS_CHAN_ANYG(se->se_chan)) { in match_bss()
1124 rate = check_rate(vap, demote11b(vap, se->se_chan), se); in match_bss()
1127 se0->se_flags |= STA_DEMOTE11B; in match_bss()
1132 * This is an 11b-only ap. Check the desired mode in in match_bss()
1134 * 11b-only ap's). Otherwise force any 11g channel used in match_bss()
1140 if (!(vap->iv_des_mode == IEEE80211_MODE_AUTO || in match_bss()
1141 vap->iv_des_mode == IEEE80211_MODE_11B)) in match_bss()
1144 se0->se_flags |= STA_DEMOTE11B; in match_bss()
1146 if (ss->ss_nssid != 0 && in match_bss()
1147 !match_ssid(se->se_ssid, ss->ss_nssid, ss->ss_ssid)) in match_bss()
1149 if ((vap->iv_flags & IEEE80211_F_DESBSSID) && in match_bss()
1150 !IEEE80211_ADDR_EQ(vap->iv_des_bssid, se->se_bssid)) in match_bss()
1152 if (se0->se_fails >= STA_FAILS_MAX) in match_bss()
1154 if (se0->se_notseen >= STA_PURGE_SCANS) in match_bss()
1156 if (se->se_rssi < STA_RSSI_MIN) in match_bss()
1172 fail ? '-' : '+', ether_sprintf(se->se_macaddr)); in match_bss()
1173 printf(" %s%c", ether_sprintf(se->se_bssid), in match_bss()
1175 printf(" %3d%c", ieee80211_chan2ieee(ic, se->se_chan), in match_bss()
1177 printf(" %+4d%c", se->se_rssi, fail & MATCH_RSSI ? '!' : ' '); in match_bss()
1181 (se->se_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : in match_bss()
1182 (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "", in match_bss()
1185 (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) ? in match_bss()
1188 ieee80211_print_essid(se->se_ssid+2, se->se_ssid[1]); in match_bss()
1201 TAILQ_FOREACH(se, &st->st_entry, se_list) { in sta_update_notseen()
1209 if (se->se_seen) in sta_update_notseen()
1210 se->se_seen = 0; in sta_update_notseen()
1212 se->se_notseen++; in sta_update_notseen()
1223 TAILQ_FOREACH(se, &st->st_entry, se_list) in sta_dec_fails()
1224 if (se->se_fails) in sta_dec_fails()
1225 se->se_fails--; in sta_dec_fails()
1232 struct sta_table *st = ss->ss_priv; in select_bss()
1238 TAILQ_FOREACH(se, &st->st_entry, se_list) { in select_bss()
1239 ieee80211_ies_expand(&se->base.se_ies); in select_bss()
1259 struct sta_table *st = ss->ss_priv; in sta_pick_bss()
1263 KASSERT(vap->iv_opmode == IEEE80211_M_STA, in sta_pick_bss()
1264 ("wrong mode %u", vap->iv_opmode)); in sta_pick_bss()
1266 if (st->st_newscan) { in sta_pick_bss()
1268 st->st_newscan = 0; in sta_pick_bss()
1270 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) { in sta_pick_bss()
1272 * Manual/background scan, don't select+join the in sta_pick_bss()
1276 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; in sta_pick_bss()
1286 if (TAILQ_FIRST(&st->st_entry) == NULL) { in sta_pick_bss()
1290 !! (ss->ss_flags & IEEE80211_SCAN_NOJOIN)); in sta_pick_bss()
1291 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN) in sta_pick_bss()
1302 st->st_newscan = 1; in sta_pick_bss()
1306 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN) in sta_pick_bss()
1310 chan = selbs->base.se_chan; in sta_pick_bss()
1311 if (selbs->se_flags & STA_DEMOTE11B) in sta_pick_bss()
1313 if (!ieee80211_sta_join(vap, chan, &selbs->base)) in sta_pick_bss()
1333 LIST_FOREACH(se, &st->st_hash[hash], se_hash) in sta_lookup()
1334 if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr)) in sta_lookup()
1344 struct ieee80211com *ic = vap->iv_ic; in sta_roam_check()
1345 struct ieee80211_node *ni = vap->iv_bss; in sta_roam_check()
1346 struct sta_table *st = ss->ss_priv; in sta_roam_check()
1352 se = sta_lookup(st, ni->ni_macaddr); in sta_roam_check()
1358 mode = ieee80211_chan2mode(ic->ic_bsschan); in sta_roam_check()
1359 roamRate = vap->iv_roamparms[mode].rate; in sta_roam_check()
1360 roamRssi = vap->iv_roamparms[mode].rssi; in sta_roam_check()
1364 ucastRate = vap->iv_txparms[mode].ucastrate; in sta_roam_check()
1366 curRssi = ic->ic_node_getrssi(ni); in sta_roam_check()
1368 curRate = ni->ni_txrate; in sta_roam_check()
1378 * Check if a new ap should be used and switch. in sta_roam_check()
1382 if (ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_scanvalid)) { in sta_roam_check()
1389 * XXX force immediate switch on scan complete in sta_roam_check()
1391 if (!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) && in sta_roam_check()
1392 ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) || in sta_roam_check()
1393 ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))) in sta_roam_check()
1397 se->base.se_rssi = curRssi; in sta_roam_check()
1408 chan = selbs->base.se_chan; in sta_roam_check()
1409 if (selbs->se_flags & STA_DEMOTE11B) in sta_roam_check()
1411 (void) ieee80211_sta_join(vap, chan, &selbs->base); in sta_roam_check()
1423 struct ieee80211vap *vap = ss->ss_vap; in sta_age()
1435 KASSERT(vap->iv_opmode == IEEE80211_M_STA, in sta_age()
1436 ("wrong mode %u", vap->iv_opmode)); in sta_age()
1437 if (vap->iv_roaming == IEEE80211_ROAMING_AUTO && in sta_age()
1438 (vap->iv_flags & IEEE80211_F_BGSCAN) && in sta_age()
1439 vap->iv_state >= IEEE80211_S_RUN) in sta_age()
1452 struct sta_table *st = ss->ss_priv; in sta_iterate()
1457 gen = st->st_scaniter++; in sta_iterate()
1460 TAILQ_FOREACH(se, &st->st_entry, se_list) { in sta_iterate()
1461 if (se->se_scangen != gen) { in sta_iterate()
1462 se->se_scangen = gen; in sta_iterate()
1464 se->base.se_age = ticks - se->se_lastupdate; in sta_iterate()
1466 (*f)(arg, &se->base); in sta_iterate()
1479 struct sta_table *st = ss->ss_priv; in sta_assoc_fail()
1484 se->se_fails++; in sta_assoc_fail()
1485 se->se_lastfail = ticks; in sta_assoc_fail()
1486 IEEE80211_NOTE_MAC(ss->ss_vap, IEEE80211_MSG_SCAN, in sta_assoc_fail()
1488 __func__, reason, se->se_fails); in sta_assoc_fail()
1496 struct sta_table *st = ss->ss_priv; in sta_assoc_success()
1502 se->se_fails = 0; in sta_assoc_success()
1503 IEEE80211_NOTE_MAC(ss->ss_vap, IEEE80211_MSG_SCAN, in sta_assoc_success()
1505 __func__, se->se_fails); in sta_assoc_success()
1507 se->se_lastassoc = ticks; in sta_assoc_success()
1529 * Adhoc mode-specific support.
1551 * Start an adhoc-mode scan by populating the channel list.
1556 struct sta_table *st = ss->ss_priv; in adhoc_start()
1560 if (ss->ss_mindwell == 0) in adhoc_start()
1561 ss->ss_mindwell = msecs_to_ticks(200); /* 200ms */ in adhoc_start()
1562 if (ss->ss_maxdwell == 0) in adhoc_start()
1563 ss->ss_maxdwell = msecs_to_ticks(200); /* 200ms */ in adhoc_start()
1565 st->st_scangen++; in adhoc_start()
1566 st->st_newscan = 1; in adhoc_start()
1572 * Select a channel to start an adhoc network on.
1574 * channels so select one that looks least occupied.
1579 struct sta_table *st = ss->ss_priv; in adhoc_pick_channel()
1585 bestrssi = -1; in adhoc_pick_channel()
1588 for (i = 0; i < ss->ss_last; i++) { in adhoc_pick_channel()
1589 c = ss->ss_chans[i]; in adhoc_pick_channel()
1597 if (flags != 0 && (c->ic_flags & flags) != flags) in adhoc_pick_channel()
1600 TAILQ_FOREACH(se, &st->st_entry, se_list) { in adhoc_pick_channel()
1601 if (se->base.se_chan != c) in adhoc_pick_channel()
1603 if (se->base.se_rssi > maxrssi) in adhoc_pick_channel()
1604 maxrssi = se->base.se_rssi; in adhoc_pick_channel()
1621 struct sta_table *st = ss->ss_priv;
1624 struct ieee80211com *ic = vap->iv_ic;
1626 KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
1627 vap->iv_opmode == IEEE80211_M_AHDEMO ||
1628 vap->iv_opmode == IEEE80211_M_MBSS,
1629 ("wrong opmode %u", vap->iv_opmode));
1631 if (st->st_newscan) {
1633 st->st_newscan = 0;
1635 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
1637 * Manual/background scan, don't select+join the
1641 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
1649 if (TAILQ_FIRST(&st->st_entry) == NULL) {
1652 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1655 /* NB: never auto-start a tdma network for slot !0 */
1657 if (vap->iv_des_nssid &&
1658 ((vap->iv_caps & IEEE80211_C_TDMA) == 0 ||
1661 if (vap->iv_des_nssid) {
1666 * specified, try to select a channel.
1668 if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
1669 IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
1672 chan = vap->iv_des_chan;
1675 * Create a HT capable IBSS; the per-node
1681 chan, vap->iv_flags_ht);
1683 chan, vap->iv_vht_flags);
1696 st->st_newscan = 1;
1700 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1704 chan = selbs->base.se_chan;
1705 if (selbs->se_flags & STA_DEMOTE11B)
1709 * The intent is to enable HT20/HT40 when joining a non-HT
1714 chan, vap->iv_flags_ht);
1716 chan, vap->iv_vht_flags);
1717 if (!ieee80211_sta_join(vap, chan, &selbs->base))
1728 struct sta_table *st = ss->ss_priv;
1732 TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) {
1733 if (se->se_notseen > STA_PURGE_SCANS) {
1734 TAILQ_REMOVE(&st->st_entry, se, se_list);
1736 ieee80211_ies_cleanup(&se->base.se_ies);
1765 struct sta_table *st = ss->ss_priv;
1769 if (ss->ss_mindwell == 0)
1770 ss->ss_mindwell = msecs_to_ticks(200); /* 200ms */
1771 if (ss->ss_maxdwell == 0)
1772 ss->ss_maxdwell = msecs_to_ticks(200); /* 200ms */
1774 st->st_scangen++;
1775 st->st_newscan = 1;
1795 struct sta_table *st = ss->ss_priv;
1799 /* XXX select channel more intelligently, e.g. channel spread, power */
1801 for (i = 0; i < ss->ss_last; i++) {
1802 struct ieee80211_channel *chan = ss->ss_chans[i];
1814 if (flags != 0 && (chan->ic_flags & flags) != flags)
1816 KASSERT(sizeof(chan->ic_ieee) == 1, ("ic_chan size"));
1818 if (st->st_maxrssi[chan->ic_ieee] == 0) {
1823 st->st_maxrssi[chan->ic_ieee] < st->st_maxrssi[bestchan->ic_ieee])
1835 struct ieee80211com *ic = vap->iv_ic;
1838 KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP,
1839 ("wrong opmode %u", vap->iv_opmode));
1852 bestchan = ieee80211_find_channel(ic, bestchan->ic_freq,
1853 bestchan->ic_flags & ~IEEE80211_CHAN_TURBO);
1859 if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) {
1861 * Manual/background scan, don't select+join the
1865 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
1868 chan = ieee80211_ht_adjust_channel(ic, bestchan, vap->iv_flags_ht);
1869 chan = ieee80211_vht_adjust_channel(ic, chan, vap->iv_vht_flags);
1901 struct sta_table *st = ss->ss_priv;
1902 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1906 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS,
1907 ("wrong opmode %u", vap->iv_opmode));
1909 if (st->st_newscan) {
1911 st->st_newscan = 0;
1913 if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
1915 * Manual/background scan, don't select+join the
1919 ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
1927 if (TAILQ_FIRST(&st->st_entry) == NULL) {
1930 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1933 if (ms->ms_idlen != 0) {
1937 * specified, try to select a channel.
1939 if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
1940 IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
1941 struct ieee80211com *ic = vap->iv_ic;
1947 chan, vap->iv_flags_ht);
1949 chan, vap->iv_vht_flags);
1952 chan = vap->iv_des_chan;
1966 st->st_newscan = 1;
1970 if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
1974 chan = selbs->base.se_chan;
1975 if (selbs->se_flags & STA_DEMOTE11B)
1977 if (!ieee80211_sta_join(vap, chan, &selbs->base))