Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Oct 2010 20:43:37 +0200
From:      Bernhard Schmidt <bschmidt@techwires.net>
To:        Alexey Dokuchaev <danfe@freebsd.org>
Cc:        net@freebsd.org
Subject:   Re: Monitor mode not working for iwi(4) on 7.X
Message-ID:  <AANLkTimB4gRYYzO8UHAGHB9p0nEm5utvXTwWX%2Baypt5J@mail.gmail.com>
In-Reply-To: <20101006100335.GA26843@FreeBSD.org>
References:  <4763016D.7060100@janh.de> <20101006100335.GA26843@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
2010/10/6 Alexey Dokuchaev <danfe@freebsd.org>:
> On Fri, Dec 14, 2007 at 11:19:25PM +0100, Jan Henrik Sylvester wrote:
>> In contrast to 6.2-RELEASE, monitor mode does not work. Kismet does
>> not receive anything, while it does with ath or ural (even at the same
>> time). dmesg with debug.iwi=2 is below -- anything unusual?
>>
>> Moreover, "ifconfig iwi0 scan" sometimes just hangs, which never
>> happened on 6.2-RELEASE.
>
> Just found this email sent to stable@ almost three years ago; sadly I
> have to confirm iwi(4) still exhibits these problems on fairly recent
> 7-STABLE (early Juneish).  Maybe I have better luck on net@ (I am
> particularly interested in working monitor mode).  Thanks.  Any debug
> information will be gladly provided.  Pointers where to look (revisions
> to try, patches, etc.) are greatly appreciated.

Try the attached patch, this is basically the code from stable/6
ported to head and stable/7. I did only some basic tests but monitor
mode seems to work and it is still possible to use the card in STA
mode.

I'm not sure why that got lost, but there must be a reason I'm not
seeing right now. If someone has more knowledge about that, please
let me know, otherwise I intend to commit it this weekend.


-- 
Bernhard

[-- Attachment #2 --]
Index: sys/dev/iwi/if_iwivar.h
===================================================================
--- sys/dev/iwi/if_iwivar.h	(revision 213517)
+++ sys/dev/iwi/if_iwivar.h	(working copy)
@@ -193,6 +193,7 @@ struct iwi_softc {
 	struct task		sc_restarttask;	/* restart adapter processing */
 	struct task		sc_disassoctask;
 	struct task		sc_wmetask;	/* set wme parameters */
+	struct task		sc_monitortask;
 
 	unsigned int		sc_softled : 1,	/* enable LED gpio status */
 				sc_ledstate: 1,	/* LED on/off state */
Index: sys/dev/iwi/if_iwi.c
===================================================================
--- sys/dev/iwi/if_iwi.c	(revision 213517)
+++ sys/dev/iwi/if_iwi.c	(working copy)
@@ -180,6 +180,7 @@ static void	iwi_release_fw_dma(struct iwi_softc *s
 static int	iwi_config(struct iwi_softc *);
 static int	iwi_get_firmware(struct iwi_softc *, enum ieee80211_opmode);
 static void	iwi_put_firmware(struct iwi_softc *);
+static void	iwi_monitor_scan(void *, int);
 static int	iwi_scanchan(struct iwi_softc *, unsigned long, int);
 static void	iwi_scan_start(struct ieee80211com *);
 static void	iwi_scan_end(struct ieee80211com *);
@@ -292,6 +293,7 @@ iwi_attach(device_t dev)
 	TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
 	TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
 	TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, sc);
+	TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc);
 
 	callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
 	callout_init_mtx(&sc->sc_rftimer, &sc->sc_mtx, 0);
@@ -460,6 +462,7 @@ iwi_detach(device_t dev)
 	ieee80211_draintask(ic, &sc->sc_radiofftask);
 	ieee80211_draintask(ic, &sc->sc_restarttask);
 	ieee80211_draintask(ic, &sc->sc_disassoctask);
+	ieee80211_draintask(ic, &sc->sc_monitortask);
 
 	iwi_stop(sc);
 
@@ -988,7 +991,8 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80
 			 * This is all totally bogus and needs to be redone.
 			 */
 			iwi_auth_and_assoc(sc, vap);
-		}
+		} else if (vap->iv_opmode == IEEE80211_M_MONITOR)
+			ieee80211_runtask(ic, &sc->sc_monitortask);
 		break;
 	case IEEE80211_S_ASSOC:
 		/*
@@ -1407,6 +1411,18 @@ iwi_notification_intr(struct iwi_softc *sc, struct
 
 		IWI_STATE_END(sc, IWI_FW_SCANNING);
 
+		/*
+		 * Monitor mode works by doing a passive scan to set
+		 * the channel and enable rx.  Because we don't want
+		 * to abort a scan lest the firmware crash we scan
+		 * for a short period of time and automatically restart
+		 * the scan when notified the sweep has completed.
+		 */
+		if (vap->iv_opmode == IEEE80211_M_MONITOR) {
+			ieee80211_runtask(ic, &sc->sc_monitortask);
+			break;
+		}
+
 		if (scan->status == IWI_SCAN_COMPLETED) {
 			/* NB: don't need to defer, net80211 does it for us */
 			ieee80211_scan_next(vap);
@@ -2557,6 +2573,11 @@ iwi_config(struct iwi_softc *sc)
 	config.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
 	config.disable_unicast_decryption = 1;
 	config.disable_multicast_decryption = 1;
+	if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+		config.allow_invalid_frames = 1;
+		config.allow_beacon_and_probe_resp = 1;
+		config.allow_mgt = 1;
+	}
 	DPRINTF(("Configuring adapter\n"));
 	error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
 	if (error != 0)
@@ -2642,6 +2663,18 @@ scan_band(const struct ieee80211_channel *c)
 	return IEEE80211_IS_CHAN_5GHZ(c) ?  IWI_CHAN_5GHZ : IWI_CHAN_2GHZ;
 }
 
+static void
+iwi_monitor_scan(void *arg, int npending)
+{
+	struct ieee80211com *ic = arg;
+	struct iwi_softc *sc = ic->ic_ifp->if_softc;
+	IWI_LOCK_DECL;
+
+	IWI_LOCK(sc);
+	(void) iwi_scanchan(sc, 2000, 0);
+	IWI_UNLOCK(sc);
+}
+
 /*
  * Start a scan on the current channel or all channels.
  */

[-- Attachment #3 --]
Index: sys/dev/iwi/if_iwivar.h
===================================================================
--- sys/dev/iwi/if_iwivar.h	(revision 213522)
+++ sys/dev/iwi/if_iwivar.h	(working copy)
@@ -193,6 +193,7 @@ struct iwi_softc {
 	struct task		sc_scanaborttask;	/* cancel active scan */
 	struct task		sc_restarttask;	/* restart adapter processing */
 	struct task		sc_opstask;	/* scan / auth processing */
+	struct task		sc_monitortask;
 
 	unsigned int		sc_softled : 1,	/* enable LED gpio status */
 				sc_ledstate: 1,	/* LED on/off state */
Index: sys/dev/iwi/if_iwi.c
===================================================================
--- sys/dev/iwi/if_iwi.c	(revision 213522)
+++ sys/dev/iwi/if_iwi.c	(working copy)
@@ -163,6 +163,7 @@ static void	iwi_release_fw_dma(struct iwi_softc *s
 static int	iwi_config(struct iwi_softc *);
 static int	iwi_get_firmware(struct iwi_softc *);
 static void	iwi_put_firmware(struct iwi_softc *);
+static void	iwi_monitor_scan(void *, int);
 static int	iwi_scanchan(struct iwi_softc *, unsigned long, int);
 static void	iwi_scan_start(struct ieee80211com *);
 static void	iwi_scan_end(struct ieee80211com *);
@@ -291,6 +292,7 @@ iwi_attach(device_t dev)
 	TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
 	TASK_INIT(&sc->sc_opstask, 0, iwi_ops, sc);
 	TASK_INIT(&sc->sc_scanaborttask, 0, iwi_scanabort, sc);
+	TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc);
 	callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
 
 	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
@@ -978,7 +980,8 @@ iwi_newstate(struct ieee80211com *ic, enum ieee802
 			 */
 			if (ic->ic_state == IEEE80211_S_SCAN)
 				iwi_assoc(ic);
-		} 
+		} else if (ic->ic_opmode == IEEE80211_M_MONITOR)
+			taskqueue_enqueue(sc->sc_tq, &sc->sc_monitortask);
 		break;
 	case IEEE80211_S_INIT:
 		/*
@@ -1411,6 +1414,18 @@ iwi_notification_intr(struct iwi_softc *sc, struct
 
 		IWI_STATE_END(sc, IWI_FW_SCANNING);
 
+		/*
+		 * Monitor mode works by doing a passive scan to set
+		 * the channel and enable rx.  Because we don't want
+		 * to abort a scan lest the firmware crash we scan
+		 * for a short period of time and automatically restart
+		 * the scan when notified the sweep has completed.
+		 */
+		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+			taskqueue_enqueue(sc->sc_tq, &sc->sc_monitortask);
+			break;
+		}
+
 		if (scan->status == IWI_SCAN_COMPLETED)
 			ieee80211_scan_next(ic);
 
@@ -2595,6 +2610,11 @@ iwi_config(struct iwi_softc *sc)
 	config.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
 	config.disable_unicast_decryption = 1;
 	config.disable_multicast_decryption = 1;
+	if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+		config.allow_invalid_frames = 1;
+		config.allow_beacon_and_probe_resp = 1;
+		config.allow_mgt = 1;
+	}
 	DPRINTF(("Configuring adapter\n"));
 	error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
 	if (error != 0)
@@ -2717,6 +2737,18 @@ scan_band(const struct ieee80211_channel *c)
 	return IEEE80211_IS_CHAN_5GHZ(c) ?  IWI_CHAN_5GHZ : IWI_CHAN_2GHZ;
 }
 
+static void
+iwi_monitor_scan(void *arg, int npending)
+{
+	struct ieee80211com *ic = arg;
+	struct iwi_softc *sc = ic->ic_ifp->if_softc;
+	IWI_LOCK_DECL;
+
+	IWI_LOCK(sc);
+	(void) iwi_scanchan(sc, 2000, 0);
+	IWI_UNLOCK(sc);
+}
+
 /*
  * Start a scan on the current channel or all channels.
  */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTimB4gRYYzO8UHAGHB9p0nEm5utvXTwWX%2Baypt5J>