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);

Reply via email to