I've ran into what seems to be a fairly modern dual-band AP (issued by a French ISP). This AP camps on channel 112. This channel requires radar detection which may explain the behaviour described below.
The AP sends 5GHz beacons with a ridicously low RSSI while no client is connected, and OpenBSD prefers the 2GHz band... + b8:ee:0e:cb:b3:08 1 +58 54M ess privacy rsn "ESSID" + b8:ee:0e:cb:b3:09 112 +6 54M ess privacy rsn "ESSID" ... unless we get lucky and the most recently measured RSSI is obtained from a probe response instead of a beacon: + b8:ee:0e:cb:b3:08 1 +58 54M ess privacy rsn "ESSID" + b8:ee:0e:cb:b3:09 112 +61 54M ess privacy rsn "ESSID" tcpdump confirms that beacons are received with a low RSSI of -10dBm as long as no other client is connected (nevermind that the positive dBm values shown here are bogus; that is a separate issue): 10:18:59.773885 802.11 flags=0<>: beacon, timestamp 974393344059, interval 100, caps=2421<ESS,PRIVACY,SPECTRUM_MGMT,SHORT_SLOTTIME>, ssid (ESSID), rates 6M* 9M 12M* 18M 24M* 36M 48M 54M, ds (chan 112), tim 0x00030000, country 'FR ', channel 36 limit 23dB, channel 40 limit 23dB, channel 44 limit 23dB, channel 48 limit 23dB, channel 52 limit 23dB, channel 56 limit 23dB, channel 60 limit 23dB, channel 64 limit 23dB, channel 100 limit 23dB, channel 104 limit 23dB, channel 108 limit 23dB, channel 112 limit 23dB, channel 116 limit 23dB, channel 132 limit 23dB, channel 136 limit 23dB, channel 140 limit 23dB, power constraint 0dB, <radiotap v0, tsf 13340545, 6Mbit/s, chan 144, 11a, sig 10dBm, noise -127dBm> Whereas probe responses consistently arrive with much more promising RSSI values of about -60dBm: 10:18:58.889338 802.11 flags=8<RETRY>: probe response, timestamp 974392459305, interval 100, caps=2421<ESS,PRIVACY,SPECTRUM_MGMT,SHORT_SLOTTIME>, ssid (ESSID), rates 6M* 9M 12M* 18M 24M* 36M 48M 54M, ds (chan 112), country 'FR ', channel 36 limit 23dB, channel 40 limit 23dB, channel 44 limit 23dB, channel 48 limit 23dB, channel 52 limit 23dB, channel 56 limit 23dB, channel 60 limit 23dB, channel 64 limit 23dB, channel 100 limit 23dB, channel 104 limit 23dB, channel 108 limit 23dB, channel 112 limit 23dB, channel 116 limit 23dB, channel 132 limit 23dB, channel 136 limit 23dB, channel 140 limit 23dB, power constraint 0dB, <radiotap v0, tsf 12455791, 6Mbit/s, chan 112, 11a, sig 60dBm, noise -127dBm> I have no idea if and where the 802.11 standard describes this behaviour. Maybe there is a way to tell the real RSSI even from beacon frames? Does anyone know more about this? Setting aside concerns about my lack of understanding of the underlying reason for this behaviour, the hack below is sufficient to make this AP show up as a strong contender in the candidate list and be preferred over 2GHz as it should be. Should I commit this hack? I don't see any downsides. Index: ieee80211_input.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v retrieving revision 1.200 diff -u -p -r1.200 ieee80211_input.c --- ieee80211_input.c 29 Apr 2018 12:11:48 -0000 1.200 +++ ieee80211_input.c 30 Apr 2018 08:32:58 -0000 @@ -1689,13 +1689,26 @@ ieee80211_recv_probe_resp(struct ieee802 memcpy(ni->ni_essid, &ssid[2], ssid[1]); } IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); - ni->ni_rssi = rxi->rxi_rssi; + /* XXX validate channel # */ + ni->ni_chan = &ic->ic_channels[chan]; + if (ic->ic_state == IEEE80211_S_SCAN && + IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) { + /* + * During a scan on 5Ghz, prefer RSSI measured for probe + * response frames. i.e. don't allow beacons to lower the + * measured RSSI. Some 5GHz APs send beacons with much + * less Tx power than they use for probe responses. + */ + if (isprobe) + ni->ni_rssi = rxi->rxi_rssi; + else if (ni->ni_rssi < rxi->rxi_rssi) + ni->ni_rssi = rxi->rxi_rssi; + } else + ni->ni_rssi = rxi->rxi_rssi; ni->ni_rstamp = rxi->rxi_tstamp; memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp)); ni->ni_intval = bintval; ni->ni_capinfo = capinfo; - /* XXX validate channel # */ - ni->ni_chan = &ic->ic_channels[chan]; ni->ni_erp = erp; /* NB: must be after ni_chan is setup */ ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);