aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-06-04 20:20:02 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-05 01:46:38 -0400
commit7e2b10c1e52ca37fb522be49f4be367f9311d0cd (patch)
tree67fd8a9e9b90f732c45f406df145c8a149d24a53 /net/core
parent77157e1973cbdb8d60bdb0ec749d6014bedc5bd5 (diff)
net: Support for multiple checksums with gso
When creating a GSO packet segment we may need to set more than one checksum in the packet (for instance a TCP checksum and UDP checksum for VXLAN encapsulation). To be efficient, we want to do checksum calculation for any part of the packet at most once. This patch adds csum_start offset to skb_gso_cb. This tracks the starting offset for skb->csum which is initially set in skb_segment. When a protocol needs to compute a transport checksum it calls gso_make_checksum which computes the checksum value from the start of transport header to csum_start and then adds in skb->csum to get the full checksum. skb->csum and csum_start are then updated to reflect the checksum of the resultant packet starting from the transport header. This patch also adds a flag to skbuff, encap_hdr_csum, which is set in *gso_segment fucntions to indicate that a tunnel protocol needs checksum calculation Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/skbuff.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3f6c7e8be8a4..05f4bef2ce12 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2885,7 +2885,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
2885 if (unlikely(!proto)) 2885 if (unlikely(!proto))
2886 return ERR_PTR(-EINVAL); 2886 return ERR_PTR(-EINVAL);
2887 2887
2888 csum = !!can_checksum_protocol(features, proto); 2888 csum = !head_skb->encap_hdr_csum &&
2889 !!can_checksum_protocol(features, proto);
2890
2889 __skb_push(head_skb, doffset); 2891 __skb_push(head_skb, doffset);
2890 headroom = skb_headroom(head_skb); 2892 headroom = skb_headroom(head_skb);
2891 pos = skb_headlen(head_skb); 2893 pos = skb_headlen(head_skb);
@@ -2983,6 +2985,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
2983 nskb->csum = skb_copy_and_csum_bits(head_skb, offset, 2985 nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
2984 skb_put(nskb, len), 2986 skb_put(nskb, len),
2985 len, 0); 2987 len, 0);
2988 SKB_GSO_CB(nskb)->csum_start =
2989 skb_headroom(nskb) + offset;
2986 continue; 2990 continue;
2987 } 2991 }
2988 2992
@@ -3052,6 +3056,8 @@ perform_csum_check:
3052 nskb->csum = skb_checksum(nskb, doffset, 3056 nskb->csum = skb_checksum(nskb, doffset,
3053 nskb->len - doffset, 0); 3057 nskb->len - doffset, 0);
3054 nskb->ip_summed = CHECKSUM_NONE; 3058 nskb->ip_summed = CHECKSUM_NONE;
3059 SKB_GSO_CB(nskb)->csum_start =
3060 skb_headroom(nskb) + doffset;
3055 } 3061 }
3056 } while ((offset += len) < head_skb->len); 3062 } while ((offset += len) < head_skb->len);
3057 3063