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>
