Yes it did the trick - Re[3]: Re[2]: em0, VLAN and bpf(?)
trouble w/RELENG_5
Robert Watson
rwatson at freebsd.org
Thu Nov 11 05:35:31 PST 2004
On Thu, 11 Nov 2004, Robert Watson wrote:
> Yes -- this patch was basically to confirm that it was indeed the
> promiscuous mode toggle of vlan support. Try the attached patch, which
> modifies the if_em driver to track when vlan support is disabled, and to
> prepend a vlan header when that is the case. Still not the final patch,
> since if nothing else I should probably not call it a "workaround" and
> should abstract the vlan prepend behavior for use by other drivers. This
> appears to work properly locally.
>
> I have an e-mail out to the Intel maintainer of the driver asking about
> their preferred solution.
That patch excluded the addition of a new variable to the adapter
structure in if_em.h. Full patch below.
==== //depot/vendor/freebsd/src/sys/dev/em/if_em.c#51 - /zoo/rwatson/p4/vendor/freebsd/src/sys/dev/em/if_em.c ====
@@ -161,7 +161,7 @@
static int em_get_buf(int i, struct adapter *,
struct mbuf *);
static void em_enable_vlans(struct adapter *);
-static int em_encap(struct adapter *, struct mbuf *);
+static int em_encap(struct adapter *, struct mbuf **);
static void em_smartspeed(struct adapter *);
static int em_82547_fifo_workaround(struct adapter *, int);
static void em_82547_update_fifo_head(struct adapter *, int);
@@ -616,7 +616,7 @@
if (m_head == NULL) break;
- if (em_encap(adapter, m_head)) {
+ if (em_encap(adapter, &m_head)) {
ifp->if_flags |= IFF_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
@@ -1176,13 +1176,15 @@
* return 0 on success, positive on failure
**********************************************************************/
static int
-em_encap(struct adapter *adapter, struct mbuf *m_head)
+em_encap(struct adapter *adapter, struct mbuf **m_headp)
{
u_int32_t txd_upper;
u_int32_t txd_lower, txd_used = 0, txd_saved = 0;
int i, j, error;
u_int64_t address;
+ struct mbuf *m_head;
+
/* For 82544 Workaround */
DESC_ARRAY desc_array;
u_int32_t array_elements;
@@ -1198,6 +1200,8 @@
struct em_tx_desc *current_tx_desc = NULL;
struct ifnet *ifp = &adapter->interface_data.ac_if;
+ m_head = *m_headp;
+
/*
* Force a cleanup if number of TX descriptors
* available hits the threshold
@@ -1250,6 +1254,36 @@
mtag = VLAN_OUTPUT_TAG(ifp, m_head);
#endif
+ /*
+ * When operating in promiscuous mode, hardware encapsulation for
+ * packets is disabled. This means we have to add the vlan
+ * encapsulation in the driver, since it will have come down from the
+ * VLAN layer with a tag instead of a VLAN header.
+ */
+ if (mtag != NULL && adapter->em_vlan_tag_workaround) {
+ struct ether_vlan_header *evl;
+ struct ether_header eh;
+
+ m_head = m_pullup(m_head, sizeof(eh));
+ if (m_head == NULL)
+ return (ENOBUFS);
+ eh = *mtod(m_head, struct ether_header *);
+ M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT);
+ if (m_head == NULL)
+ return (ENOBUFS);
+ m_head = m_pullup(m_head, sizeof(*evl));
+ if (m_head == 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(VLAN_TAG_VALUE(mtag));
+ m_tag_delete(m_head, mtag);
+ mtag = NULL;
+ *m_headp = m_head;
+ }
+
i = adapter->next_avail_tx_desc;
if (adapter->pcix_82544) {
txd_saved = i;
@@ -1497,19 +1531,20 @@
if (ifp->if_flags & IFF_PROMISC) {
reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
-
/* Disable VLAN stripping in promiscous mode
* This enables bridging of vlan tagged frames to occur
* and also allows vlan tags to be seen in tcpdump
*/
ctrl &= ~E1000_CTRL_VME;
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
-
+ adapter->em_vlan_tag_workaround = 1;
} else if (ifp->if_flags & IFF_ALLMULTI) {
reg_rctl |= E1000_RCTL_MPE;
reg_rctl &= ~E1000_RCTL_UPE;
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
- }
+ adapter->em_vlan_tag_workaround = 0;
+ } else
+ adapter->em_vlan_tag_workaround = 0;
return;
}
@@ -1526,6 +1561,8 @@
E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
em_enable_vlans(adapter);
+ adapter->em_vlan_tag_workaround = 0;
+
return;
}
==== //depot/vendor/freebsd/src/sys/dev/em/if_em.h#26 - /zoo/rwatson/p4/vendor/freebsd/src/sys/dev/em/if_em.h ====
@@ -346,6 +346,7 @@
int io_rid;
u_int8_t unit;
struct mtx mtx;
+ int em_vlan_tag_workaround;
/* Info about the board itself */
u_int32_t part_num;
More information about the freebsd-current
mailing list