1 Add an optional background scanning threshold triggered by low rssi
2 (useful for passing updated scan results to the supplicant ahead of
3 time, before losing connectivity entirely)
5 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
7 --- a/net80211/ieee80211_ioctl.h
8 +++ b/net80211/ieee80211_ioctl.h
10 IEEE80211_PARAM_MINRATE = 76, /* Maximum rate (by table index) */
11 IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
12 IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
13 + IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
16 #define SIOCG80211STATS (SIOCDEVPRIVATE+2)
17 --- a/net80211/ieee80211_var.h
18 +++ b/net80211/ieee80211_var.h
20 #define IEEE80211_BGSCAN_IDLE_MIN 100 /* min idle time (ms) */
21 #define IEEE80211_BGSCAN_IDLE_DEFAULT 250 /* default idle time (ms) */
23 +#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
25 #define IEEE80211_COVERAGE_CLASS_MAX 31 /* max coverage class */
26 #define IEEE80211_REGCLASSIDS_MAX 10 /* max regclass id list */
29 u_int8_t iv_nickname[IEEE80211_NWID_LEN];
30 u_int iv_bgscanidle; /* bg scan idle threshold */
31 u_int iv_bgscanintvl; /* bg scan min interval */
32 + u_int iv_bgscanthr; /* bg scan rssi threshold */
33 + u_int iv_bgscantrintvl; /* bg scan trigger interval */
34 + unsigned long iv_bgscanthr_next; /* last trigger for bgscan */
35 u_int iv_scanvalid; /* scan cache valid threshold */
36 struct ieee80211_roam iv_roam; /* sta-mode roaming state */
39 #define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: use software beacon timer */
40 #define IEEE80211_FEXT_DROPUNENC_EAPOL 0x00000800 /* CONF: drop unencrypted eapol frames */
41 #define IEEE80211_FEXT_APPIE_UPDATE 0x00001000 /* STATE: beacon APP IE updated */
42 +#define IEEE80211_FEXT_BGSCAN_THR 0x00002000 /* bgscan due to low rssi */
44 #define IEEE80211_COM_UAPSD_ENABLE(_ic) ((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD)
45 #define IEEE80211_COM_UAPSD_DISABLE(_ic) ((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD)
46 --- a/net80211/ieee80211_wireless.c
47 +++ b/net80211/ieee80211_wireless.c
52 + case IEEE80211_PARAM_BGSCAN_THRESH:
53 + vap->iv_bgscanthr = value;
55 case IEEE80211_PARAM_MCAST_RATE:
56 /* units are in KILObits per second */
57 if (value >= 256 && value <= 54000)
59 case IEEE80211_PARAM_BGSCAN_INTERVAL:
60 param[0] = vap->iv_bgscanintvl / HZ; /* seconds */
62 + case IEEE80211_PARAM_BGSCAN_THRESH:
63 + param[0] = vap->iv_bgscanthr; /* rssi */
65 case IEEE80211_PARAM_MCAST_RATE:
66 param[0] = vap->iv_mcast_rate; /* seconds */
68 @@ -5666,6 +5672,10 @@
69 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanintvl" },
70 { IEEE80211_PARAM_BGSCAN_INTERVAL,
71 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanintvl" },
72 + { IEEE80211_PARAM_BGSCAN_THRESH,
73 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bgscanthr" },
74 + { IEEE80211_PARAM_BGSCAN_THRESH,
75 + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_bgscanthr" },
76 { IEEE80211_PARAM_MCAST_RATE,
77 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcast_rate" },
78 { IEEE80211_PARAM_MCAST_RATE,
79 --- a/net80211/ieee80211_input.c
80 +++ b/net80211/ieee80211_input.c
81 @@ -3013,8 +3013,10 @@
83 struct ieee80211com *ic = vap->iv_ic;
85 + vap->iv_bgscantrintvl = (vap->iv_bgscantrintvl + 1) % 4;
86 return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
87 - time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle));
88 + (((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && !vap->iv_bgscantrintvl) ||
89 + time_after(jiffies, ic->ic_lastdata + vap->iv_bgscanidle)));
93 @@ -3258,6 +3260,23 @@
94 /* record tsf of last beacon */
95 memcpy(ni->ni_tstamp.data, scan.tstamp,
96 sizeof(ni->ni_tstamp));
98 + /* When rssi is low, start doing bgscans more frequently to allow
99 + * the supplicant to make a better switching decision */
100 + if ((rssi < vap->iv_bgscanthr) &&
101 + (!vap->iv_bgscanthr_next ||
102 + !time_before(jiffies, vap->iv_bgscanthr_next)) &&
103 + !(ic->ic_flags & IEEE80211_F_SCAN)) {
106 + ic->ic_lastdata = 0;
107 + ic->ic_lastscan = 0;
108 + ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN_THR;
109 + ret = ieee80211_bg_scan(vap);
111 + vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
114 if (ni->ni_intval != scan.bintval) {
115 IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
116 "beacon interval divergence: "
117 --- a/net80211/ieee80211_scan.c
118 +++ b/net80211/ieee80211_scan.c
120 ieee80211_sta_pwrsave(vap, 0);
121 if (ss->ss_next >= ss->ss_last) {
122 ieee80211_notify_scan_done(vap);
123 - ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
124 + ic->ic_flags_ext &= ~(IEEE80211_FEXT_BGSCAN|IEEE80211_FEXT_BGSCAN_THR);
127 SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;