netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets.
@ 2010-11-10  1:09 Jesse Gross
  2010-11-10  1:09 ` [PATCH net-2.6 2/3] bnx2x: Look inside vlan when determining checksum proto Jesse Gross
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jesse Gross @ 2010-11-10  1:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Hao Zheng

From: Hao Zheng <hzheng@nicira.com>

Depending on how a packet is vlan tagged (i.e. hardware accelerated or
not), the encapsulated protocol is stored in different locations.  This
provides a consistent method of accessing that protocol, which is needed
by drivers, security checks, etc.

Signed-off-by: Hao Zheng <hzheng@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
 include/linux/if_vlan.h |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index c2f3a72..ee06c52 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -339,6 +339,26 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
 	}
 }
 
+/**
+ * vlan_get_protocol - get protocol EtherType.
+ * @skb: skbuff to query
+ *
+ * Returns the EtherType of the packet, regardless of whether it is
+ * vlan encapsulated (normal or hardware accelerated) or not.
+ */
+static inline __be16 vlan_get_protocol(struct sk_buff *skb)
+{
+	__be16 protocol = 0;
+
+	if (vlan_tx_tag_present(skb) ||
+	     skb->protocol != cpu_to_be16(ETH_P_8021Q))
+		protocol = skb->protocol;
+	else if (likely(pskb_may_pull(skb, VLAN_ETH_HLEN)))
+		protocol = ((const struct vlan_ethhdr *)skb->data)->
+			   h_vlan_encapsulated_proto;
+
+	return protocol;
+}
 #endif /* __KERNEL__ */
 
 /* VLAN IOCTLs are found in sockios.h */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-2.6 2/3] bnx2x: Look inside vlan when determining checksum proto.
  2010-11-10  1:09 [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Jesse Gross
@ 2010-11-10  1:09 ` Jesse Gross
  2010-11-10  1:09 ` [PATCH net-2.6 3/3] ixgbe: Look inside vlan when determining offload protocol Jesse Gross
  2010-11-10  5:54 ` [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Stephen Hemminger
  2 siblings, 0 replies; 5+ messages in thread
From: Jesse Gross @ 2010-11-10  1:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Hao Zheng, Eilon Greenstein

From: Hao Zheng <hzheng@nicira.com>

Currently the skb->protocol field is used to setup checksum
offloading on transmit for the correct protocol.  However, if
vlan offloading is disabled or otherwise not used, the protocol
field will be ETH_P_8021Q, not the actual protocol.  This will
cause the checksum to be not computed correctly, even though the
hardware is capable of looking inside vlan tags.  Instead,
look inside the header if necessary to determine the correct
protocol type.

To some extent this fixes a regression from 2.6.36 because it
was previously not possible to disable vlan offloading and this
error case was not exposed.

Signed-off-by: Hao Zheng <hzheng@nicira.com>
CC: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
 drivers/net/bnx2x/bnx2x_cmn.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 459614d..94d5f59 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -1680,7 +1680,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
 		rc = XMIT_PLAIN;
 
 	else {
-		if (skb->protocol == htons(ETH_P_IPV6)) {
+		if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) {
 			rc = XMIT_CSUM_V6;
 			if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
 				rc |= XMIT_CSUM_TCP;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-2.6 3/3] ixgbe: Look inside vlan when determining offload protocol.
  2010-11-10  1:09 [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Jesse Gross
  2010-11-10  1:09 ` [PATCH net-2.6 2/3] bnx2x: Look inside vlan when determining checksum proto Jesse Gross
@ 2010-11-10  1:09 ` Jesse Gross
  2010-11-10  5:54 ` [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Stephen Hemminger
  2 siblings, 0 replies; 5+ messages in thread
From: Jesse Gross @ 2010-11-10  1:09 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, Hao Zheng, Jeff Kirsher, Alex Duyck, Jesse Brandeburg

From: Hao Zheng <hzheng@nicira.com>

Currently the skb->protocol field is used to setup various
offloading parameters on transmit for the correct protocol.
However, if vlan offloading is disabled or otherwise not used,
the protocol field will be ETH_P_8021Q, not the actual protocol.
This will cause the offloading to be not performed correctly,
even though the hardware is capable of looking inside vlan tags.
Instead, look inside the header if necessary to determine the
correct protocol type.

To some extent this fixes a regression from 2.6.36 because it
was previously not possible to disable vlan offloading and this
error case was not exposed.

Signed-off-by: Hao Zheng <hzheng@nicira.com>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
CC: Alex Duyck <alexander.h.duyck@intel.com>
CC: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
 drivers/net/ixgbe/ixgbe_main.c |   60 +++++++++++++++++++++------------------
 1 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 2bd3eb4..fbad4d8 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -764,8 +764,9 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 #ifdef IXGBE_FCOE
 				/* adjust for FCoE Sequence Offload */
 				if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
-				    && (skb->protocol == htons(ETH_P_FCOE)) &&
-				    skb_is_gso(skb)) {
+				    && skb_is_gso(skb)
+				    && vlan_get_protocol(skb) ==
+				    htons(ETH_P_FCOE)) {
 					hlen = skb_transport_offset(skb) +
 						sizeof(struct fc_frame_header) +
 						sizeof(struct fcoe_crc_eof);
@@ -5823,7 +5824,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
 
 static int ixgbe_tso(struct ixgbe_adapter *adapter,
 		     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
-		     u32 tx_flags, u8 *hdr_len)
+		     u32 tx_flags, u8 *hdr_len, __be16 protocol)
 {
 	struct ixgbe_adv_tx_context_desc *context_desc;
 	unsigned int i;
@@ -5841,7 +5842,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
 		l4len = tcp_hdrlen(skb);
 		*hdr_len += l4len;
 
-		if (skb->protocol == htons(ETH_P_IP)) {
+		if (protocol == htons(ETH_P_IP)) {
 			struct iphdr *iph = ip_hdr(skb);
 			iph->tot_len = 0;
 			iph->check = 0;
@@ -5880,7 +5881,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
 		type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
 				   IXGBE_ADVTXD_DTYP_CTXT);
 
-		if (skb->protocol == htons(ETH_P_IP))
+		if (protocol == htons(ETH_P_IP))
 			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
 		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
 		context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
@@ -5906,16 +5907,10 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
 	return false;
 }
 
-static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb)
+static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb,
+		      __be16 protocol)
 {
 	u32 rtn = 0;
-	__be16 protocol;
-
-	if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
-		protocol = ((const struct vlan_ethhdr *)skb->data)->
-					h_vlan_encapsulated_proto;
-	else
-		protocol = skb->protocol;
 
 	switch (protocol) {
 	case cpu_to_be16(ETH_P_IP):
@@ -5943,7 +5938,7 @@ static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb)
 	default:
 		if (unlikely(net_ratelimit()))
 			e_warn(probe, "partial checksum but proto=%x!\n",
-			       skb->protocol);
+			       protocol);
 		break;
 	}
 
@@ -5952,7 +5947,8 @@ static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb)
 
 static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
 			  struct ixgbe_ring *tx_ring,
-			  struct sk_buff *skb, u32 tx_flags)
+			  struct sk_buff *skb, u32 tx_flags,
+			  __be16 protocol)
 {
 	struct ixgbe_adv_tx_context_desc *context_desc;
 	unsigned int i;
@@ -5981,7 +5977,7 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
 				    IXGBE_ADVTXD_DTYP_CTXT);
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
-			type_tucmd_mlhl |= ixgbe_psum(adapter, skb);
+			type_tucmd_mlhl |= ixgbe_psum(adapter, skb, protocol);
 
 		context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
 		/* use index zero for tx checksum offload */
@@ -6179,7 +6175,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
 }
 
 static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
-		      int queue, u32 tx_flags)
+		      int queue, u32 tx_flags, __be16 protocol)
 {
 	struct ixgbe_atr_input atr_input;
 	struct tcphdr *th;
@@ -6190,7 +6186,7 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
 	u8 l4type = 0;
 
 	/* Right now, we support IPv4 only */
-	if (skb->protocol != htons(ETH_P_IP))
+	if (protocol != htons(ETH_P_IP))
 		return;
 	/* check if we're UDP or TCP */
 	if (iph->protocol == IPPROTO_TCP) {
@@ -6257,10 +6253,13 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 	int txq = smp_processor_id();
-
 #ifdef IXGBE_FCOE
-	if ((skb->protocol == htons(ETH_P_FCOE)) ||
-	    (skb->protocol == htons(ETH_P_FIP))) {
+	__be16 protocol;
+
+	protocol = vlan_get_protocol(skb);
+
+	if ((protocol == htons(ETH_P_FCOE)) ||
+	    (protocol == htons(ETH_P_FIP))) {
 		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
 			txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
 			txq += adapter->ring_feature[RING_F_FCOE].mask;
@@ -6303,6 +6302,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 	int tso;
 	int count = 0;
 	unsigned int f;
+	__be16 protocol;
+
+	protocol = vlan_get_protocol(skb);
 
 	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= vlan_tx_tag_get(skb);
@@ -6323,8 +6325,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 	/* for FCoE with DCB, we force the priority to what
 	 * was specified by the switch */
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
-	    (skb->protocol == htons(ETH_P_FCOE) ||
-	     skb->protocol == htons(ETH_P_FIP))) {
+	    (protocol == htons(ETH_P_FCOE) ||
+	     protocol == htons(ETH_P_FIP))) {
 #ifdef CONFIG_IXGBE_DCB
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 			tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK
@@ -6334,7 +6336,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 		}
 #endif
 		/* flag for FCoE offloads */
-		if (skb->protocol == htons(ETH_P_FCOE))
+		if (protocol == htons(ETH_P_FCOE))
 			tx_flags |= IXGBE_TX_FLAGS_FCOE;
 	}
 #endif
@@ -6368,9 +6370,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 			tx_flags |= IXGBE_TX_FLAGS_FSO;
 #endif /* IXGBE_FCOE */
 	} else {
-		if (skb->protocol == htons(ETH_P_IP))
+		if (protocol == htons(ETH_P_IP))
 			tx_flags |= IXGBE_TX_FLAGS_IPV4;
-		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len);
+		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len,
+				protocol);
 		if (tso < 0) {
 			dev_kfree_skb_any(skb);
 			return NETDEV_TX_OK;
@@ -6378,7 +6381,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 
 		if (tso)
 			tx_flags |= IXGBE_TX_FLAGS_TSO;
-		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
+		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags,
+				       protocol) &&
 			 (skb->ip_summed == CHECKSUM_PARTIAL))
 			tx_flags |= IXGBE_TX_FLAGS_CSUM;
 	}
@@ -6392,7 +6396,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev
 			     test_bit(__IXGBE_FDIR_INIT_DONE,
 				      &tx_ring->reinit_state)) {
 				ixgbe_atr(adapter, skb, tx_ring->queue_index,
-					  tx_flags);
+					  tx_flags, protocol);
 				tx_ring->atr_count = 0;
 			}
 		}
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets.
  2010-11-10  1:09 [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Jesse Gross
  2010-11-10  1:09 ` [PATCH net-2.6 2/3] bnx2x: Look inside vlan when determining checksum proto Jesse Gross
  2010-11-10  1:09 ` [PATCH net-2.6 3/3] ixgbe: Look inside vlan when determining offload protocol Jesse Gross
@ 2010-11-10  5:54 ` Stephen Hemminger
  2010-11-10  7:18   ` Jesse Gross
  2 siblings, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2010-11-10  5:54 UTC (permalink / raw)
  To: Jesse Gross; +Cc: David Miller, netdev, Hao Zheng

On Tue,  9 Nov 2010 17:09:02 -0800
Jesse Gross <jesse@nicira.com> wrote:

> From: Hao Zheng <hzheng@nicira.com>
> 
> Depending on how a packet is vlan tagged (i.e. hardware accelerated or
> not), the encapsulated protocol is stored in different locations.  This
> provides a consistent method of accessing that protocol, which is needed
> by drivers, security checks, etc.
> 
> Signed-off-by: Hao Zheng <hzheng@nicira.com>
> Signed-off-by: Jesse Gross <jesse@nicira.com>
> ---
>  include/linux/if_vlan.h |   20 ++++++++++++++++++++
>  1 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
> index c2f3a72..ee06c52 100644
> --- a/include/linux/if_vlan.h
> +++ b/include/linux/if_vlan.h
> @@ -339,6 +339,26 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
>  	}
>  }
>  
> +/**
> + * vlan_get_protocol - get protocol EtherType.
> + * @skb: skbuff to query
> + *
> + * Returns the EtherType of the packet, regardless of whether it is
> + * vlan encapsulated (normal or hardware accelerated) or not.
> + */
> +static inline __be16 vlan_get_protocol(struct sk_buff *skb)
> +{
> +	__be16 protocol = 0;
> +
> +	if (vlan_tx_tag_present(skb) ||
> +	     skb->protocol != cpu_to_be16(ETH_P_8021Q))
> +		protocol = skb->protocol;
> +	else if (likely(pskb_may_pull(skb, VLAN_ETH_HLEN)))
> +		protocol = ((const struct vlan_ethhdr *)skb->data)->
> +			   h_vlan_encapsulated_proto;
> +
> +	return protocol;
> +}

This this calls pskb_may_pull, which modifies the skb data
offsets and therefore could invalidate any callers pointers
to ip header or other fields.
Therefore you will need to audit all callers of this function!

Also, your code doesn't handle the case of too small a frame (VLAN header only).



-- 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets.
  2010-11-10  5:54 ` [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Stephen Hemminger
@ 2010-11-10  7:18   ` Jesse Gross
  0 siblings, 0 replies; 5+ messages in thread
From: Jesse Gross @ 2010-11-10  7:18 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev, Hao Zheng

On Tue, Nov 9, 2010 at 9:54 PM, Stephen Hemminger <shemminger@vyatta.com> wrote:
> On Tue,  9 Nov 2010 17:09:02 -0800
> Jesse Gross <jesse@nicira.com> wrote:
>
>> From: Hao Zheng <hzheng@nicira.com>
>>
>> Depending on how a packet is vlan tagged (i.e. hardware accelerated or
>> not), the encapsulated protocol is stored in different locations.  This
>> provides a consistent method of accessing that protocol, which is needed
>> by drivers, security checks, etc.
>>
>> Signed-off-by: Hao Zheng <hzheng@nicira.com>
>> Signed-off-by: Jesse Gross <jesse@nicira.com>
>> ---
>>  include/linux/if_vlan.h |   20 ++++++++++++++++++++
>>  1 files changed, 20 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
>> index c2f3a72..ee06c52 100644
>> --- a/include/linux/if_vlan.h
>> +++ b/include/linux/if_vlan.h
>> @@ -339,6 +339,26 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
>>       }
>>  }
>>
>> +/**
>> + * vlan_get_protocol - get protocol EtherType.
>> + * @skb: skbuff to query
>> + *
>> + * Returns the EtherType of the packet, regardless of whether it is
>> + * vlan encapsulated (normal or hardware accelerated) or not.
>> + */
>> +static inline __be16 vlan_get_protocol(struct sk_buff *skb)
>> +{
>> +     __be16 protocol = 0;
>> +
>> +     if (vlan_tx_tag_present(skb) ||
>> +          skb->protocol != cpu_to_be16(ETH_P_8021Q))
>> +             protocol = skb->protocol;
>> +     else if (likely(pskb_may_pull(skb, VLAN_ETH_HLEN)))
>> +             protocol = ((const struct vlan_ethhdr *)skb->data)->
>> +                        h_vlan_encapsulated_proto;
>> +
>> +     return protocol;
>> +}
>
> This this calls pskb_may_pull, which modifies the skb data
> offsets and therefore could invalidate any callers pointers
> to ip header or other fields.
> Therefore you will need to audit all callers of this function!

That's a good point.  I switched it to use skb_header_pointer()
instead, which is probably more efficient anyways and avoids the
potential for a problem.

>
> Also, your code doesn't handle the case of too small a frame (VLAN header only).

The goal is to get equivalence to checking skb->protocol, except to
handle vlan accelerated vs non-accelerated consistently.  In this
case, the caller would need to check the length of the protocol header
as appropriate.  If the packet claims to be a vlan frame and the
length is less than the size of a vlan header then we'll return 0,
which should be sufficient to avoid any protocol processing.

Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-11-10  7:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-10  1:09 [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Jesse Gross
2010-11-10  1:09 ` [PATCH net-2.6 2/3] bnx2x: Look inside vlan when determining checksum proto Jesse Gross
2010-11-10  1:09 ` [PATCH net-2.6 3/3] ixgbe: Look inside vlan when determining offload protocol Jesse Gross
2010-11-10  5:54 ` [PATCH net-2.6 1/3] vlan: Add function to retrieve EtherType from vlan packets Stephen Hemminger
2010-11-10  7:18   ` Jesse Gross

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).