Yes it did the trick - Re[3]: Re[2]: em0, VLAN and bpf(?) trouble w/RELENG_5

Robert Watson rwatson at freebsd.org
Sat Nov 13 04:38:48 PST 2004


On Thu, 11 Nov 2004, Robert Watson wrote:

> That patch excluded the addition of a new variable to the adapter
> structure in if_em.h.  Full patch below. 

FYI I have merged this patch to CVS HEAD; I will merge it to the RELENG_5
branch after it's settled for a few days, and then request permission to
merge to the RELENG_5_3 errata branch for inclusion there after further
settling and testing.  I've had several positive reports back, but would
appreciate any additional testing of the change as committed to HEAD.

Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
robert at fledge.watson.org      Principal Research Scientist, McAfee Research


> ==== //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