aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/346-protmode_trig.patch
blob: 5b5cec6e984b41c05ddc0d2b7842c36e1a71aa7d (plain)
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
128
129
130
131
132
133
134
135
--- a/net80211/ieee80211.c
+++ b/net80211/ieee80211.c
@@ -333,7 +333,9 @@ ieee80211_ifattach(struct ieee80211com *
 			IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS), 
 			ic->ic_lintval), ic->ic_lintval);
 	}
-		
+	ic->ic_protmode_timeout = IEEE80211_PROTMODE_TIMEOUT;
+	ic->ic_protmode_rssi = IEEE80211_PROTMODE_RSSITHR;
+
 	IEEE80211_LOCK_INIT(ic, "ieee80211com");
 	IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps");
 	TAILQ_INIT(&ic->ic_vaps);
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -3411,14 +3411,18 @@ ieee80211_recv_mgmt(struct ieee80211vap
 			IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
 
 			/* Assume no ERP IE == 11b AP */
-			if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
-				!(ic->ic_flags & IEEE80211_F_USEPROT)) {
+			if ((!has_erp || (has_erp &&
+				(scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+				(rssi > ic->ic_protmode_rssi)) {
 				struct ieee80211vap *tmpvap;
 
-				ic->ic_flags |= IEEE80211_F_USEPROT;
-				TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
-					tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+				if (!(ic->ic_flags & IEEE80211_F_USEPROT)) {
+					ic->ic_flags |= IEEE80211_F_USEPROT;
+					TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+						tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+					}
 				}
+				ic->ic_protmode_lasttrig = jiffies;
 			}
 		}
 
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -643,6 +643,8 @@ enum {
 	IEEE80211_PARAM_BEACON_MISS_THRESH_MS	= 74,	/* Beacon miss threshold (in ms) */
 	IEEE80211_PARAM_MAXRATE			= 75,	/* Maximum rate (by table index) */
 	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 */
 };
 
 #define	SIOCG80211STATS			(SIOCDEVPRIVATE+2)
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -128,6 +128,9 @@
 
 #define	IEEE80211_APPIE_MAX	1024
 
+#define IEEE80211_PROTMODE_RSSITHR	15	/* default rssi threshold for protection mode trigger */
+#define IEEE80211_PROTMODE_TIMEOUT	30	/* timeout for keeping protection mode alive */
+
 #define IEEE80211_PWRCONSTRAINT_VAL(ic) \
 	(((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
 	    (ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0)
@@ -324,6 +327,9 @@ struct ieee80211com {
 	u_int16_t ic_newtxpowlimit; 		/* tx power limit to change to (in 0.5 dBm) */
 	u_int16_t ic_uapsdmaxtriggers; 		/* max triggers that could arrive */
 	u_int8_t ic_coverageclass; 		/* coverage class */
+	u_int8_t ic_protmode_rssi;			/* rssi threshold for protection mode */
+	u_int64_t ic_protmode_lasttrig;		/* last trigger for protection mode */
+	u_int16_t ic_protmode_timeout;		/* protection mode timeout */
 
 	/* Channel state:
 	 *
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
@@ -2312,6 +2312,12 @@ ieee80211_ioctl_setparam(struct net_devi
 		    IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
 			retv = ENETRESET;
 		break;
+	case IEEE80211_PARAM_PROTMODE_TIMEOUT:
+		ic->ic_protmode_timeout = value;
+		break;
+	case IEEE80211_PARAM_PROTMODE_RSSI:
+		ic->ic_protmode_rssi = value;
+		break;
 	case IEEE80211_PARAM_MCASTCIPHER:
 		if ((vap->iv_caps & cipher2cap(value)) == 0 &&
 		    !ieee80211_crypto_available(vap, value))
@@ -2955,6 +2961,12 @@ ieee80211_ioctl_getparam(struct net_devi
 	case IEEE80211_PARAM_PROTMODE:
 		param[0] = ic->ic_protmode;
 		break;
+	case IEEE80211_PARAM_PROTMODE_TIMEOUT:
+		param[0] = ic->ic_protmode_timeout;
+		break;
+	case IEEE80211_PARAM_PROTMODE_RSSI:
+		param[0] = ic->ic_protmode_rssi;
+		break;
 	case IEEE80211_PARAM_MCASTCIPHER:
 		param[0] = rsn->rsn_mcastcipher;
 		break;
@@ -5346,6 +5358,14 @@ static const struct iw_priv_args ieee802
 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protmode" },
 	{ IEEE80211_PARAM_PROTMODE,
 	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protmode" },
+	{ IEEE80211_PARAM_PROTMODE_RSSI,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protrssi" },
+	{ IEEE80211_PARAM_PROTMODE_RSSI,
+	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protrssi" },
+	{ IEEE80211_PARAM_PROTMODE_TIMEOUT,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "prottime" },
+	{ IEEE80211_PARAM_PROTMODE_TIMEOUT,
+	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_prottime" },
 	{ IEEE80211_PARAM_MCASTCIPHER,
 	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcastcipher" },
 	{ IEEE80211_PARAM_MCASTCIPHER,
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -1877,6 +1877,17 @@ ieee80211_node_timeout(unsigned long arg
 
 	ieee80211_scan_timeout(ic);
 	ieee80211_timeout_stations(&ic->ic_sta);
+	if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+		(ic->ic_protmode_lasttrig + ic->ic_protmode_timeout * HZ <
+			jiffies)) {
+		struct ieee80211vap *tmpvap;
+
+		/* expire protection mode */
+		ic->ic_flags &= ~IEEE80211_F_USEPROT;
+		TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {
+			tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+		}
+	}
 
 	ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ;
 	add_timer(&ic->ic_inact);