Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Jun 2009 00:33:28 +0000 (UTC)
From:      Sam Leffler <sam@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r193292 - head/sys/net80211
Message-ID:  <200906020033.n520XSbb097397@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sam
Date: Tue Jun  2 00:33:28 2009
New Revision: 193292
URL: http://svn.freebsd.org/changeset/base/193292

Log:
  Fix monitor mode vaps to work as intended:
  o track # bpf taps on monitor mode vaps instead of # monitor mode vaps
  o spam monitor mode taps on tx/rx
  o fix ieee80211_radiotap_rx_all to dispatch frames only if the vap is up
  o while here print radiotap (and superg) state in show com

Modified:
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211_ddb.c
  head/sys/net80211/ieee80211_freebsd.c
  head/sys/net80211/ieee80211_hostap.c
  head/sys/net80211/ieee80211_input.c
  head/sys/net80211/ieee80211_radiotap.c
  head/sys/net80211/ieee80211_var.h

Modified: head/sys/net80211/ieee80211.c
==============================================================================
--- head/sys/net80211/ieee80211.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -513,8 +513,6 @@ ieee80211_vap_attach(struct ieee80211vap
 
 	IEEE80211_LOCK(ic);
 	TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
-	if (vap->iv_opmode == IEEE80211_M_MONITOR)
-		ic->ic_monvaps++;
 	ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
 #ifdef IEEE80211_SUPPORT_SUPERG
 	ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
@@ -575,8 +573,6 @@ ieee80211_vap_detach(struct ieee80211vap
 	IEEE80211_LOCK(ic);
 	KASSERT(vap->iv_state == IEEE80211_S_INIT , ("vap still running"));
 	TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
-	if (vap->iv_opmode == IEEE80211_M_MONITOR)
-		ic->ic_monvaps--;
 	ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
 #ifdef IEEE80211_SUPPORT_SUPERG
 	ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);

Modified: head/sys/net80211/ieee80211_ddb.c
==============================================================================
--- head/sys/net80211/ieee80211_ddb.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_ddb.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -584,6 +584,11 @@ _db_show_com(const struct ieee80211com *
 	db_printf(" lastnonht %d", ic->ic_lastnonht);
 	db_printf("\n");
 
+	db_printf("\tsuperg %p\n", ic->ic_superg);
+
+	db_printf("\tmontaps %d th %p txchan %p rh %p rxchan %p\n",
+	    ic->ic_montaps, ic->ic_th, ic->ic_txchan, ic->ic_rh, ic->ic_rxchan);
+
 	if (showprocs) {
 		DB_PRINTSYM("\t", "ic_vap_create", ic->ic_vap_create);
 		DB_PRINTSYM("\t", "ic_vap_delete", ic->ic_vap_delete);

Modified: head/sys/net80211/ieee80211_freebsd.c
==============================================================================
--- head/sys/net80211/ieee80211_freebsd.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_freebsd.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -706,11 +706,16 @@ bpf_track(void *arg, struct ifnet *ifp, 
 		 * vap.  This flag is used by drivers to prepare radiotap
 		 * state only when needed.
 		 */
-		if (attach)
+		if (attach) {
 			ieee80211_syncflag_ext(vap, IEEE80211_FEXT_BPF);
+			if (vap->iv_opmode == IEEE80211_M_MONITOR)
+				atomic_add_int(&vap->iv_ic->ic_montaps, 1);
 		/* NB: if_softc is NULL on vap detach */
-		else if (vap != NULL && !bpf_peers_present(vap->iv_rawbpf))
+		} else if (vap != NULL && !bpf_peers_present(vap->iv_rawbpf)) {
 			ieee80211_syncflag_ext(vap, -IEEE80211_FEXT_BPF);
+			if (vap->iv_opmode == IEEE80211_M_MONITOR)
+				atomic_subtract_int(&vap->iv_ic->ic_montaps, 1);
+		}
 	}
 }
 

Modified: head/sys/net80211/ieee80211_hostap.c
==============================================================================
--- head/sys/net80211/ieee80211_hostap.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_hostap.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -302,6 +302,9 @@ hostap_deliver_data(struct ieee80211vap 
 	struct ether_header *eh = mtod(m, struct ether_header *);
 	struct ifnet *ifp = vap->iv_ifp;
 
+	/* clear driver/net80211 flags before passing up */
+	m->m_flags &= ~(M_80211_RX | M_MCAST | M_BCAST);
+
 	KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP,
 	    ("gack, opmode %d", vap->iv_opmode));
 	/*
@@ -316,9 +319,6 @@ hostap_deliver_data(struct ieee80211vap 
 	} else
 		IEEE80211_NODE_STAT(ni, rx_ucast);
 
-	/* clear driver/net80211 flags before passing up */
-	m->m_flags &= ~M_80211_RX;
-
 	/* perform as a bridge within the AP */
 	if ((vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0) {
 		struct mbuf *mcopy = NULL;

Modified: head/sys/net80211/ieee80211_input.c
==============================================================================
--- head/sys/net80211/ieee80211_input.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_input.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -60,6 +60,8 @@ ieee80211_input_all(struct ieee80211com 
 	struct ieee80211vap *vap;
 	int type = -1;
 
+	m->m_flags |= M_BCAST;		/* NB: mark for bpf tap'ing */
+
 	/* XXX locking */
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
 		struct ieee80211_node *ni;
@@ -199,6 +201,9 @@ ieee80211_deliver_data(struct ieee80211v
 	struct ether_header *eh = mtod(m, struct ether_header *);
 	struct ifnet *ifp = vap->iv_ifp;
 
+	/* clear driver/net80211 flags before passing up */
+	m->m_flags &= ~(M_80211_RX | M_MCAST | M_BCAST);
+
 	/* NB: see hostap_deliver_data, this path doesn't handle hostap */
 	KASSERT(vap->iv_opmode != IEEE80211_M_HOSTAP, ("gack, hostap"));
 	/*
@@ -214,9 +219,6 @@ ieee80211_deliver_data(struct ieee80211v
 		IEEE80211_NODE_STAT(ni, rx_ucast);
 	m->m_pkthdr.rcvif = ifp;
 
-	/* clear driver/net80211 flags before passing up */
-	m->m_flags &= ~M_80211_RX;
-
 	if (ni->ni_vlan != 0) {
 		/* attach vlan tag */
 		m->m_pkthdr.ether_vtag = ni->ni_vlan;

Modified: head/sys/net80211/ieee80211_radiotap.c
==============================================================================
--- head/sys/net80211/ieee80211_radiotap.c	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_radiotap.c	Tue Jun  2 00:33:28 2009	(r193292)
@@ -168,6 +168,7 @@ ieee80211_radiotap_chan_change(struct ie
 	}
 }
 
+#if 0
 static void
 dispatch_radiotap(struct ieee80211vap *vap0, struct mbuf *m,
 	struct ieee80211_radiotap_header *rh)
@@ -175,17 +176,46 @@ dispatch_radiotap(struct ieee80211vap *v
 	struct ieee80211com *ic = vap0->iv_ic;
 	int len = le16toh(rh->it_len);
 
-	if (ieee80211_radiotap_active_vap(vap0))
+	if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF)
 		bpf_mtap2(vap0->iv_rawbpf, rh, len, m);
-	if (ic->ic_monvaps) {
+	/*
+	 * Spam monitor mode vaps with unicast frames.  Multicast
+	 * frames are handled by passing through ieee80211_input_all
+	 * which distributes copies to the monitor mode vaps to be
+	 * processed above.
+	 */
+	if (ic->ic_montaps != 0 && (m->m_flags & M_BCAST) == 0) {
 		struct ieee80211vap *vap;
 		TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
-			if (vap->iv_opmode == IEEE80211_M_MONITOR &&
-			    vap != vap0 && ieee80211_radiotap_active_vap(vap))
+			if (vap != vap0 &&
+			    vap->iv_opmode == IEEE80211_M_MONITOR &&
+			    (vap->iv_flags_ext & IEEE80211_FEXT_BPF) &&
+			    vap->iv_state != IEEE80211_S_INIT)
 				bpf_mtap2(vap->iv_rawbpf, rh, len, m);
 		}
 	}
 }
+#endif
+
+/*
+ * Distribute radiotap data (+packet) to all monitor mode
+ * vaps with an active tap other than vap0.
+ */
+static void
+spam_vaps(struct ieee80211vap *vap0, struct mbuf *m,
+	struct ieee80211_radiotap_header *rh, int len)
+{
+	struct ieee80211com *ic = vap0->iv_ic;
+	struct ieee80211vap *vap;
+
+	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+		if (vap != vap0 &&
+		    vap->iv_opmode == IEEE80211_M_MONITOR &&
+		    (vap->iv_flags_ext & IEEE80211_FEXT_BPF) &&
+		    vap->iv_state != IEEE80211_S_INIT)
+			bpf_mtap2(vap->iv_rawbpf, rh, len, m);
+	}
+}
 
 /*
  * Dispatch radiotap data for transmitted packet.
@@ -193,8 +223,20 @@ dispatch_radiotap(struct ieee80211vap *v
 void
 ieee80211_radiotap_tx(struct ieee80211vap *vap0, struct mbuf *m)
 {
-	KASSERT(vap0->iv_ic->ic_th != NULL, ("no tx radiotap header"));
-	dispatch_radiotap(vap0, m, vap0->iv_ic->ic_th);
+	struct ieee80211com *ic = vap0->iv_ic;
+	struct ieee80211_radiotap_header *th = ic->ic_th;
+	int len;
+
+	KASSERT(th != NULL, ("no tx radiotap header"));
+	len = le16toh(th->it_len);
+
+	if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF)
+		bpf_mtap2(vap0->iv_rawbpf, th, len, m);
+	/*
+	 * Spam monitor mode vaps.
+	 */
+	if (ic->ic_montaps != 0)
+		spam_vaps(vap0, m, th, len);
 }
 
 /*
@@ -203,8 +245,22 @@ ieee80211_radiotap_tx(struct ieee80211va
 void
 ieee80211_radiotap_rx(struct ieee80211vap *vap0, struct mbuf *m)
 {
-	KASSERT(vap0->iv_ic->ic_rh != NULL, ("no rx radiotap header"));
-	dispatch_radiotap(vap0, m, vap0->iv_ic->ic_rh);
+	struct ieee80211com *ic = vap0->iv_ic;
+	struct ieee80211_radiotap_header *rh = ic->ic_rh;
+	int len;
+
+	KASSERT(rh != NULL, ("no rx radiotap header"));
+	len = le16toh(rh->it_len);
+
+	if (vap0->iv_flags_ext & IEEE80211_FEXT_BPF)
+		bpf_mtap2(vap0->iv_rawbpf, rh, len, m);
+	/*
+	 * Spam monitor mode vaps with unicast frames.  Multicast
+	 * frames are handled by passing through ieee80211_input_all
+	 * which distributes copies to the monitor mode vaps.
+	 */
+	if (ic->ic_montaps != 0 && (m->m_flags & M_BCAST) == 0)
+		spam_vaps(vap0, m, rh, len);
 }
 
 /*
@@ -221,7 +277,8 @@ ieee80211_radiotap_rx_all(struct ieee802
 
 	/* XXX locking? */
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
-		if (ieee80211_radiotap_active_vap(vap))
+		if (ieee80211_radiotap_active_vap(vap) &&
+		    vap->iv_state != IEEE80211_S_INIT)
 			bpf_mtap2(vap->iv_rawbpf, rh, len, m);
 	}
 }

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h	Tue Jun  2 00:30:30 2009	(r193291)
+++ head/sys/net80211/ieee80211_var.h	Tue Jun  2 00:33:28 2009	(r193292)
@@ -215,7 +215,7 @@ struct ieee80211com {
 	void			*ic_txchan;	/* channel state in ic_th */
 	struct ieee80211_radiotap_header *ic_rh;/* rx radiotap headers */
 	void			*ic_rxchan;	/* channel state in ic_rh */
-	int			ic_monvaps;	/* # monitor mode vaps */
+	int			ic_montaps;	/* active monitor mode taps */
 
 	/* virtual ap create/delete */
 	struct ieee80211vap*	(*ic_vap_create)(struct ieee80211com *,
@@ -669,7 +669,8 @@ ieee80211_radiotap_active(const struct i
 static __inline int
 ieee80211_radiotap_active_vap(const struct ieee80211vap *vap)
 {
-	return (vap->iv_flags_ext & IEEE80211_FEXT_BPF) != 0;
+	return (vap->iv_flags_ext & IEEE80211_FEXT_BPF) ||
+	    vap->iv_ic->ic_montaps != 0;
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906020033.n520XSbb097397>