Index: if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.571 diff -u -p -r1.571 if.c --- if.c 9 Jan 2019 01:14:21 -0000 1.571 +++ if.c 21 Feb 2019 04:03:44 -0000 @@ -895,11 +895,29 @@ if_ih_remove(struct ifnet *ifp, int (*in } void -if_input_process(struct ifnet *ifp, struct mbuf_list *ml) +if_input_one(struct ifnet *ifp, struct mbuf *m) { - struct mbuf *m; struct ifih *ifih; struct srp_ref sr; + + /* + * Pass this mbuf to all input handlers of its + * interface until it is consumed. + */ + SRPL_FOREACH(ifih, &sr, &ifp->if_inputs, ifih_next) { + if ((*ifih->ifih_input)(ifp, m, ifih->ifih_cookie)) + break; + } + SRPL_LEAVE(&sr); + + if (ifih == NULL) + m_freem(m); +} + +void +if_input_process(struct ifnet *ifp, struct mbuf_list *ml) +{ + struct mbuf *m; int s; if (ml_empty(ml)) @@ -922,20 +940,8 @@ if_input_process(struct ifnet *ifp, stru */ NET_RLOCK(); s = splnet(); - while ((m = ml_dequeue(ml)) != NULL) { - /* - * Pass this mbuf to all input handlers of its - * interface until it is consumed. - */ - SRPL_FOREACH(ifih, &sr, &ifp->if_inputs, ifih_next) { - if ((*ifih->ifih_input)(ifp, m, ifih->ifih_cookie)) - break; - } - SRPL_LEAVE(&sr); - - if (ifih == NULL) - m_freem(m); - } + while ((m = ml_dequeue(ml)) != NULL) + if_input_one(ifp, m); splx(s); NET_RUNLOCK(); } Index: if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.258 diff -u -p -r1.258 if_ethersubr.c --- if_ethersubr.c 18 Feb 2019 03:41:21 -0000 1.258 +++ if_ethersubr.c 21 Feb 2019 04:03:44 -0000 @@ -74,6 +74,7 @@ didn't get a copy, you may request one f */ #include "bpfilter.h" +#include "vlan.h" #include #include @@ -103,6 +104,10 @@ didn't get a copy, you may request one f #include #endif +#if NVLAN > 0 +#include +#endif + #include "pppoe.h" #if NPPPOE > 0 #include @@ -362,6 +367,17 @@ ether_input(struct ifnet *ifp, struct mb ac = (struct arpcom *)ifp; eh = mtod(m, struct ether_header *); + etype = ntohs(eh->ether_type); + + if (ISSET(m->m_flags, M_VLANTAG) || + etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) { +#if NVLAN > 0 + m = vlan_input(ifp, m); + if (m == NULL) + return (1); +#endif + goto dropanyway; + } /* Is the packet for us? */ if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) { @@ -387,15 +403,6 @@ ether_input(struct ifnet *ifp, struct mb m->m_flags |= M_MCAST; ifp->if_imcasts++; } - - /* - * HW vlan tagged packets that were not collected by vlan(4) must - * be dropped now. - */ - if (m->m_flags & M_VLANTAG) - goto dropanyway; - - etype = ntohs(eh->ether_type); switch (etype) { case ETHERTYPE_IP: Index: if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.94 diff -u -p -r1.94 if_var.h --- if_var.h 9 Jan 2019 01:14:21 -0000 1.94 +++ if_var.h 21 Feb 2019 04:03:44 -0000 @@ -334,6 +334,7 @@ void if_start(struct ifnet *); int if_enqueue(struct ifnet *, struct mbuf *); int if_enqueue_ifq(struct ifnet *, struct mbuf *); void if_input(struct ifnet *, struct mbuf_list *); +void if_input_one(struct ifnet *, struct mbuf *); void if_input_process(struct ifnet *, struct mbuf_list *); int if_input_local(struct ifnet *, struct mbuf *, sa_family_t); int if_output_local(struct ifnet *, struct mbuf *, sa_family_t); Index: if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.183 diff -u -p -r1.183 if_vlan.c --- if_vlan.c 15 Feb 2019 13:00:51 -0000 1.183 +++ if_vlan.c 21 Feb 2019 04:03:44 -0000 @@ -83,7 +83,6 @@ void vlanattach(int count); int vlan_clone_create(struct if_clone *, int); int vlan_clone_destroy(struct ifnet *); -int vlan_input(struct ifnet *, struct mbuf *, void *); int vlan_enqueue(struct ifnet *, struct mbuf *); void vlan_start(struct ifqueue *ifq); int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); @@ -335,88 +334,94 @@ vlan_inject(struct mbuf *m, uint16_t typ return (m); } -/* - * vlan_input() returns 1 if it has consumed the packet, 0 otherwise. - */ -int -vlan_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +struct mbuf * +vlan_input(struct ifnet *ifp0, struct mbuf *m) { struct ifvlan *ifv; + struct ifnet *ifp; struct ether_vlan_header *evl; - struct ether_header *eh; SRPL_HEAD(, ifvlan) *tagh, *list; struct srp_ref sr; u_int tag; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); u_int16_t etype; +#if NBPFILTER > 0 + caddr_t if_bpf; +#endif - eh = mtod(m, struct ether_header *); - etype = ntohs(eh->ether_type); - - if (m->m_flags & M_VLANTAG) { + if (ISSET(m->m_flags, M_VLANTAG)) { etype = ETHERTYPE_VLAN; tagh = vlan_tagh; - } else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) { - if (m->m_len < sizeof(*evl) && - (m = m_pullup(m, sizeof(*evl))) == NULL) { - ifp0->if_ierrors++; - return (1); + } else { + if (m->m_len < sizeof(*evl)) { + m = m_pullup(m, sizeof(*evl)); + if (m == NULL) + return (NULL); } evl = mtod(m, struct ether_vlan_header *); - m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); + etype = ntohs(evl->evl_encap_proto); tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; - } else { - /* Skip non-VLAN packets. */ - return (0); + m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); } /* From now on ether_vtag is fine */ tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag); - m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag); - - /* IEEE 802.1p has prio 0 and 1 swapped */ - if (m->m_pkthdr.pf.prio <= 1) - m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio; - list = &tagh[TAG_HASH(tag)]; SRPL_FOREACH(ifv, &sr, list, ifv_list) { - if (ifp0->if_index == ifv->ifv_ifidx0 && tag == ifv->ifv_tag && + if (ifp0->if_index == ifv->ifv_ifidx0 && + tag == ifv->ifv_tag && etype == ifv->ifv_type) break; } - if (ifv == NULL) { - ifp0->if_noproto++; - goto drop; - } + if (ifv == NULL || !ISSET(ifv->ifv_if.if_flags, IFF_RUNNING)) + goto decline; - if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != - (IFF_UP|IFF_RUNNING)) - goto drop; + /* The packet is ours now */ + + m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag); + /* IEEE 802.1p has prio 0 and 1 swapped */ + if (m->m_pkthdr.pf.prio <= 1) + m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio; /* * Having found a valid vlan interface corresponding to * the given source interface and vlan tag, remove the * encapsulation. */ - if (m->m_flags & M_VLANTAG) { - m->m_flags &= ~M_VLANTAG; + if (ISSET(m->m_flags, M_VLANTAG)) { + CLR(m->m_flags, M_VLANTAG); } else { - eh->ether_type = evl->evl_proto; - memmove((char *)eh + EVL_ENCAPLEN, eh, sizeof(*eh)); + memmove((char *)evl + EVL_ENCAPLEN, evl, + offsetof(struct ether_vlan_header, evl_encap_proto)); m_adj(m, EVL_ENCAPLEN); } - ml_enqueue(&ml, m); - if_input(&ifv->ifv_if, &ml); + ifp = &ifv->ifv_if; + counters_pkt(ifp->if_counters, + ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); + + m->m_pkthdr.ph_ifidx = ifp->if_index; + m->m_pkthdr.ph_rtableid = ifp->if_rdomain; + +#if NBPFILTER > 0 + if_bpf = ifp->if_bpf; + if (if_bpf) { + if (bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT)) { + m_freem(m); + goto leave; + } + } +#endif + + if_input_one(ifp, m); +leave: SRPL_LEAVE(&sr); - return (1); + return (NULL); -drop: +decline: SRPL_LEAVE(&sr); - m_freem(m); - return (1); + return (m); } int @@ -440,8 +445,6 @@ vlan_parent_up(struct ifvlan *ifv, struc vlan_multi_apply(ifv, ifp0, SIOCADDMULTI); - if_ih_insert(ifp0, vlan_input, NULL); - return (0); } @@ -560,7 +563,6 @@ vlan_down(struct ifvlan *ifv) ifp0 = if_get(ifv->ifv_ifidx0); if (ifp0 != NULL) { - if_ih_remove(ifp0, vlan_input, NULL); if (ISSET(ifv->ifv_flags, IFVF_PROMISC)) ifpromisc(ifp0, 0); vlan_multi_apply(ifv, ifp0, SIOCDELMULTI); Index: if_vlan_var.h =================================================================== RCS file: /cvs/src/sys/net/if_vlan_var.h,v retrieving revision 1.39 diff -u -p -r1.39 if_vlan_var.h --- if_vlan_var.h 15 Feb 2019 13:00:51 -0000 1.39 +++ if_vlan_var.h 21 Feb 2019 04:03:44 -0000 @@ -85,6 +85,7 @@ struct ifvlan { #define IFVF_LLADDR 0x02 /* don't inherit the parents mac */ struct mbuf *vlan_inject(struct mbuf *, uint16_t, uint16_t); +struct mbuf *vlan_input(struct ifnet *, struct mbuf *); #endif /* _KERNEL */ #endif /* _NET_IF_VLAN_VAR_H_ */