From 03f5ed13f7108351cc2e0b939f4c2f9dc82fead0 Mon Sep 17 00:00:00 2001 From: andre Date: Fri, 29 Sep 2006 21:38:12 +0000 Subject: [PATCH] Back out rev. 1.152 as it was breaking vlan tag insertion when vlan tag stripping was disabled due to being in promisc mode. This is a hardware bug. Update comment to explicitly state the reason the manual vlan tag insertion in this case. See rev. 1.53 for further information as well. Noticed by: jhb --- sys/dev/em/if_em.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 08c92c1d4321..bfabd62b6a2e 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -1474,6 +1474,45 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) } } + /* + * When operating in promiscuous mode, hardware stripping of the + * VLAN tag on receive is disabled. This should not prevent us + * from doing hardware insertion of the VLAN tag here as that + * is controlled by the dma descriptor flags and not the receive + * tag strip setting. Unfortunatly this hardware switches the + * VLAN encapsulation type from 802.1q to ISL when stripping om + * receive is disabled. This means we have to add the vlan + * encapsulation here in the driver, since it will have come down + * from the VLAN layer with a tag instead of a VLAN header. + */ + if ((m_head->m_flags & M_VLANTAG) && adapter->em_insert_vlan_header) { + struct ether_vlan_header *evl; + struct ether_header eh; + + m_head = m_pullup(m_head, sizeof(eh)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } + eh = *mtod(m_head, struct ether_header *); + M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } + m_head = m_pullup(m_head, sizeof(*evl)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } + evl = mtod(m_head, struct ether_vlan_header *); + bcopy(&eh, evl, sizeof(*evl)); + evl->evl_proto = evl->evl_encap_proto; + evl->evl_encap_proto = htons(ETHERTYPE_VLAN); + evl->evl_tag = htons(m_head->m_pkthdr.ether_vtag); + *m_headp = m_head; + } + /* * TSO workaround: * If an mbuf contains only the IP and TCP header we have