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