+#if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+#define inet_proto_csum_replace16 rpl_inet_proto_csum_replace16
+static inline void inet_proto_csum_replace16(__sum16 *sum,
+ struct sk_buff *skb,
+ const __be32 *from,
+ const __be32 *to,
+ int pseudohdr)
+{
+ __be32 diff[] = {
+ ~from[0], ~from[1], ~from[2], ~from[3],
+ to[0], to[1], to[2], to[3],
+ };
+ if (get_ip_summed(skb) != OVS_CSUM_PARTIAL) {
+ *sum = csum_fold(csum_partial(diff, sizeof(diff),
+ ~csum_unfold(*sum)));
+ if (get_ip_summed(skb) == OVS_CSUM_COMPLETE && pseudohdr)
+ skb->csum = ~csum_partial(diff, sizeof(diff),
+ ~skb->csum);
+ } else if (pseudohdr)
+ *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
+ csum_unfold(*sum)));
+}
+#endif
+
+#ifdef NEED_CSUM_NORMALIZE
+static inline void update_csum_start(struct sk_buff *skb, int delta)
+{
+ if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
+ u16 csum_start, csum_offset;
+
+ get_skb_csum_pointers(skb, &csum_start, &csum_offset);
+ set_skb_csum_pointers(skb, csum_start + delta, csum_offset);
+ }
+}
+
+static inline int rpl_pskb_expand_head(struct sk_buff *skb, int nhead,
+ int ntail, gfp_t gfp_mask)
+{
+ int err;
+ int old_headroom = skb_headroom(skb);
+
+ err = pskb_expand_head(skb, nhead, ntail, gfp_mask);
+ if (unlikely(err))
+ return err;
+
+ update_csum_start(skb, skb_headroom(skb) - old_headroom);
+
+ return 0;
+}
+#define pskb_expand_head rpl_pskb_expand_head
+
+static inline unsigned char *rpl__pskb_pull_tail(struct sk_buff *skb,
+ int delta)
+{
+ unsigned char *ret;
+ int old_headroom = skb_headroom(skb);
+
+ ret = __pskb_pull_tail(skb, delta);
+ if (unlikely(!ret))
+ return ret;
+
+ update_csum_start(skb, skb_headroom(skb) - old_headroom);
+
+ return ret;
+}
+#define __pskb_pull_tail rpl__pskb_pull_tail
+#endif
+