Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / include / linux / skbuff.h
index 4ce9ff7..eab4f8f 100644 (file)
@@ -2162,6 +2162,11 @@ static inline int skb_checksum_start_offset(const struct sk_buff *skb)
        return skb->csum_start - skb_headroom(skb);
 }
 
+static inline unsigned char *skb_checksum_start(const struct sk_buff *skb)
+{
+       return skb->head + skb->csum_start;
+}
+
 static inline int skb_transport_offset(const struct sk_buff *skb)
 {
        return skb_transport_header(skb) - skb->data;
@@ -2400,6 +2405,10 @@ static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi,
 {
        return __napi_alloc_skb(napi, length, GFP_ATOMIC);
 }
+void napi_consume_skb(struct sk_buff *skb, int budget);
+
+void __kfree_skb_flush(void);
+void __kfree_skb_defer(struct sk_buff *skb);
 
 /**
  * __dev_alloc_pages - allocate page for network Rx
@@ -2622,6 +2631,13 @@ static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len
               skb_headroom(skb) + len <= skb->hdr_len;
 }
 
+static inline int skb_try_make_writable(struct sk_buff *skb,
+                                       unsigned int write_len)
+{
+       return skb_cloned(skb) && !skb_clone_writable(skb, write_len) &&
+              pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+}
+
 static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
                            int cloned)
 {
@@ -3550,6 +3566,7 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
 struct skb_gso_cb {
        int     mac_offset;
        int     encap_level;
+       __wsum  csum;
        __u16   csum_start;
 };
 #define SKB_SGO_CB_OFFSET      32
@@ -3576,6 +3593,16 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
        return 0;
 }
 
+static inline void gso_reset_checksum(struct sk_buff *skb, __wsum res)
+{
+       /* Do not update partial checksums if remote checksum is enabled. */
+       if (skb->remcsum_offload)
+               return;
+
+       SKB_GSO_CB(skb)->csum = res;
+       SKB_GSO_CB(skb)->csum_start = skb_checksum_start(skb) - skb->head;
+}
+
 /* Compute the checksum for a gso segment. First compute the checksum value
  * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
  * then add in skb->csum (checksum from csum_start to end of packet).
@@ -3586,15 +3613,14 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
  */
 static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
 {
-       int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) -
-                  skb_transport_offset(skb);
-       __wsum partial;
+       unsigned char *csum_start = skb_transport_header(skb);
+       int plen = (skb->head + SKB_GSO_CB(skb)->csum_start) - csum_start;
+       __wsum partial = SKB_GSO_CB(skb)->csum;
 
-       partial = csum_partial(skb_transport_header(skb), plen, skb->csum);
-       skb->csum = res;
-       SKB_GSO_CB(skb)->csum_start -= plen;
+       SKB_GSO_CB(skb)->csum = res;
+       SKB_GSO_CB(skb)->csum_start = csum_start - skb->head;
 
-       return csum_fold(partial);
+       return csum_fold(csum_partial(csum_start, plen, partial));
 }
 
 static inline bool skb_is_gso(const struct sk_buff *skb)
@@ -3684,5 +3710,30 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
        return hdr_len + skb_gso_transport_seglen(skb);
 }
 
+/* Local Checksum Offload.
+ * Compute outer checksum based on the assumption that the
+ * inner checksum will be offloaded later.
+ * See Documentation/networking/checksum-offloads.txt for
+ * explanation of how this works.
+ * Fill in outer checksum adjustment (e.g. with sum of outer
+ * pseudo-header) before calling.
+ * Also ensure that inner checksum is in linear data area.
+ */
+static inline __wsum lco_csum(struct sk_buff *skb)
+{
+       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 */
+       partial = ~csum_unfold(*(__force __sum16 *)(csum_start +
+                                                   skb->csum_offset));
+
+       /* Add in checksum of our headers (incl. outer checksum
+        * adjustment filled in by caller) and return result.
+        */
+       return csum_partial(l4_hdr, csum_start - l4_hdr, partial);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */