PERFORCE change 87291 for review

Sam Leffler sam at FreeBSD.org
Sun Nov 27 00:17:48 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=87291

Change 87291 by sam at sam_ebb on 2005/11/27 00:17:11

	Revamp ioctl handling a la linux: don't pass ENETRESET
	back from ieee80211_ioctl except in cases where the device
	must be re-initialized; instead handle state changes
	internally.  This eliminates most gratuitous scanning.

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#52 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#39 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.h#25 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#52 (text+ko) ====

@@ -70,6 +70,7 @@
 	    ((_ic)->ic_ifp->if_drv_flags & IFF_DRV_RUNNING))
 #define	IS_UP_AUTO(_ic) \
 	(IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
+#define	RESCAN	1
 
 static struct ieee80211_channel *findchannel(struct ieee80211com *,
 		int ieee, int mode);
@@ -1201,7 +1202,7 @@
 	    isclr(chanlist, ic->ic_bsschan->ic_ieee))
 		ic->ic_bsschan = IEEE80211_CHAN_ANYC;
 	memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
-	return IS_UP_AUTO(ic) ? ENETRESET : 0;
+	return IS_UP_AUTO(ic) ? ieee80211_init(ic, RESCAN) : 0;
 }
 
 static int
@@ -1412,7 +1413,8 @@
 		ic->ic_des_ssid[0].len = ireq->i_len;
 		memcpy(ic->ic_des_ssid[0].ssid, tmpssid, ireq->i_len);
 		ic->ic_des_nssid = (ireq->i_len > 0);
-		error = ENETRESET;
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
 		break;
 	case IEEE80211_IOC_WEP:
 		switch (ireq->i_val) {
@@ -1429,7 +1431,8 @@
 			ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
 			break;
 		}
-		error = ENETRESET;
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
 		break;
 	case IEEE80211_IOC_WEPKEY:
 		kid = (u_int) ireq->i_val;
@@ -1458,8 +1461,6 @@
 		} else
 			error = EINVAL;
 		ieee80211_key_update_end(ic);
-		if (!error)			/* NB: for compatibility */
-			error = ENETRESET;
 		break;
 	case IEEE80211_IOC_WEPTXKEY:
 		kid = (u_int) ireq->i_val;
@@ -1467,7 +1468,6 @@
 		    (u_int16_t) kid != IEEE80211_KEYIX_NONE)
 			return EINVAL;
 		ic->ic_def_txkey = kid;
-		error = ENETRESET;	/* push to hardware */
 		break;
 	case IEEE80211_IOC_AUTHMODE:
 		switch (ireq->i_val) {
@@ -1507,7 +1507,8 @@
 		ic->ic_bss->ni_authmode = ireq->i_val;
 		/* XXX mixed/mode/usage? */
 		ic->ic_auth = auth;
-		error = ENETRESET;
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
 		break;
 	case IEEE80211_IOC_CHANNEL:
 		/* XXX 0xffff overflows 16-bit signed */
@@ -1580,18 +1581,7 @@
 			 * will pickup the desired channel and avoid scanning.
 			 */
 			if (IS_UP_AUTO(ic))
-				error = ENETRESET;
-		}
-		if (error == ENETRESET && ic->ic_opmode == IEEE80211_M_MONITOR) {
-			if (IS_UP(ic)) {
-				/*
-				 * Monitor mode can switch directly.
-				 */
-				if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
-					ic->ic_curchan = ic->ic_des_chan;
-				error = ic->ic_reset(ic->ic_ifp);
-			} else
-				error = 0;
+				error = ieee80211_init(ic, RESCAN);
 		}
 		break;
 	case IEEE80211_IOC_POWERSAVE:
@@ -1702,7 +1692,7 @@
 			ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
 			break;
 		}
-		error = ENETRESET;		/* XXX? */
+		error = ENETRESET;
 		break;
 	case IEEE80211_IOC_WME:
 		if (ireq->i_val) {
@@ -1711,7 +1701,8 @@
 			ic->ic_flags |= IEEE80211_F_WME;
 		} else
 			ic->ic_flags &= ~IEEE80211_F_WME;
-		error = ENETRESET;		/* XXX maybe not for station? */
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, 0);
 		break;
 	case IEEE80211_IOC_HIDESSID:
 		if (ireq->i_val)
@@ -1801,7 +1792,8 @@
 			ic->ic_flags &= ~IEEE80211_F_DESBSSID;
 		else
 			ic->ic_flags |= IEEE80211_F_DESBSSID;
-		error = ENETRESET;
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
 		break;
 	case IEEE80211_IOC_CHANLIST:
 		error = ieee80211_ioctl_setchanlist(ic, ireq);
@@ -1873,7 +1865,7 @@
 			ic->ic_flags |= IEEE80211_F_FF;
 		} else
 			ic->ic_flags &= ~IEEE80211_F_FF;
-		error = ENETRESET;		/* XXX maybe not for station? */
+		error = ENETRESET;
 		break;
 	case IEEE80211_IOC_TURBOP:
 		if (ireq->i_val) {
@@ -1882,7 +1874,7 @@
 			ic->ic_flags |= IEEE80211_F_TURBOP;
 		} else
 			ic->ic_flags &= ~IEEE80211_F_TURBOP;
-		error = ENETRESET;		/* XXX maybe not for station? */
+		error = ENETRESET;
 		break;
 	case IEEE80211_IOC_BGSCAN:
 		if (ireq->i_val) {
@@ -1942,8 +1934,8 @@
 		error = EINVAL;
 		break;
 	}
-	if (error == ENETRESET && !IS_UP_AUTO(ic))
-		error = 0;
+	if (error == ENETRESET)
+		error = IS_UP_AUTO(ic) ? ieee80211_init(ic, 0) : 0;
 	return error;
 }
 

==== //depot/projects/wifi/sys/net80211/ieee80211_proto.c#39 (text+ko) ====

@@ -843,6 +843,56 @@
 }
 
 /*
+ * Start a device.  If this is the first vap running on the
+ * underlying device then we first bring it up.
+ */
+int
+ieee80211_init(struct ieee80211com *ic, int forcescan)
+{
+	struct ifnet *ifp = ic->ic_ifp;
+
+	IEEE80211_DPRINTF(ic,
+		IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
+		"%s\n", "start running");
+
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		ifp->if_init(ifp);
+	/*
+	 * Kick the 802.11 state machine as appropriate.
+	 */
+	if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
+		if (ic->ic_opmode == IEEE80211_M_STA) {
+			/*
+			 * Try to be intelligent about clocking the state
+			 * machine.  If we're currently in RUN state then
+			 * we should be able to apply any new state/parameters
+			 * simply by re-associating.  Otherwise we need to
+			 * re-scan to select an appropriate ap.
+			 */ 
+			if (ic->ic_state != IEEE80211_S_RUN || forcescan)
+				ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
+			else
+				ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
+		} else {
+			/*
+			 * For monitor+wds modes there's nothing to do but
+			 * start running.  Otherwise, if this is the first
+			 * vap to be brought up, start a scan which may be
+			 * preempted if the station is locked to a particular
+			 * channel.
+			 */
+			if (ic->ic_opmode == IEEE80211_M_MONITOR ||
+			    ic->ic_opmode == IEEE80211_M_WDS) {
+				ic->ic_state = IEEE80211_S_INIT;	/* XXX*/
+				ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+			} else
+				ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
+		}
+	}
+	return 0;
+}
+
+/*
  * Switch between turbo and non-turbo operating modes.
  * Use the specified channel flags to locate the new
  * channel, update 802.11 state, and then call back into

==== //depot/projects/wifi/sys/net80211/ieee80211_proto.h#25 (text+ko) ====

@@ -217,6 +217,7 @@
 
 #define	ieee80211_new_state(_ic, _nstate, _arg) \
 	(((_ic)->ic_newstate)((_ic), (_nstate), (_arg)))
+int	ieee80211_init(struct ieee80211com *, int forcescan);
 void	ieee80211_dturbo_switch(struct ieee80211com *, int newflags);
 void	ieee80211_beacon_miss(struct ieee80211com *);
 void	ieee80211_print_essid(const u_int8_t *, int);


More information about the p4-projects mailing list