From owner-freebsd-current@FreeBSD.ORG Thu Nov 11 13:35:31 2004 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6EE7D16A4CE for ; Thu, 11 Nov 2004 13:35:31 +0000 (GMT) Received: from fledge.watson.org (fledge.watson.org [204.156.12.50]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0292743D39 for ; Thu, 11 Nov 2004 13:35:31 +0000 (GMT) (envelope-from robert@fledge.watson.org) Received: from fledge.watson.org (localhost [127.0.0.1]) by fledge.watson.org (8.13.1/8.13.1) with ESMTP id iABDYIct098208; Thu, 11 Nov 2004 08:34:18 -0500 (EST) (envelope-from robert@fledge.watson.org) Received: from localhost (robert@localhost)iABDYIaZ098205; Thu, 11 Nov 2004 13:34:18 GMT (envelope-from robert@fledge.watson.org) Date: Thu, 11 Nov 2004 13:34:18 +0000 (GMT) From: Robert Watson X-Sender: robert@fledge.watson.org To: astesin@ukrtelecom.net In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: freebsd-current@freebsd.org cc: mike@sentex.net cc: mib@wnet.ua Subject: Re: Yes it did the trick - Re[3]: Re[2]: em0, VLAN and bpf(?) trouble w/RELENG_5 X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Nov 2004 13:35:31 -0000 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;