An AP which never responds to auth/assoc requests can remain in the joinlist and keep being selected. This results in an endless loop between SCAN and AUTH (and sometimes ASSOC) states:
iwm0: SCAN -> AUTH iwm0: sending auth to 00:1a:dd:da:e3:f1 on channel 64 mode 11a iwm0: AUTH -> SCAN Another AP added to the joinlist may never be selected if it has a lower score than this "bad" AP in the list (e.g. if the "bad" AP is using WPA and the alternative AP which was added uses no encryption). In this example, the AP which does not respond has the SSID "OpenBSD", and I added the unencrypted "univbuc_free" network to the joinlist during SCAN: iwm0: end passive scan iwm0: AP 10:bd:18:3d:c1:11 "univbuc_free" score 43 iwm0: AP 10:bd:18:3d:c1:1e "univbuc_free" score 43 iwm0: AP 10:bd:18:4d:9f:f1 "univbuc_free" score 43 iwm0: AP 10:bd:18:4d:9f:fe "univbuc_free" score 43 iwm0: AP f4:ea:67:5c:f9:61 "univbuc_free" score 43 iwm0: AP f4:ea:67:5c:f9:6e "univbuc_free" score 45 iwm0: AP f4:ea:67:5d:01:51 "univbuc_free" score 43 iwm0: AP f4:ea:67:5d:01:5e "univbuc_free" score 43 iwm0: AP f4:ea:67:bf:aa:11 "univbuc_free" score 43 iwm0: AP f4:ea:67:c0:f8:71 "univbuc_free" score 43 iwm0: AP f4:ea:67:c0:f8:7e "univbuc_free" score 43 iwm0: best AP 00:1a:dd:da:e3:e1 "OpenBSD" score 52 iwm0: switching to network "OpenBSD" With this diff we deselect an AP which fails to auth/assoc, and give higher priority to APs which have had no auth/assoc failures yet. This looks like: iwm0: end active scan iwm0: AP 10:bd:18:3c:d4:81 "univbuc_free" score 54 iwm0: AP 10:bd:18:3c:d4:8e "univbuc_free" score 54 iwm0: AP 10:bd:18:4d:98:81 "univbuc_free" score 54 iwm0: AP 10:bd:18:4d:98:8e "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:9f:7e "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:9f:fe "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:cf:41 "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:cf:4e "univbuc_free" score 53 iwm0: AP 10:bd:18:6c:aa:51 "univbuc_free" score 53 iwm0: AP 10:bd:18:6c:aa:5e "univbuc_free" score 53 iwm0: AP f4:ea:67:5c:f9:61 "univbuc_free" score 33 iwm0: AP f4:ea:67:5c:f9:6e "univbuc_free" score 53 iwm0: AP f4:ea:67:5d:01:51 "univbuc_free" score 53 iwm0: AP f4:ea:67:5d:01:5e "univbuc_free" score 53 iwm0: AP f4:ea:67:c0:f8:71 "univbuc_free" score 54 iwm0: AP f4:ea:67:c0:f8:7e "univbuc_free" score 54 iwm0: best AP 00:1a:dd:da:e3:f1 "OpenBSD" score 73 iwm0: switching to network "OpenBSD" (long scan result list omitted) iwm0: SCAN -> AUTH iwm0: sending auth to 00:1a:dd:da:e3:f1 on channel 64 mode 11a iwm0: authentication timed out for 00:1a:dd:da:e3:f1 iwm0: AUTH -> SCAN iwm0: end active scan iwm0: AP 00:1a:dd:da:e3:f1 "OpenBSD" score 52 iwm0: AP 10:bd:18:4d:9f:71 "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:9f:7e "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:9f:f1 "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:9f:fe "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:cf:41 "univbuc_free" score 53 iwm0: AP 10:bd:18:4d:cf:4e "univbuc_free" score 53 iwm0: AP 10:bd:18:6c:aa:51 "univbuc_free" score 53 iwm0: AP 18:33:9d:6d:9c:61 "univbuc_free" score 53 iwm0: AP 18:33:9d:6d:9c:6e "univbuc_free" score 53 iwm0: AP f4:ea:67:5c:f9:61 "univbuc_free" score 33 iwm0: AP f4:ea:67:5d:01:5e "univbuc_free" score 53 iwm0: AP f4:ea:67:be:74:21 "univbuc_free" score 53 iwm0: AP f4:ea:67:bf:aa:11 "univbuc_free" score 53 iwm0: AP f4:ea:67:c0:f8:71 "univbuc_free" score 53 iwm0: AP f4:ea:67:c0:f8:7e "univbuc_free" score 53 iwm0: best AP f4:ea:67:5d:01:51 "univbuc_free" score 53 iwm0: switching to network "univbuc_free" ok? diff refs/heads/master refs/heads/join-deselect blob - bf2b2858f03d302ded03555bda21450f9c80cf66 blob + d66ca6238ff5d4c8a642805ef45843088bae4289 --- sys/net80211/ieee80211.c +++ sys/net80211/ieee80211.c @@ -772,8 +772,25 @@ ieee80211_watchdog(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; - if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) + if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) { + if (ic->ic_opmode == IEEE80211_M_STA && + (ic->ic_state == IEEE80211_S_AUTH || + ic->ic_state == IEEE80211_S_ASSOC)) { + struct ieee80211_node *ni; + if (ifp->if_flags & IFF_DEBUG) + printf("%s: %s timed out for %s\n", + ifp->if_xname, + ic->ic_state == IEEE80211_S_ASSOC ? + "association" : "authentication", + ether_sprintf(ic->ic_bss->ni_macaddr)); + ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr); + if (ni) + ni->ni_fails++; + if (ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN)) + ieee80211_deselect_ess(ic); + } ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + } if (ic->ic_mgt_timer != 0) ifp->if_timer = 1; blob - 41530d2a311e1dbc2c0e70f95a14c360e9f981d6 (mode 644) blob + 78a907b8c5c2e146b4f904fdc2f352430fdf8757 (mode 600) --- sys/net80211/ieee80211_node.c +++ sys/net80211/ieee80211_node.c @@ -476,6 +476,10 @@ ieee80211_ess_calculate_score(struct ieee80211com *ic, ni->ni_rssi > min_5ghz_rssi) score += 2; + /* Boost this AP if it had no auth/assoc failures in the past. */ + if (ni->ni_fails == 0) + score += 21; + return score; } @@ -669,6 +673,15 @@ ieee80211_set_ess(struct ieee80211com *ic, struct ieee ic->ic_def_txkey = ess->def_txkey; ic->ic_flags |= IEEE80211_F_WEPON; } +} + +void +ieee80211_deselect_ess(struct ieee80211com *ic) +{ + memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); + ic->ic_des_esslen = 0; + ieee80211_disable_wep(ic); + ieee80211_disable_rsn(ic); } void blob - d5560e75f48cd00aa424f22bdb0237e447405420 blob + f1e728c0e72d599aed4165b8d68e412ba3d9413f --- sys/net80211/ieee80211_var.h +++ sys/net80211/ieee80211_var.h @@ -472,6 +472,7 @@ int ieee80211_add_ess(struct ieee80211com *, struct ie void ieee80211_del_ess(struct ieee80211com *, char *, int, int); void ieee80211_set_ess(struct ieee80211com *, struct ieee80211_ess *, struct ieee80211_node *); +void ieee80211_deselect_ess(struct ieee80211com *); struct ieee80211_ess *ieee80211_get_ess(struct ieee80211com *, const char *, int); extern int ieee80211_cache_size;