On Sun, Apr 29, 2018 at 11:51:26AM +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.
>
> Paul, do you think this is approach fits into the larger context
> of your plans for RSSI? Or would it disturb you?
A first read suggest this is a good step in the direction I was planing
to go. I will look deeper into this the following days and come back
with a reply to this and the other emails from you here.
>
> 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 29 Apr 2018 09:08:05 -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 *, uint8_t);
> 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->ni_rssi) > 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->ni_rssi) > 0))
> selbs5 = ni;
> - } else if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi)
> + } else if (selbs == NULL ||
> + ic->ic_node_cmprssi(ic, ni, selbs->ni_rssi) > 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->ni_rssi) >= 0)
> + selbs = selbs5;
> + else
> + selbs = selbs2;
> + } else if (selbs2)
> selbs = selbs2;
> else if (selbs5)
> selbs = selbs5;
> @@ -991,6 +1000,31 @@ ieee80211_node_checkrssi(struct ieee8021
> return (ni->ni_rssi >= (u_int8_t)thres);
> }
>
> +/*
> + * Determine if an RSSI value is significantly different from the
> + * RSSI stored in a node structure. This function assumes RSSI values
> + * are represented either 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 *ni, uint8_t rssi)
> +{
> + uint8_t thres;
> +
> + if (ic->ic_max_rssi)
> + thres = IEEE80211_RSSI_CMP_THRES_RATIO;
> + else
> + thres = IEEE80211_RSSI_CMP_THRES;
> +
> + if (ni->ni_rssi + thres < rssi)
> + return -1;
> + if (ni->ni_rssi - thres > rssi)
> + return 1;
> + return 0;
> +}
> +
> void
> ieee80211_setup_node(struct ieee80211com *ic,
> struct ieee80211_node *ni, const u_int8_t *macaddr)
> @@ -1259,7 +1293,8 @@ ieee80211_find_node_for_beacon(struct ie
> if ((ni = ieee80211_find_node(ic, macaddr)) != NULL) {
> s = splnet();
>
> - if (ni->ni_chan != chan && ni->ni_rssi >= rssi)
> + if (ni->ni_chan != chan &&
> + ic->ic_node_cmprssi(ic, ni, rssi) >= 0)
> score++;
> if (ssid[1] == 0 && ni->ni_esslen != 0)
> score++;
> 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 29 Apr 2018 08:54:20 -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 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 {
> @@ -270,6 +273,8 @@ 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 *, uint8_t);
> u_int8_t ic_max_rssi;
> struct ieee80211_tree ic_tree;
> int ic_nnodes; /* length of ic_nnodes */