All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header
@ 2013-02-22  9:32 Cong Wang
  2013-02-22  9:32 ` [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers Cong Wang
  2013-02-23  1:04 ` [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Jesse Gross
  0 siblings, 2 replies; 5+ messages in thread
From: Cong Wang @ 2013-02-22  9:32 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Jesse Gross, Cong Wang

From: Cong Wang <amwang@redhat.com>

In vlan_insert_tag(), we insert a 4-byte VLAN header _after_
mac header:

        memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
        ...
        veth->h_vlan_proto = htons(ETH_P_8021Q);
        ...
        veth->h_vlan_TCI = htons(vlan_tci);

so after it, we should recompute the checksum to include these 4 bytes.
skb->data still points to the mac header, therefore VLAN header is at
(2 * ETH_ALEN = 12) bytes after it, not (ETH_HLEN = 14) bytes.

This can also be observed via tcpdump:

         0x0000:  ffff ffff ffff 5254 005d 6f6e 8100 000a
         0x0010:  0806 0001 0800 0604 0001 5254 005d 6f6e
         0x0020:  c0a8 026e 0000 0000 0000 c0a8 0282

Similar for __pop_vlan_tci(), the vlan header we remove is the one
overwritten in:

	memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN);

Therefore the VLAN_HLEN = 4 bytes after 2 * ETH_ALEN is the part
we want to sub from checksum.

Cc: David S. Miller <davem@davemloft.net>
Cc: Jesse Gross <jesse@nicira.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/openvswitch/actions.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index ac2defe..d4d5363 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -58,7 +58,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 
 	if (skb->ip_summed == CHECKSUM_COMPLETE)
 		skb->csum = csum_sub(skb->csum, csum_partial(skb->data
-					+ ETH_HLEN, VLAN_HLEN, 0));
+					+ (2 * ETH_ALEN), VLAN_HLEN, 0));
 
 	vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
 	*current_tci = vhdr->h_vlan_TCI;
@@ -115,7 +115,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
 
 		if (skb->ip_summed == CHECKSUM_COMPLETE)
 			skb->csum = csum_add(skb->csum, csum_partial(skb->data
-					+ ETH_HLEN, VLAN_HLEN, 0));
+					+ (2 * ETH_ALEN), VLAN_HLEN, 0));
 
 	}
 	__vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
-- 
1.7.7.6

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

* [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers
  2013-02-22  9:32 [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Cong Wang
@ 2013-02-22  9:32 ` Cong Wang
  2013-02-23  1:05   ` Jesse Gross
  2013-02-23  1:04 ` [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Jesse Gross
  1 sibling, 1 reply; 5+ messages in thread
From: Cong Wang @ 2013-02-22  9:32 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Jesse Gross, Cong Wang

From: Cong Wang <amwang@redhat.com>

There are two places to call vlan_set_encap_proto():
vlan_untag() and __pop_vlan_tci().

vlan_untag() assumes skb->data points after mac addr, otherwise
the following code

        vhdr = (struct vlan_hdr *) skb->data;
        vlan_tci = ntohs(vhdr->h_vlan_TCI);
        __vlan_hwaccel_put_tag(skb, vlan_tci);

        skb_pull_rcsum(skb, VLAN_HLEN);

won't be correct. But __pop_vlan_tci() assumes points _before_
mac addr.

In vlan_set_encap_proto(), it looks for some magic L2 value
after mac addr:

        rawp = skb->data;
        if (*(unsigned short *) rawp == 0xFFFF)
	...

Therefore __pop_vlan_tci() is obviously wrong.

A quick fix is avoiding using skb->data in vlan_set_encap_proto(),
use 'vhdr+1' is always correct in both cases.

Cc: David S. Miller <davem@davemloft.net>
Cc: Jesse Gross <jesse@nicira.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/linux/if_vlan.h |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index d06cc5c..218a3b6 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -331,7 +331,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
 					struct vlan_hdr *vhdr)
 {
 	__be16 proto;
-	unsigned char *rawp;
+	unsigned short *rawp;
 
 	/*
 	 * Was a VLAN packet, grab the encapsulated protocol, which the layer
@@ -344,8 +344,8 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
 		return;
 	}
 
-	rawp = skb->data;
-	if (*(unsigned short *) rawp == 0xFFFF)
+	rawp = (unsigned short *)(vhdr + 1);
+	if (*rawp == 0xFFFF)
 		/*
 		 * This is a magic hack to spot IPX packets. Older Novell
 		 * breaks the protocol design and runs IPX over 802.3 without
-- 
1.7.7.6

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

* Re: [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header
  2013-02-22  9:32 [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Cong Wang
  2013-02-22  9:32 ` [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers Cong Wang
@ 2013-02-23  1:04 ` Jesse Gross
  1 sibling, 0 replies; 5+ messages in thread
From: Jesse Gross @ 2013-02-23  1:04 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David S. Miller

On Fri, Feb 22, 2013 at 1:32 AM, Cong Wang <amwang@redhat.com> wrote:
> From: Cong Wang <amwang@redhat.com>
>
> In vlan_insert_tag(), we insert a 4-byte VLAN header _after_
> mac header:
>
>         memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
>         ...
>         veth->h_vlan_proto = htons(ETH_P_8021Q);
>         ...
>         veth->h_vlan_TCI = htons(vlan_tci);
>
> so after it, we should recompute the checksum to include these 4 bytes.
> skb->data still points to the mac header, therefore VLAN header is at
> (2 * ETH_ALEN = 12) bytes after it, not (ETH_HLEN = 14) bytes.
>
> This can also be observed via tcpdump:
>
>          0x0000:  ffff ffff ffff 5254 005d 6f6e 8100 000a
>          0x0010:  0806 0001 0800 0604 0001 5254 005d 6f6e
>          0x0020:  c0a8 026e 0000 0000 0000 c0a8 0282
>
> Similar for __pop_vlan_tci(), the vlan header we remove is the one
> overwritten in:
>
>         memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN);
>
> Therefore the VLAN_HLEN = 4 bytes after 2 * ETH_ALEN is the part
> we want to sub from checksum.
>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Jesse Gross <jesse@nicira.com>
> Signed-off-by: Cong Wang <amwang@redhat.com>

Applied, thanks.

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

* Re: [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers
  2013-02-22  9:32 ` [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers Cong Wang
@ 2013-02-23  1:05   ` Jesse Gross
  2013-02-24  2:01     ` David Miller
  0 siblings, 1 reply; 5+ messages in thread
From: Jesse Gross @ 2013-02-23  1:05 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David S. Miller

On Fri, Feb 22, 2013 at 1:32 AM, Cong Wang <amwang@redhat.com> wrote:
> From: Cong Wang <amwang@redhat.com>
>
> There are two places to call vlan_set_encap_proto():
> vlan_untag() and __pop_vlan_tci().
>
> vlan_untag() assumes skb->data points after mac addr, otherwise
> the following code
>
>         vhdr = (struct vlan_hdr *) skb->data;
>         vlan_tci = ntohs(vhdr->h_vlan_TCI);
>         __vlan_hwaccel_put_tag(skb, vlan_tci);
>
>         skb_pull_rcsum(skb, VLAN_HLEN);
>
> won't be correct. But __pop_vlan_tci() assumes points _before_
> mac addr.
>
> In vlan_set_encap_proto(), it looks for some magic L2 value
> after mac addr:
>
>         rawp = skb->data;
>         if (*(unsigned short *) rawp == 0xFFFF)
>         ...
>
> Therefore __pop_vlan_tci() is obviously wrong.
>
> A quick fix is avoiding using skb->data in vlan_set_encap_proto(),
> use 'vhdr+1' is always correct in both cases.
>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Jesse Gross <jesse@nicira.com>
> Signed-off-by: Cong Wang <amwang@redhat.com>

Acked-by: Jesse Gross <jesse@nicira.com>

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

* Re: [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers
  2013-02-23  1:05   ` Jesse Gross
@ 2013-02-24  2:01     ` David Miller
  0 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2013-02-24  2:01 UTC (permalink / raw)
  To: jesse; +Cc: amwang, netdev

From: Jesse Gross <jesse@nicira.com>
Date: Fri, 22 Feb 2013 17:05:01 -0800

> On Fri, Feb 22, 2013 at 1:32 AM, Cong Wang <amwang@redhat.com> wrote:
>> From: Cong Wang <amwang@redhat.com>
>>
>> There are two places to call vlan_set_encap_proto():
>> vlan_untag() and __pop_vlan_tci().
>>
>> vlan_untag() assumes skb->data points after mac addr, otherwise
>> the following code
>>
>>         vhdr = (struct vlan_hdr *) skb->data;
>>         vlan_tci = ntohs(vhdr->h_vlan_TCI);
>>         __vlan_hwaccel_put_tag(skb, vlan_tci);
>>
>>         skb_pull_rcsum(skb, VLAN_HLEN);
>>
>> won't be correct. But __pop_vlan_tci() assumes points _before_
>> mac addr.
>>
>> In vlan_set_encap_proto(), it looks for some magic L2 value
>> after mac addr:
>>
>>         rawp = skb->data;
>>         if (*(unsigned short *) rawp == 0xFFFF)
>>         ...
>>
>> Therefore __pop_vlan_tci() is obviously wrong.
>>
>> A quick fix is avoiding using skb->data in vlan_set_encap_proto(),
>> use 'vhdr+1' is always correct in both cases.
>>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: Jesse Gross <jesse@nicira.com>
>> Signed-off-by: Cong Wang <amwang@redhat.com>
> 
> Acked-by: Jesse Gross <jesse@nicira.com>

Applied, thanks.

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

end of thread, other threads:[~2013-02-24  2:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-22  9:32 [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Cong Wang
2013-02-22  9:32 ` [PATCH 2/2] vlan: adjust vlan_set_encap_proto() for its callers Cong Wang
2013-02-23  1:05   ` Jesse Gross
2013-02-24  2:01     ` David Miller
2013-02-23  1:04 ` [PATCH 1/2] openvswitch: fix the calculation of checksum for vlan header Jesse Gross

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.