madwifi: add an optional background scanning threshold triggered by low rssi
[openwrt.git] / package / madwifi / patches / 357-bgscan_thresh.patch
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)
4
5 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
6
7 --- a/net80211/ieee80211_ioctl.h
8 +++ b/net80211/ieee80211_ioctl.h
9 @@ -646,6 +646,7 @@
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 */
14  };
15  
16  #define        SIOCG80211STATS                 (SIOCDEVPRIVATE+2)
17 --- a/net80211/ieee80211_var.h
18 +++ b/net80211/ieee80211_var.h
19 @@ -92,6 +92,8 @@
20  #define        IEEE80211_BGSCAN_IDLE_MIN       100     /* min idle time (ms) */
21  #define        IEEE80211_BGSCAN_IDLE_DEFAULT   250     /* default idle time (ms) */
22  
23 +#define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
24 +
25  #define IEEE80211_COVERAGE_CLASS_MAX   31      /* max coverage class */
26  #define IEEE80211_REGCLASSIDS_MAX      10      /* max regclass id list */
27  
28 @@ -219,6 +221,9 @@
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 */
37  
38 @@ -608,6 +613,7 @@
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 */
43  
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
48 @@ -2744,6 +2744,9 @@
49                 else
50                         retv = EINVAL;
51                 break;
52 +       case IEEE80211_PARAM_BGSCAN_THRESH:
53 +               vap->iv_bgscanthr = value;
54 +               break;
55         case IEEE80211_PARAM_MCAST_RATE:
56                 /* units are in KILObits per second */
57                 if (value >= 256 && value <= 54000)
58 @@ -3144,6 +3147,9 @@
59         case IEEE80211_PARAM_BGSCAN_INTERVAL:
60                 param[0] = vap->iv_bgscanintvl / HZ;    /* seconds */
61                 break;
62 +       case IEEE80211_PARAM_BGSCAN_THRESH:
63 +               param[0] = vap->iv_bgscanthr;   /* rssi */
64 +               break;
65         case IEEE80211_PARAM_MCAST_RATE:
66                 param[0] = vap->iv_mcast_rate;  /* seconds */
67                 break;
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 @@
82  {
83         struct ieee80211com *ic = vap->iv_ic;
84  
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)));
90  }
91  
92  static __inline int
93 @@ -3258,6 +3260,23 @@
94                         /* record tsf of last beacon */
95                         memcpy(ni->ni_tstamp.data, scan.tstamp,
96                                 sizeof(ni->ni_tstamp));
97 +
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)) {
104 +                               int ret;
105 +
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);
110 +                               if (ret)
111 +                                       vap->iv_bgscanthr_next = jiffies + msecs_to_jiffies(IEEE80211_BGSCAN_TRIGGER_INTVL * 1000);
112 +                       }
113 +
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
119 @@ -782,7 +782,7 @@
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);
125                                 }
126                         }
127                         SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;