mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			161 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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 @@ enum {
 | |
|  	IEEE80211_PARAM_MINRATE			= 76,	/* Minimum 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,10 @@ struct ieee80211vap {
 | |
|  	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 */
 | |
| +	unsigned long iv_lastconnect;	/* time of last connect attempt */
 | |
|  	u_int iv_scanvalid;				/* scan cache valid threshold */
 | |
|  	struct ieee80211_roam iv_roam;			/* sta-mode roaming state */
 | |
|  
 | |
| @@ -608,6 +614,7 @@ MALLOC_DECLARE(M_80211_VAP);
 | |
|  #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 @@ ieee80211_ioctl_setparam(struct net_devi
 | |
|  		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 @@ ieee80211_ioctl_getparam(struct net_devi
 | |
|  	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 @@ static const struct iw_priv_args ieee802
 | |
|  	  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 @@ contbgscan(struct ieee80211vap *vap)
 | |
|  {
 | |
|  	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,25 @@ ieee80211_recv_mgmt(struct ieee80211vap
 | |
|  			/* 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 (!(ic->ic_flags & IEEE80211_F_SCAN) && (rssi < vap->iv_bgscanthr) &&
 | |
| +					(!vap->iv_bgscanthr_next ||
 | |
| +						!time_before(jiffies, vap->iv_bgscanthr_next)) &&
 | |
| +					(vap->iv_state == IEEE80211_S_RUN) &&
 | |
| +					time_after(jiffies, vap->iv_lastconnect +
 | |
| +						msecs_to_jiffies(IEEE80211_BGSCAN_INTVAL_MIN * 1000))) {
 | |
| +				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
 | |
| @@ -616,6 +616,7 @@ ieee80211_cancel_scan(struct ieee80211va
 | |
|  
 | |
|  		/* clear bg scan NOPICK and mark cancel request */
 | |
|  		ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
 | |
| +		ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN_THR;
 | |
|  		SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
 | |
|  		ss->ss_ops->scan_cancel(ss, vap);
 | |
|  		/* force it to fire asap */
 | |
| @@ -782,7 +783,7 @@ again:
 | |
|  				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;
 | |
| --- a/net80211/ieee80211_proto.c
 | |
| +++ b/net80211/ieee80211_proto.c
 | |
| @@ -1450,6 +1450,7 @@ __ieee80211_newstate(struct ieee80211vap
 | |
|  		}
 | |
|  		break;
 | |
|  	case IEEE80211_S_AUTH:
 | |
| +		vap->iv_lastconnect = jiffies;
 | |
|  		/* auth frames are possible between IBSS nodes, 
 | |
|  		 * see 802.11-1999, chapter 5.7.6 */
 | |
|  		KASSERT(vap->iv_opmode == IEEE80211_M_STA || 
 | |
| --- a/net80211/ieee80211_output.c
 | |
| +++ b/net80211/ieee80211_output.c
 | |
| @@ -238,7 +238,8 @@ ieee80211_hardstart(struct sk_buff *skb,
 | |
|  	}
 | |
|  	
 | |
|  	/* Cancel any running BG scan */
 | |
| -	ieee80211_cancel_scan(vap);
 | |
| +	if (!(ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN_THR) && (vap->iv_state == IEEE80211_S_RUN))
 | |
| +		ieee80211_cancel_scan(vap);
 | |
|  
 | |
|  	/* 
 | |
|  	 * Find the node for the destination so we can do
 |