From owner-svn-src-head@FreeBSD.ORG Tue Jun 2 00:33:29 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 44287106566C; Tue, 2 Jun 2009 00:33:29 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 317A58FC22; Tue, 2 Jun 2009 00:33:29 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n520XSss097404; Tue, 2 Jun 2009 00:33:28 GMT (envelope-from sam@svn.freebsd.org) Received: (from sam@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n520XSbb097397; Tue, 2 Jun 2009 00:33:28 GMT (envelope-from sam@svn.freebsd.org) Message-Id: <200906020033.n520XSbb097397@svn.freebsd.org> From: Sam Leffler Date: Tue, 2 Jun 2009 00:33:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193292 - head/sys/net80211 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Jun 2009 00:33:29 -0000 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; } /*