goda@ found a regression due to the recent M_PROTO1 change. Apparently gif(4) is using this flag to know that a packet comes from bridge(4) and wants etherip encapsulation.
Instead of hiding another layer-violation (yeah for bridge!) make it obvious. Diff below, any ok? Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.254 diff -u -p -r1.254 if_bridge.c --- net/if_bridge.c 16 Jul 2015 21:14:21 -0000 1.254 +++ net/if_bridge.c 16 Jul 2015 23:13:33 -0000 @@ -91,6 +91,10 @@ #include <net/if_vlan_var.h> #endif +#if NGIF > 0 +#include <net/if_gif.h> +#endif + #include <net/if_bridge.h> /* @@ -1355,6 +1359,7 @@ bridge_input(struct ifnet *ifp, struct m IF_ENQUEUE(&sc->sc_if.if_snd, mc); splx(s); schednetisr(NETISR_BRIDGE); +#if NGIF > 0 if (ifp->if_type == IFT_GIF) { TAILQ_FOREACH(ifl, &sc->sc_iflist, next) { if (ifl->ifp->if_type != IFT_ETHER) @@ -1366,6 +1371,7 @@ bridge_input(struct ifnet *ifp, struct m return (NULL); } } +#endif /* NGIF */ return (m); } @@ -2556,8 +2562,12 @@ bridge_ifenqueue(struct bridge_softc *sc /* Count packets input into the gif from outside */ ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; + + error = gif_encap(ifp, &m, AF_LINK); + if (error) + return (error); } -#endif +#endif /* NGIF */ len = m->m_pkthdr.len; error = if_enqueue(ifp, m); Index: net/if_gif.c =================================================================== RCS file: /cvs/src/sys/net/if_gif.c,v retrieving revision 1.76 diff -u -p -r1.76 if_gif.c --- net/if_gif.c 16 Jul 2015 21:21:49 -0000 1.76 +++ net/if_gif.c 16 Jul 2015 23:09:57 -0000 @@ -169,39 +169,6 @@ gif_start(struct ifnet *ifp) continue; } - /* - * Check if the packet is coming via bridge and needs - * etherip encapsulation or not. bridge(4) directly calls - * the start function and bypasses the if_output function - * so we need to do the encap here. - */ - if (ifp->if_bridgeport && (m->m_flags & M_PROTO1)) { - int error = 0; - /* - * Remove multicast and broadcast flags or encapsulated - * packet ends up as multicast or broadcast packet. - */ - m->m_flags &= ~(M_BCAST|M_MCAST); - switch (sc->gif_psrc->sa_family) { - case AF_INET: - error = in_gif_output(ifp, AF_LINK, &m); - break; -#ifdef INET6 - case AF_INET6: - error = in6_gif_output(ifp, AF_LINK, &m); - break; -#endif - default: - error = EAFNOSUPPORT; - m_freem(m); - break; - } - if (error) - continue; - if (gif_checkloop(ifp, m)) - continue; - } - #if NBPFILTER > 0 if (ifp->if_bpf) { int offset; @@ -279,48 +246,58 @@ gif_start(struct ifnet *ifp) } int -gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, - struct rtentry *rt) +gif_encap(struct ifnet *ifp, struct mbuf **mp, sa_family_t af) { struct gif_softc *sc = (struct gif_softc*)ifp; int error = 0; - - if (!(ifp->if_flags & IFF_UP) || - sc->gif_psrc == NULL || sc->gif_pdst == NULL || - sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) { - m_freem(m); - error = ENETDOWN; - goto end; - } - /* * Remove multicast and broadcast flags or encapsulated packet * ends up as multicast or broadcast packet. */ - m->m_flags &= ~(M_BCAST|M_MCAST); + (*mp)->m_flags &= ~(M_BCAST|M_MCAST); /* * Encapsulate packet. Add IP or IP6 header depending on tunnel AF. */ switch (sc->gif_psrc->sa_family) { case AF_INET: - error = in_gif_output(ifp, dst->sa_family, &m); + error = in_gif_output(ifp, af, mp); break; #ifdef INET6 case AF_INET6: - error = in6_gif_output(ifp, dst->sa_family, &m); + error = in6_gif_output(ifp, af, mp); break; #endif default: - m_freem(m); + m_freem(*mp); error = EAFNOSUPPORT; break; } if (error) + return (error); + + error = gif_checkloop(ifp, *mp); + return (error); +} + +int +gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) +{ + struct gif_softc *sc = (struct gif_softc*)ifp; + int error = 0; + + if (!(ifp->if_flags & IFF_UP) || + sc->gif_psrc == NULL || sc->gif_pdst == NULL || + sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) { + m_freem(m); + error = ENETDOWN; goto end; + } - if ((error = gif_checkloop(ifp, m))) + error = gif_encap(ifp, &m, dst->sa_family); + if (error) goto end; error = if_enqueue(ifp, m); Index: net/if_gif.h =================================================================== RCS file: /cvs/src/sys/net/if_gif.h,v retrieving revision 1.12 diff -u -p -r1.12 if_gif.h --- net/if_gif.h 16 Jul 2015 21:21:49 -0000 1.12 +++ net/if_gif.h 16 Jul 2015 23:09:05 -0000 @@ -47,4 +47,6 @@ struct gif_softc { extern LIST_HEAD(gif_softc_head, gif_softc) gif_softc_list; +int gif_encap(struct ifnet *, struct mbuf **, sa_family_t); + #endif /* _NET_IF_GIF_H_ */