On 17/06/15(Wed) 14:07, Martin Pieuchot wrote: > On 08/06/15(Mon) 15:58, Martin Pieuchot wrote: > > Diff below moves bridge_output() to if_output(). It fixes the case I > > already described some weeks ago where you have a physical interface > > in a bridge and a vlan on top of it which is not in the bridge. > > > > It also change the loop prevention code to use M_PROTO1 like in the > > input path. > > > > Tests, comments and oks welcome. > > Updated diff to match the recent if_get() change. I've got one positive > report so far, any ok?
I'm still looking for oks. > > Index: net/if.c > =================================================================== > RCS file: /cvs/src/sys/net/if.c,v > retrieving revision 1.340 > diff -u -p -r1.340 if.c > --- net/if.c 16 Jun 2015 11:09:39 -0000 1.340 > +++ net/if.c 17 Jun 2015 12:01:12 -0000 > @@ -449,6 +449,19 @@ if_output(struct ifnet *ifp, struct mbuf > int s, length, error = 0; > unsigned short mflags; > > +#ifdef DIAGNOSTIC > + if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) { > + printf("%s: trying to send packet on wrong domain. " > + "if %d vs. mbuf %d\n", ifp->if_xname, ifp->if_rdomain, > + rtable_l2(m->m_pkthdr.ph_rtableid)); > + } > +#endif > + > +#if NBRIDGE > 0 > + if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) > + return (bridge_output(ifp, m, NULL, NULL)); > +#endif > + > length = m->m_pkthdr.len; > mflags = m->m_flags; > > Index: net/if_bridge.c > =================================================================== > RCS file: /cvs/src/sys/net/if_bridge.c,v > retrieving revision 1.244 > diff -u -p -r1.244 if_bridge.c > --- net/if_bridge.c 16 Jun 2015 11:09:39 -0000 1.244 > +++ net/if_bridge.c 17 Jun 2015 12:01:12 -0000 > @@ -2635,10 +2635,12 @@ bridge_ifenqueue(struct bridge_softc *sc > { > int error, len; > > + /* Loop prevention. */ > + m->m_flags |= M_PROTO1; > + > #if NGIF > 0 > /* Packet needs etherip encapsulation. */ > if (ifp->if_type == IFT_GIF) { > - m->m_flags |= M_PROTO1; > > /* Count packets input into the gif from outside */ > ifp->if_ipackets++; > Index: net/if_ethersubr.c > =================================================================== > RCS file: /cvs/src/sys/net/if_ethersubr.c,v > retrieving revision 1.205 > diff -u -p -r1.205 if_ethersubr.c > --- net/if_ethersubr.c 16 Jun 2015 11:09:39 -0000 1.205 > +++ net/if_ethersubr.c 17 Jun 2015 12:01:12 -0000 > @@ -181,15 +181,6 @@ ether_output(struct ifnet *ifp, struct m > struct arpcom *ac = (struct arpcom *)ifp; > int error = 0; > > -#ifdef DIAGNOSTIC > - if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) { > - printf("%s: trying to send packet on wrong domain. " > - "if %d vs. mbuf %d, AF %d\n", ifp->if_xname, > - ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid), > - dst->sa_family); > - } > -#endif > - > esrc = ac->ac_enaddr; > > if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) > @@ -276,47 +267,6 @@ ether_output(struct ifnet *ifp, struct m > eh->ether_type = etype; > memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost)); > memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); > - > -#if NBRIDGE > 0 > - /* > - * Interfaces that are bridgeports need special handling for output. > - */ > - if (ifp->if_bridgeport) { > - struct m_tag *mtag; > - > - /* > - * Check if this packet has already been sent out through > - * this bridgeport, in which case we simply send it out > - * without further bridge processing. > - */ > - for (mtag = m_tag_find(m, PACKET_TAG_BRIDGE, NULL); mtag; > - mtag = m_tag_find(m, PACKET_TAG_BRIDGE, mtag)) { > -#ifdef DEBUG > - /* Check that the information is there */ > - if (mtag->m_tag_len != sizeof(caddr_t)) { > - error = EINVAL; > - goto bad; > - } > -#endif > - if (!memcmp(&ifp->if_bridgeport, mtag + 1, > - sizeof(caddr_t))) > - break; > - } > - if (mtag == NULL) { > - /* Attach a tag so we can detect loops */ > - mtag = m_tag_get(PACKET_TAG_BRIDGE, sizeof(caddr_t), > - M_NOWAIT); > - if (mtag == NULL) { > - error = ENOBUFS; > - goto bad; > - } > - memcpy(mtag + 1, &ifp->if_bridgeport, sizeof(caddr_t)); > - m_tag_prepend(m, mtag); > - error = bridge_output(ifp, m, NULL, NULL); > - return (error); > - } > - } > -#endif > > return (if_output(ifp, m)); > bad: > Index: sys/mbuf.h > =================================================================== > RCS file: /cvs/src/sys/sys/mbuf.h,v > retrieving revision 1.192 > diff -u -p -r1.192 mbuf.h > --- sys/mbuf.h 16 Jun 2015 11:09:40 -0000 1.192 > +++ sys/mbuf.h 17 Jun 2015 12:01:12 -0000 > @@ -454,7 +454,6 @@ struct m_tag *m_tag_next(struct mbuf *, > /* Packet tag types */ > #define PACKET_TAG_IPSEC_IN_DONE 0x0001 /* IPsec applied, in */ > #define PACKET_TAG_IPSEC_OUT_DONE 0x0002 /* IPsec applied, out */ > -#define PACKET_TAG_BRIDGE 0x0020 /* Bridge processing done */ > #define PACKET_TAG_GIF 0x0040 /* GIF processing done > */ > #define PACKET_TAG_GRE 0x0080 /* GRE processing done > */ > #define PACKET_TAG_DLT 0x0100 /* data link layer type > */ >