Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Apr 2004 12:59:35 +0100
From:      Bruce M Simpson <bms@spc.org>
To:        freebsd-net@FreeBSD.org
Subject:   [PATCH] Add multicast-promiscuous workaround to wi(4), net80211
Message-ID:  <20040408115935.GH14073@empiric.dek.spc.org>

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

--s9fJI615cBHmzTOP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Please review this patch and synopsis; all comments are appreciated.

Synopsis: wi(4) hardware does not natively support IFF_ALLMULTI.

Background:
ConsumeX is a community-owned and operated wireless network collective based
in South East London. Multicast streaming is a highly desirable feature
for this fast-growing network.

Problem Description:
Multicast routing from the wire requires that the hardware supports the
notion of IFF_ALLMULTI, that is, multicast-promiscuous mode -- the ability
to receive all multicast frames but not all unicast ones.

PRISM2 and Hermes based hardware does not have an IFF_ALLMULTI flag. Hacks
such as setting the first multicast hash filter entry to all-ones (0xFFFFFF)
do not work and are not documented anywhere to the best of my knowledge.

The workaround is to put the interface into hardware-promiscuous mode when
IFF_ALLMULTI is requested, and add logic to the net80211 layer to silently
drop packets which are not destined for the station or any given multicast
Ethernet address, based on the presence of a new property,
IEEE80211_C_NO_ALLMULTI which indicates that the hardware suffers from
this particular limitation.

This patch has only been tested in IBSS mode, the logic for STA mode will
be different; sadly, none of this is likely to work with HostAP.

Changed Files:
src/sys/dev/wi/if_wi.c
src/sys/net80211/ieee80211_input.c
src/sys/net80211/ieee80211_var.h

Sponsored by: spc.org

Regards,
BMS

--s9fJI615cBHmzTOP
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="prism2-allmulti.col.patch"

Generated by cvsdiffcoll on Thu  8 Apr 2004 12:56:45 BST

Index: src/sys/dev/wi/if_wi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/wi/if_wi.c,v
retrieving revision 1.164
diff -u -u -r1.164 if_wi.c
--- src/sys/dev/wi/if_wi.c	20 Mar 2004 19:57:47 -0000	1.164
+++ src/sys/dev/wi/if_wi.c	8 Apr 2004 11:56:42 -0000
@@ -310,7 +310,8 @@
 
 	ic->ic_phytype = IEEE80211_T_DS;
 	ic->ic_opmode = IEEE80211_M_STA;
-	ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO;
+	ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO |
+	    IEEE80211_C_NO_ALLMULTI;
 	ic->ic_state = IEEE80211_S_INIT;
 
 	/*
@@ -1095,11 +1096,23 @@
 		 * Can't do promisc and hostap at the same time.  If all that's
 		 * changing is the promisc flag, try to short-circuit a call to
 		 * wi_init() by just setting PROMISC in the hardware.
+		 *
+		 * IFF_ALLMULTI is a special case which is handled first,
+		 * as this class of hardware does not have promiscuous
+		 * multicast support; this requires setting hardware
+		 * promiscuous mode and then discarding unwanted frames
+		 * from within the net80211 layer.
 		 */
 		if (ifp->if_flags & IFF_UP) {
 			if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
 			    ifp->if_flags & IFF_RUNNING) {
-				if (ifp->if_flags & IFF_PROMISC &&
+				if (ifp->if_flags & IFF_ALLMULTI &&
+				    !(sc->sc_if_flags & IFF_ALLMULTI)) {
+					wi_write_val(sc, WI_RID_PROMISC, 1);
+				} else if (!(ifp->if_flags & IFF_ALLMULTI) &&
+				    sc->sc_if_flags & IFF_ALLMULTI) {
+					wi_write_val(sc, WI_RID_PROMISC, 0);
+				} else if (ifp->if_flags & IFF_PROMISC &&
 				    !(sc->sc_if_flags & IFF_PROMISC)) {
 					wi_write_val(sc, WI_RID_PROMISC, 1);
 				} else if (!(ifp->if_flags & IFF_PROMISC) &&
Index: src/sys/net80211/ieee80211_input.c
===================================================================
RCS file: /home/ncvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.13
diff -u -u -r1.13 ieee80211_input.c
--- src/sys/net80211/ieee80211_input.c	15 Jan 2004 08:44:27 -0000	1.13
+++ src/sys/net80211/ieee80211_input.c	8 Apr 2004 11:12:12 -0000
@@ -208,6 +208,21 @@
 				ic->ic_stats.is_rx_wrongdir++;
 				goto out;
 			}
+			/*
+			 * If the hardware does not support multicast
+			 * promiscuous mode, it will have been forced to
+			 * 'full' promiscuous mode. Discard frames which
+			 * are not destined for us, if we are not in
+			 * the 'full' promiscuous mode at the ifnet layer.
+			 */
+			if ((ifp->if_flags & IFF_ALLMULTI) &&
+			    !(ifp->if_flags & IFF_PROMISC) &&
+			    (ic->ic_caps & IEEE80211_C_NO_ALLMULTI) &&
+			    !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
+			    !IEEE80211_ADDR_EQ(wh->i_addr1, ic->ic_myaddr)) {
+				ic->ic_stats.is_rx_wrongdir++;
+				goto out;
+			}
 			break;
 		case IEEE80211_M_HOSTAP:
 			if (dir != IEEE80211_FC1_DIR_TODS) {
Index: src/sys/net80211/ieee80211_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.11
diff -u -u -r1.11 ieee80211_var.h
--- src/sys/net80211/ieee80211_var.h	15 Jan 2004 08:44:27 -0000	1.11
+++ src/sys/net80211/ieee80211_var.h	8 Apr 2004 10:44:08 -0000
@@ -239,6 +239,7 @@
 #define	IEEE80211_C_SHPREAMBLE	0x00000100	/* CAPABILITY: short preamble */
 #define	IEEE80211_C_MONITOR	0x00000200	/* CAPABILITY: monitor mode */
 #define	IEEE80211_C_RCVMGT	0x00000400	/* CAPABILITY: rcv mgt frames */
+#define	IEEE80211_C_NO_ALLMULTI	0x00001000	/* CAPABILITY: no ALLMULTI */
 
 /* flags for ieee80211_fix_rate() */
 #define	IEEE80211_F_DOSORT	0x00000001	/* sort rate list */

--s9fJI615cBHmzTOP--



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