| 1 | Add an optional threshold for low-rssi disconnection. This can be useful |
| 2 | when letting wpa_supplicant control roaming. |
| 3 | |
| 4 | Signed-off-by: Felix Fietkau <nbd@openwrt.org> |
| 5 | |
| 6 | --- a/net80211/ieee80211_ioctl.h |
| 7 | +++ b/net80211/ieee80211_ioctl.h |
| 8 | @@ -647,6 +647,8 @@ enum { |
| 9 | IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */ |
| 10 | IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */ |
| 11 | IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */ |
| 12 | + IEEE80211_PARAM_RSSI_DIS_THR = 80, /* rssi threshold for disconnection */ |
| 13 | + IEEE80211_PARAM_RSSI_DIS_COUNT = 81, /* counter for rssi threshold */ |
| 14 | }; |
| 15 | |
| 16 | #define SIOCG80211STATS (SIOCDEVPRIVATE+2) |
| 17 | --- a/net80211/ieee80211_wireless.c |
| 18 | +++ b/net80211/ieee80211_wireless.c |
| 19 | @@ -2799,6 +2799,12 @@ ieee80211_ioctl_setparam(struct net_devi |
| 20 | case IEEE80211_PARAM_ROAM_RATE_11G: |
| 21 | vap->iv_roam.rate11b = value; |
| 22 | break; |
| 23 | + case IEEE80211_PARAM_RSSI_DIS_THR: |
| 24 | + vap->iv_rssi_dis_thr = value; |
| 25 | + break; |
| 26 | + case IEEE80211_PARAM_RSSI_DIS_COUNT: |
| 27 | + vap->iv_rssi_dis_max = value; |
| 28 | + break; |
| 29 | case IEEE80211_PARAM_UAPSDINFO: |
| 30 | if (vap->iv_opmode == IEEE80211_M_HOSTAP) { |
| 31 | if (ic->ic_caps & IEEE80211_C_UAPSD) { |
| 32 | @@ -3184,6 +3190,12 @@ ieee80211_ioctl_getparam(struct net_devi |
| 33 | case IEEE80211_PARAM_ROAM_RATE_11G: |
| 34 | param[0] = vap->iv_roam.rate11b; |
| 35 | break; |
| 36 | + case IEEE80211_PARAM_RSSI_DIS_THR: |
| 37 | + param[0] = vap->iv_rssi_dis_thr; |
| 38 | + break; |
| 39 | + case IEEE80211_PARAM_RSSI_DIS_COUNT: |
| 40 | + param[0] = vap->iv_rssi_dis_max; |
| 41 | + break; |
| 42 | case IEEE80211_PARAM_UAPSDINFO: |
| 43 | if (vap->iv_opmode == IEEE80211_M_HOSTAP) { |
| 44 | if (IEEE80211_VAP_UAPSD_ENABLED(vap)) |
| 45 | @@ -5733,6 +5745,14 @@ static const struct iw_priv_args ieee802 |
| 46 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rate11g" }, |
| 47 | { IEEE80211_PARAM_ROAM_RATE_11G, |
| 48 | 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rate11g" }, |
| 49 | + { IEEE80211_PARAM_RSSI_DIS_THR, |
| 50 | + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_disthr" }, |
| 51 | + { IEEE80211_PARAM_RSSI_DIS_THR, |
| 52 | + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_disthr" }, |
| 53 | + { IEEE80211_PARAM_RSSI_DIS_COUNT, |
| 54 | + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rssi_discnt" }, |
| 55 | + { IEEE80211_PARAM_RSSI_DIS_COUNT, |
| 56 | + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rssi_discnt" }, |
| 57 | { IEEE80211_PARAM_UAPSDINFO, |
| 58 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "uapsd" }, |
| 59 | { IEEE80211_PARAM_UAPSDINFO, |
| 60 | --- a/net80211/ieee80211_input.c |
| 61 | +++ b/net80211/ieee80211_input.c |
| 62 | @@ -3261,6 +3261,19 @@ ieee80211_recv_mgmt(struct ieee80211vap |
| 63 | memcpy(ni->ni_tstamp.data, scan.tstamp, |
| 64 | sizeof(ni->ni_tstamp)); |
| 65 | |
| 66 | + /* when rssi falls below the disconnection threshold, drop the connection */ |
| 67 | + if ((vap->iv_rssi_dis_thr > 0) && (vap->iv_rssi_dis_max > 0)) { |
| 68 | + if ((rssi > 0) && (rssi < vap->iv_rssi_dis_thr)) { |
| 69 | + if (++vap->iv_rssi_dis_trig > vap->iv_rssi_dis_max) { |
| 70 | + vap->iv_rssi_dis_trig = 0; |
| 71 | + ieee80211_node_leave(ni); |
| 72 | + return; |
| 73 | + } |
| 74 | + } else { |
| 75 | + vap->iv_rssi_dis_trig = 0; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | /* When rssi is low, start doing bgscans more frequently to allow |
| 80 | * the supplicant to make a better switching decision */ |
| 81 | if (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) && |
| 82 | --- a/net80211/ieee80211_var.h |
| 83 | +++ b/net80211/ieee80211_var.h |
| 84 | @@ -223,6 +223,9 @@ struct ieee80211vap { |
| 85 | u_int iv_bgscanintvl; /* bg scan min interval */ |
| 86 | u_int iv_bgscanthr; /* bg scan rssi threshold */ |
| 87 | u_int iv_bgscantrintvl; /* bg scan trigger interval */ |
| 88 | + u_int iv_rssi_dis_thr; /* rssi disassoc threshold */ |
| 89 | + u_int iv_rssi_dis_max; /* max beacons below disconnect threshold */ |
| 90 | + u_int iv_rssi_dis_trig; /* rssi disassoc trigger count */ |
| 91 | unsigned long iv_bgscanthr_next; /* last trigger for bgscan */ |
| 92 | unsigned long iv_lastconnect; /* time of last connect attempt */ |
| 93 | u_int iv_scanvalid; /* scan cache valid threshold */ |
| 94 | |