Date: Sat, 10 Feb 2007 21:17:52 +0000 From: Bruce M Simpson <bms@incunabulum.net> To: freebsd-net@freebsd.org Subject: [PATCH] Introduce M_PROMISC to lower part of Ethernet code Message-ID: <45CE3680.2010103@incunabulum.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------030408010207040301060400 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi, Thunderbird keeps crashing whenever I draft these messages, which is frustrating. Can we discuss this change? I would like to get it in as we get the following wins: 1. Potentially cleaner code in ether_demux()/ether_input() 2. Ways of detecting and preventing L2/L3 forwarding loops 3. Being able to do more with promiscuous mode in general e.g. using it to emulate broken IFF_ALLMULTI with network cards which can't support multicast routing properly. Feedback eagerly looked forward to; this is not a complete change; this is strictly development quality at the moment. Regards, BMS --------------030408010207040301060400 Content-Type: text/x-patch; name="promisc2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="promisc2.diff" Index: net/if_ethersubr.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.222 diff -u -p -r1.222 if_ethersubr.c --- net/if_ethersubr.c 24 Dec 2006 08:52:13 -0000 1.222 +++ net/if_ethersubr.c 10 Feb 2007 20:59:39 -0000 @@ -582,6 +582,7 @@ ether_input(struct ifnet *ifp, struct mb if (IFP2AC(ifp)->ac_netgraph != NULL) { KASSERT(ng_ether_input_p != NULL, ("ng_ether_input_p is NULL")); + m->m_flags &= ~M_PROMISC; (*ng_ether_input_p)(ifp, &m); if (m == NULL) return; @@ -598,6 +599,7 @@ ether_input(struct ifnet *ifp, struct mb * at the src/sys/netgraph/ng_ether.c:ng_ether_rcv_upper() */ if (ifp->if_bridge) { + m->m_flags &= ~M_PROMISC; BRIDGE_INPUT(ifp, m); if (m == NULL) return; @@ -634,6 +636,14 @@ ether_demux(struct ifnet *ifp, struct mb if (rule) /* packet was already bridged */ goto post_stats; #endif + /* + * If the frame was received promiscuously, mark it as such. + */ + if ((ifp->if_flags & IFF_PROMISC) && + !ETHER_IS_MULTICAST(eh->ether_dhost) && + bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) { + m->m_flags |= M_PROMISC; + } if (!(ifp->if_bridge) && !((ether_type == ETHERTYPE_VLAN || m->m_flags & M_VLANTAG) && @@ -648,8 +658,10 @@ ether_demux(struct ifnet *ifp, struct mb * evaluation, to see if the carp ether_dhost values break any * of these checks! */ - if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) + if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) { + m->m_flags &= ~M_PROMISC; goto pre_stats; + } #endif /* * Discard packet if upper layers shouldn't see it because it @@ -662,14 +674,16 @@ ether_demux(struct ifnet *ifp, struct mb * give them a chance to consider it as well (e. g. in case * bridging is only active on a VLAN). They will drop it if * it's undesired. + * + * XXX: There is no way this check can be invoked if + * there are no VLANs attached to this parent interface, + * which is likely to cause recursion if we're acting + * as an IP forwarder... */ - if ((ifp->if_flags & IFF_PROMISC) != 0 - && !ETHER_IS_MULTICAST(eh->ether_dhost) - && bcmp(eh->ether_dhost, - IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0 - && (ifp->if_flags & IFF_PPROMISC) == 0) { - m_freem(m); - return; + if ((m->m_flags & M_PROMISC) && + (ifp->if_flags & IFF_PPROMISC) == 0) { + m_freem(m); + return; } } @@ -720,6 +734,7 @@ post_stats: * or drop the packet. */ KASSERT(vlan_input_p != NULL,("ether_input: VLAN not loaded!")); + m->m_flags &= ~M_PROMISC; (*vlan_input_p)(ifp, m); return; } @@ -732,6 +747,7 @@ post_stats: case ETHERTYPE_VLAN: if (ifp->if_vlantrunk != NULL) { KASSERT(vlan_input_p,("ether_input: VLAN not loaded!")); + m->m_flags &= ~M_PROMISC; (*vlan_input_p)(ifp, m); } else { ifp->if_noproto++; Index: sys/mbuf.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mbuf.h,v retrieving revision 1.202 diff -u -p -r1.202 mbuf.h --- sys/mbuf.h 25 Jan 2007 01:05:23 -0000 1.202 +++ sys/mbuf.h 10 Feb 2007 20:59:40 -0000 @@ -182,6 +182,7 @@ struct mbuf { #define M_FIRSTFRAG 0x1000 /* packet is first fragment */ #define M_LASTFRAG 0x2000 /* packet is last fragment */ #define M_VLANTAG 0x10000 /* ether_vtag is valid */ +#define M_PROMISC 0x20000 /* packet was not for us */ /* * External buffer types: identify ext_buf type. @@ -203,7 +204,7 @@ struct mbuf { #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\ M_PROTO3|M_PROTO4|M_PROTO5|M_SKIP_FIREWALL|\ M_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG|\ - M_VLANTAG) + M_VLANTAG|M_PROMISC) /* * Flags to purge when crossing layers. --------------030408010207040301060400--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45CE3680.2010103>