On 2018 May 01 (Tue) at 11:20:54 +0200 (+0200), Stefan Sperling wrote:
:On Mon, Apr 30, 2018 at 08:57:23AM +0200, Peter Hessler wrote:
:> On 2018 Apr 29 (Sun) at 11:51:26 +0200 (+0200), Stefan Sperling wrote:
:> :This diff tries to avoid situations where background scans play
:> :ping-pong between different APs with nearly equal RSSI, as
:> :observed by phessler.
:> :
:> :Not all drivers represent RSSI values in dBm or percentage, so the
:> :diff includes the possibility for drivers to override the new RSSI
:> :comparison function. However, since the threshold is rather low
:> :applying this to all drivers for now should not do any harm, unless
:> :there is a driver where the RSSI value range is ridiculously small.
:> :I'm not aware of any such driver at present.
:> :
:>
:> I'm concerned about two things.
:>
:> The usage is confusing, because you pass two incompatible things to be
:> compared. I would prefer ieee80211_node_cmprssi(ic, rssi_one, rssi_two).
:
:Agreed. Updated diff below. I've chosen to make it compare two nodes
:since the function lives in the nodes namespace. It makes the function
:a bit less flexible as it cannot be used to compare naked rssi values.
:But that's not really needed for the problem at hand; after all, we
:want to compare APs.
:
:> Also, in the case where ni->ni_rssi has a very weak signal, the second
:> comparison can underflow.
:
:Indeed. Thanks for catching this!
:
OK
:Index: ieee80211_node.c
:===================================================================
:RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
:retrieving revision 1.129
:diff -u -p -r1.129 ieee80211_node.c
:--- ieee80211_node.c 28 Apr 2018 14:49:07 -0000 1.129
:+++ ieee80211_node.c 30 Apr 2018 07:30:43 -0000
:@@ -67,6 +67,8 @@ u_int8_t ieee80211_node_getrssi(struct i
: const struct ieee80211_node *);
: int ieee80211_node_checkrssi(struct ieee80211com *,
: const struct ieee80211_node *);
:+int ieee80211_node_cmprssi(struct ieee80211com *,
:+ const struct ieee80211_node *, const struct ieee80211_node *);
: void ieee80211_setup_node(struct ieee80211com *, struct ieee80211_node *,
: const u_int8_t *);
: void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *);
:@@ -133,6 +135,7 @@ ieee80211_node_attach(struct ifnet *ifp)
: ic->ic_node_copy = ieee80211_node_copy;
: ic->ic_node_getrssi = ieee80211_node_getrssi;
: ic->ic_node_checkrssi = ieee80211_node_checkrssi;
:+ ic->ic_node_cmprssi = ieee80211_node_cmprssi;
: ic->ic_scangen = 1;
: ic->ic_max_nnodes = ieee80211_cache_size;
:
:@@ -761,12 +764,15 @@ ieee80211_end_scan(struct ifnet *ifp)
:
: if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {
: if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) &&
:- (selbs2 == NULL || ni->ni_rssi > selbs2->ni_rssi))
:+ (selbs2 == NULL ||
:+ ic->ic_node_cmprssi(ic, ni, selbs2) > 0))
: selbs2 = ni;
: else if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) &&
:- (selbs5 == NULL || ni->ni_rssi > selbs5->ni_rssi))
:+ (selbs5 == NULL ||
:+ ic->ic_node_cmprssi(ic, ni, selbs5) > 0))
: selbs5 = ni;
:- } else if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)
:+ } else if (selbs == NULL ||
:+ ic->ic_node_cmprssi(ic, ni, selbs) > 0)
: selbs = ni;
: }
:
:@@ -782,9 +788,12 @@ ieee80211_end_scan(struct ifnet *ifp)
: */
: if (selbs5 && selbs5->ni_rssi > min_5ghz_rssi)
: selbs = selbs5;
:- else if (selbs5 && selbs2)
:- selbs = (selbs5->ni_rssi >= selbs2->ni_rssi ? selbs5 : selbs2);
:- else if (selbs2)
:+ else if (selbs5 && selbs2) {
:+ if (ic->ic_node_cmprssi(ic, selbs5, selbs2) >= 0)
:+ selbs = selbs5;
:+ else
:+ selbs = selbs2;
:+ } else if (selbs2)
: selbs = selbs2;
: else if (selbs5)
: selbs = selbs5;
:@@ -989,6 +998,38 @@ ieee80211_node_checkrssi(struct ieee8021
: IEEE80211_RSSI_THRES_2GHZ :
: IEEE80211_RSSI_THRES_5GHZ;
: return (ni->ni_rssi >= (u_int8_t)thres);
:+}
:+
:+/*
:+ * Determine if RSSI values of two nodes are significantly different.
:+ * This function assumes RSSI values are represented either in dBm or
:+ * as a percentage of ic_max_rssi. Drivers should override this function
:+ * in case their RSSI values use a different representation.
:+ */
:+int
:+ieee80211_node_cmprssi(struct ieee80211com *ic,
:+ const struct ieee80211_node *ni1, const struct ieee80211_node *ni2)
:+{
:+ uint8_t thres;
:+
:+ if (ic->ic_max_rssi)
:+ thres = IEEE80211_RSSI_CMP_THRES_RATIO;
:+ else
:+ thres = IEEE80211_RSSI_CMP_THRES_DBM;
:+
:+ /* cap threshold to prevent overflow in calculations below */
:+ while (thres > 0) {
:+ if (ni1->ni_rssi + thres >= ni1->ni_rssi &&
:+ ni1->ni_rssi - thres <= ni1->ni_rssi)
:+ break;
:+ thres--;
:+ }
:+
:+ if (ni1->ni_rssi + thres < ni2->ni_rssi)
:+ return -1;
:+ if (ni1->ni_rssi - thres > ni2->ni_rssi)
:+ return 1;
:+ return 0;
: }
:
: void
:Index: ieee80211_var.h
:===================================================================
:RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
:retrieving revision 1.85
:diff -u -p -r1.85 ieee80211_var.h
:--- ieee80211_var.h 26 Apr 2018 12:50:07 -0000 1.85
:+++ ieee80211_var.h 30 Apr 2018 07:30:56 -0000
:@@ -62,6 +62,9 @@
: #define IEEE80211_RSSI_THRES_RATIO_2GHZ 60 /* in percent */
: #define IEEE80211_RSSI_THRES_RATIO_5GHZ 50 /* in percent */
:
:+#define IEEE80211_RSSI_CMP_THRES_DBM 8 /* in dBm */
:+#define IEEE80211_RSSI_CMP_THRES_RATIO 5 /* in percent */
:+
: #define IEEE80211_BGSCAN_FAIL_MAX 360 /* units of 500 msec */
:
: enum ieee80211_phytype {
:@@ -269,6 +272,9 @@ struct ieee80211com {
: u_int8_t (*ic_node_getrssi)(struct ieee80211com *,
: const struct ieee80211_node *);
: int (*ic_node_checkrssi)(struct ieee80211com *,
:+ const struct ieee80211_node *);
:+ int (*ic_node_cmprssi)(struct ieee80211com *,
:+ const struct ieee80211_node *,
: const struct ieee80211_node *);
: u_int8_t ic_max_rssi;
: struct ieee80211_tree ic_tree;
:
--
Never let your sense of morals prevent you from doing what is right.
-- Salvor Hardin, "Foundation"