diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index eb9fed003c85..1b973fec4a8a 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -604,7 +604,8 @@ ether_demux(struct ifnet *ifp, struct mbuf *m) #endif if (!(BDG_ACTIVE(ifp)) && - !(ether_type == ETHERTYPE_VLAN && ifp->if_nvlans > 0)) { + !((ether_type == ETHERTYPE_VLAN || m->m_flags & M_VLANTAG) && + ifp->if_nvlans > 0)) { /* * Discard packet if upper layers shouldn't see it because it * was unicast to a different Ethernet address. If the driver @@ -618,7 +619,7 @@ ether_demux(struct ifnet *ifp, struct mbuf *m) * it's undesired. */ if ((ifp->if_flags & IFF_PROMISC) != 0 - && (eh->ether_dhost[0] & 1) == 0 + && !ETHER_IS_MULTICAST(eh->ether_dhost) && bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0 && (ifp->if_flags & IFF_PPROMISC) == 0) { @@ -657,8 +658,7 @@ post_stats: * Check to see if the device performed the VLAN decapsulation and * provided us with the tag. */ - if (m_tag_first(m) != NULL && - m_tag_locate(m, MTAG_VLAN, MTAG_VLAN_TAG, NULL) != NULL) { + if (m->m_flags & M_VLANTAG) { /* * If no VLANs are configured, drop. */ diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 02762b4381c7..d977bc959195 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -563,6 +563,7 @@ vlan_input(struct ifnet *ifp, struct mbuf *m) */ tag = EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag)); m_tag_delete(m, mtag); + m->m_flags &= ~M_VLANTAG; } else { switch (ifp->if_type) { case IFT_ETHER: diff --git a/sys/net/if_vlan_var.h b/sys/net/if_vlan_var.h index b8b9997496eb..11cbf7b20fcf 100644 --- a/sys/net/if_vlan_var.h +++ b/sys/net/if_vlan_var.h @@ -80,8 +80,8 @@ struct vlanreq { * * to mark the packet m with the specified VLAN tag. The last * parameter provides code to execute in case of an error. On - * output the driver should check ifnet to see if any VLANs are - * in use and only then check for a packet tag; this is done with: + * output the driver should check mbuf to see if a VLAN tag is + * present and only then check for a tag; this is done with: * * struct m_tag *mtag; * mtag = VLAN_OUTPUT_TAG(ifp, m); @@ -107,10 +107,11 @@ struct vlanreq { } \ *(u_int *)(mtag+1) = (_t); \ m_tag_prepend((_m), mtag); \ + (_m)->m_flags |= M_VLANTAG; \ } while (0) #define VLAN_OUTPUT_TAG(_ifp, _m) \ - ((_ifp)->if_nvlans != 0 ? \ + ((_m)->m_flags & M_VLANTAG ? \ m_tag_locate((_m), MTAG_VLAN, MTAG_VLAN_TAG, NULL) : NULL) #define VLAN_TAG_VALUE(_mt) (*(u_int *)((_mt)+1)) #endif /* _KERNEL */ diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index d8e84a60c47b..c954f92088af 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -178,6 +178,7 @@ struct mbuf { #define M_FRAG 0x0800 /* packet is a fragment of a larger packet */ #define M_FIRSTFRAG 0x1000 /* packet is first fragment */ #define M_LASTFRAG 0x2000 /* packet is last fragment */ +#define M_VLANTAG 0x10000 /* packet has VLAN tag attached */ /* * External buffer types: identify ext_buf type. @@ -195,7 +196,8 @@ 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_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG|\ + M_VLANTAG) /* * Flags indicating hw checksum support and sw checksum requirements.