*/
static inline __wsum lco_csum(struct sk_buff *skb)
{
- char *inner_csum_field;
- __wsum csum;
+ unsigned char *csum_start = skb_checksum_start(skb);
+ unsigned char *l4_hdr = skb_transport_header(skb);
+ __wsum partial;
/* Start with complement of inner checksum adjustment */
- inner_csum_field = skb->data + skb_checksum_start_offset(skb) +
- skb->csum_offset;
- csum = ~csum_unfold(*(__force __sum16 *)inner_csum_field);
+ partial = ~csum_unfold(*(__force __sum16 *)(csum_start +
+ skb->csum_offset));
+
/* Add in checksum of our headers (incl. outer checksum
- * adjustment filled in by caller)
+ * adjustment filled in by caller) and return result.
*/
- csum = skb_checksum(skb, 0, skb_checksum_start_offset(skb), csum);
- /* The result is the checksum from skb->data to end of packet */
- return csum;
+ return csum_partial(l4_hdr, csum_start - l4_hdr, partial);
}
#endif /* __KERNEL__ */