net: reduce structures when XFRM=n
[safe/jmp/linux-2.6] / include / linux / skbuff.h
index c45ad12..487e345 100644 (file)
 #define HAVE_ALLOC_SKB         /* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */
 
+/* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
-#define CHECKSUM_PARTIAL 1
-#define CHECKSUM_UNNECESSARY 2
-#define CHECKSUM_COMPLETE 3
+#define CHECKSUM_UNNECESSARY 1
+#define CHECKSUM_COMPLETE 2
+#define CHECKSUM_PARTIAL 3
 
 #define SKB_DATA_ALIGN(X)      (((X) + (SMP_CACHE_BYTES - 1)) & \
                                 ~(SMP_CACHE_BYTES - 1))
 #define SKB_WITH_OVERHEAD(X)   \
-       (((X) - sizeof(struct skb_shared_info)) & \
-        ~(SMP_CACHE_BYTES - 1))
+       ((X) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
 #define SKB_MAX_ORDER(X, ORDER) \
        SKB_WITH_OVERHEAD((PAGE_SIZE << (ORDER)) - (X))
 #define SKB_MAX_HEAD(X)                (SKB_MAX_ORDER((X), 0))
  *         is able to produce some skb->csum, it MUST use COMPLETE,
  *         not UNNECESSARY.
  *
+ *     PARTIAL: identical to the case for output below.  This may occur
+ *         on a packet received directly from another Linux OS, e.g.,
+ *         a virtualised Linux kernel on the same host.  The packet can
+ *         be treated in the same way as UNNECESSARY except that on
+ *         output (i.e., forwarding) the checksum must be filled in
+ *         by the OS or the hardware.
+ *
  * B. Checksumming on output.
  *
  *     NONE: skb is checksummed by protocol or csum is not required.
  *
  *     PARTIAL: device is required to csum packet as seen by hard_start_xmit
- *     from skb->transport_header to the end and to record the checksum
- *     at skb->transport_header + skb->csum.
+ *     from skb->csum_start to the end and to record the checksum
+ *     at skb->csum_start + skb->csum_offset.
  *
  *     Device must show its capabilities in dev->features, set
  *     at device setup time.
  *                       TCP/UDP over IPv4. Sigh. Vendors like this
  *                       way by an unknown reason. Though, see comment above
  *                       about CHECKSUM_UNNECESSARY. 8)
+ *     NETIF_F_IPV6_CSUM about as dumb as the last one but does IPv6 instead.
  *
  *     Any questions? No questions, good.              --ANK
  */
 
 struct net_device;
+struct scatterlist;
+struct pipe_inode_info;
 
-#ifdef CONFIG_NETFILTER
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 struct nf_conntrack {
        atomic_t use;
-       void (*destroy)(struct nf_conntrack *);
 };
+#endif
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info {
        atomic_t use;
        struct net_device *physindev;
        struct net_device *physoutdev;
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-       struct net_device *netoutdev;
-#endif
        unsigned int mask;
        unsigned long data[32 / sizeof(unsigned long)];
 };
 #endif
 
-#endif
-
 struct sk_buff_head {
        /* These two members must be first. */
        struct sk_buff  *next;
@@ -126,8 +131,8 @@ typedef struct skb_frag_struct skb_frag_t;
 
 struct skb_frag_struct {
        struct page *page;
-       __u16 page_offset;
-       __u16 size;
+       __u32 page_offset;
+       __u32 size;
 };
 
 /* This data is invariant across clones and lives at
@@ -141,14 +146,20 @@ struct skb_shared_info {
        unsigned short  gso_segs;
        unsigned short  gso_type;
        __be32          ip6_frag_id;
+#ifdef CONFIG_HAS_DMA
+       unsigned int    num_dma_maps;
+#endif
        struct sk_buff  *frag_list;
        skb_frag_t      frags[MAX_SKB_FRAGS];
+#ifdef CONFIG_HAS_DMA
+       dma_addr_t      dma_maps[MAX_SKB_FRAGS + 1];
+#endif
 };
 
 /* We divide dataref into two halves.  The higher 16 bits hold references
  * to the payload part of skb->data.  The lower 16 bits hold references to
- * the entire skb->data.  It is up to the users of the skb to agree on
- * where the payload starts.
+ * the entire skb->data.  A clone of a headerless skb holds the length of
+ * the header in skb->hdr_len.
  *
  * All users must obey the rule that the skb->data reference count must be
  * greater than or equal to the payload reference count.
@@ -179,6 +190,16 @@ enum {
        SKB_GSO_TCPV6 = 1 << 4,
 };
 
+#if BITS_PER_LONG > 32
+#define NET_SKBUFF_DATA_USES_OFFSET 1
+#endif
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+typedef unsigned int sk_buff_data_t;
+#else
+typedef unsigned char *sk_buff_data_t;
+#endif
+
 /** 
  *     struct sk_buff - socket buffer
  *     @next: Next buffer in list
@@ -186,8 +207,7 @@ enum {
  *     @sk: Socket we are owned by
  *     @tstamp: Time we arrived
  *     @dev: Device we arrived on/are leaving by
- *     @iif: ifindex of device we arrived on
- *     @h: Transport layer header
+ *     @transport_header: Transport layer header
  *     @network_header: Network layer header
  *     @mac_header: Link layer header
  *     @dst: destination entry
@@ -196,7 +216,10 @@ enum {
  *     @len: Length of actual data
  *     @data_len: Data length
  *     @mac_len: Length of link layer header
- *     @csum: Checksum
+ *     @hdr_len: writable header length of cloned skb
+ *     @csum: Checksum (must include start/offset pair)
+ *     @csum_start: Offset from skb->head where checksumming should start
+ *     @csum_offset: Offset from csum_start where checksum should be stored
  *     @local_df: allow local fragmentation
  *     @cloned: Head may be cloned (check refcnt to be sure)
  *     @nohdr: Payload reference only, must not modify header
@@ -215,14 +238,22 @@ enum {
  *     @mark: Generic packet mark
  *     @nfct: Associated connection, if any
  *     @ipvs_property: skbuff is owned by ipvs
+ *     @peeked: this packet has been seen already, so stats have been
+ *             done for it, don't do them again
+ *     @nf_trace: netfilter packet trace flag
  *     @nfctinfo: Relationship of this skb to the connection
  *     @nfct_reasm: netfilter conntrack re-assembly pointer
  *     @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ *     @iif: ifindex of device we arrived on
+ *     @queue_mapping: Queue mapping for multiqueue devices
  *     @tc_index: Traffic control index
  *     @tc_verd: traffic control verdict
+ *     @ndisc_nodetype: router type (from link layer)
+ *     @do_not_encrypt: set to prevent encryption of this frame
  *     @dma_cookie: a cookie to one of several possible DMA operations
  *             done by skb DMA functions
  *     @secmark: security marking
+ *     @vlan_tci: vlan tag control information
  */
 
 struct sk_buff {
@@ -233,15 +264,14 @@ struct sk_buff {
        struct sock             *sk;
        ktime_t                 tstamp;
        struct net_device       *dev;
-       int                     iif;
-       /* 4 byte hole on 64 bit*/
 
-       unsigned char           *transport_header;
-       unsigned char           *network_header;
-       unsigned char           *mac_header;
-       struct  dst_entry       *dst;
+       union {
+               struct  dst_entry       *dst;
+               struct  rtable          *rtable;
+       };
+#ifdef CONFIG_XFRM
        struct  sec_path        *sp;
-
+#endif
        /*
         * This is the control buffer. It is free to use for every
         * layer. Please put your private variables there. If you
@@ -251,11 +281,15 @@ struct sk_buff {
        char                    cb[48];
 
        unsigned int            len,
-                               data_len,
-                               mac_len;
+                               data_len;
+       __u16                   mac_len,
+                               hdr_len;
        union {
                __wsum          csum;
-               __u32           csum_offset;
+               struct {
+                       __u16   csum_start;
+                       __u16   csum_offset;
+               };
        };
        __u32                   priority;
        __u8                    local_df:1,
@@ -265,25 +299,36 @@ struct sk_buff {
                                nfctinfo:3;
        __u8                    pkt_type:3,
                                fclone:2,
-                               ipvs_property:1;
+                               ipvs_property:1,
+                               peeked:1,
+                               nf_trace:1;
        __be16                  protocol;
 
        void                    (*destructor)(struct sk_buff *skb);
-#ifdef CONFIG_NETFILTER
-       struct nf_conntrack     *nfct;
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+       struct nf_conntrack     *nfct;
        struct sk_buff          *nfct_reasm;
 #endif
 #ifdef CONFIG_BRIDGE_NETFILTER
        struct nf_bridge_info   *nf_bridge;
 #endif
-#endif /* CONFIG_NETFILTER */
+
+       int                     iif;
+       __u16                   queue_mapping;
 #ifdef CONFIG_NET_SCHED
        __u16                   tc_index;       /* traffic control index */
 #ifdef CONFIG_NET_CLS_ACT
        __u16                   tc_verd;        /* traffic control verdict */
 #endif
 #endif
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+       __u8                    ndisc_nodetype:2;
+#endif
+#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
+       __u8                    do_not_encrypt:1;
+#endif
+       /* 0/13/14 bit hole */
+
 #ifdef CONFIG_NET_DMA
        dma_cookie_t            dma_cookie;
 #endif
@@ -293,13 +338,18 @@ struct sk_buff {
 
        __u32                   mark;
 
+       __u16                   vlan_tci;
+
+       sk_buff_data_t          transport_header;
+       sk_buff_data_t          network_header;
+       sk_buff_data_t          mac_header;
        /* These elements must be at the end, see alloc_skb() for details.  */
+       sk_buff_data_t          tail;
+       sk_buff_data_t          end;
+       unsigned char           *head,
+                               *data;
        unsigned int            truesize;
        atomic_t                users;
-       unsigned char           *head,
-                               *data,
-                               *tail,
-                               *end;
 };
 
 #ifdef __KERNEL__
@@ -310,6 +360,14 @@ struct sk_buff {
 
 #include <asm/system.h>
 
+#ifdef CONFIG_HAS_DMA
+#include <linux/dma-mapping.h>
+extern int skb_dma_map(struct device *dev, struct sk_buff *skb,
+                      enum dma_data_direction dir);
+extern void skb_dma_unmap(struct device *dev, struct sk_buff *skb,
+                         enum dma_data_direction dir);
+#endif
+
 extern void kfree_skb(struct sk_buff *skb);
 extern void           __kfree_skb(struct sk_buff *skb);
 extern struct sk_buff *__alloc_skb(unsigned int size,
@@ -326,7 +384,9 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
        return __alloc_skb(size, priority, 1, -1);
 }
 
-extern void           kfree_skbmem(struct sk_buff *skb);
+extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
+
+extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
 extern struct sk_buff *skb_clone(struct sk_buff *skb,
                                 gfp_t priority);
 extern struct sk_buff *skb_copy(const struct sk_buff *skb,
@@ -341,6 +401,11 @@ extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
 extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
                                       int newheadroom, int newtailroom,
                                       gfp_t priority);
+extern int            skb_to_sgvec(struct sk_buff *skb,
+                                   struct scatterlist *sg, int offset,
+                                   int len);
+extern int            skb_cow_data(struct sk_buff *skb, int tailbits,
+                                   struct sk_buff **trailer);
 extern int            skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)       kfree_skb(a)
 extern void          skb_over_panic(struct sk_buff *skb, int len,
@@ -351,7 +416,9 @@ extern void       skb_truesize_bug(struct sk_buff *skb);
 
 static inline void skb_truesize_check(struct sk_buff *skb)
 {
-       if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+       int len = sizeof(struct sk_buff) + skb->len;
+
+       if (unlikely((int)skb->truesize < len))
                skb_truesize_bug(skb);
 }
 
@@ -382,8 +449,20 @@ extern unsigned int   skb_find_text(struct sk_buff *skb, unsigned int from,
                                    unsigned int to, struct ts_config *config,
                                    struct ts_state *state);
 
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
+{
+       return skb->head + skb->end;
+}
+#else
+static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
+{
+       return skb->end;
+}
+#endif
+
 /* Internal */
-#define skb_shinfo(SKB)                ((struct skb_shared_info *)((SKB)->end))
+#define skb_shinfo(SKB)        ((struct skb_shared_info *)(skb_end_pointer(SKB)))
 
 /**
  *     skb_queue_empty - check if a queue is empty
@@ -397,6 +476,37 @@ static inline int skb_queue_empty(const struct sk_buff_head *list)
 }
 
 /**
+ *     skb_queue_is_last - check if skb is the last entry in the queue
+ *     @list: queue head
+ *     @skb: buffer
+ *
+ *     Returns true if @skb is the last buffer on the list.
+ */
+static inline bool skb_queue_is_last(const struct sk_buff_head *list,
+                                    const struct sk_buff *skb)
+{
+       return (skb->next == (struct sk_buff *) list);
+}
+
+/**
+ *     skb_queue_next - return the next packet in the queue
+ *     @list: queue head
+ *     @skb: current buffer
+ *
+ *     Return the next packet in @list after @skb.  It is only valid to
+ *     call this if skb_queue_is_last() evaluates to false.
+ */
+static inline struct sk_buff *skb_queue_next(const struct sk_buff_head *list,
+                                            const struct sk_buff *skb)
+{
+       /* This BUG_ON may seem severe, but if we just return then we
+        * are going to dereference garbage.
+        */
+       BUG_ON(skb_queue_is_last(list, skb));
+       return skb->next;
+}
+
+/**
  *     skb_get - reference buffer
  *     @skb: buffer to reference
  *
@@ -584,6 +694,22 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
        return list_->qlen;
 }
 
+/**
+ *     __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head
+ *     @list: queue to initialize
+ *
+ *     This initializes only the list and queue length aspects of
+ *     an sk_buff_head object.  This allows to initialize the list
+ *     aspects of an sk_buff_head without reinitializing things like
+ *     the spinlock.  It can also be used for on-stack sk_buff_head
+ *     objects where the spinlock is known to not be used.
+ */
+static inline void __skb_queue_head_init(struct sk_buff_head *list)
+{
+       list->prev = list->next = (struct sk_buff *)list;
+       list->qlen = 0;
+}
+
 /*
  * This function creates a split out lock class for each invocation;
  * this is needed for now since a whole lot of users of the skb-queue
@@ -595,8 +721,7 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
 static inline void skb_queue_head_init(struct sk_buff_head *list)
 {
        spin_lock_init(&list->lock);
-       list->prev = list->next = (struct sk_buff *)list;
-       list->qlen = 0;
+       __skb_queue_head_init(list);
 }
 
 static inline void skb_queue_head_init_class(struct sk_buff_head *list,
@@ -607,11 +732,98 @@ static inline void skb_queue_head_init_class(struct sk_buff_head *list,
 }
 
 /*
- *     Insert an sk_buff at the start of a list.
+ *     Insert an sk_buff on a list.
  *
  *     The "__skb_xxxx()" functions are the non-atomic ones that
  *     can only be called with interrupts disabled.
  */
+extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+static inline void __skb_insert(struct sk_buff *newsk,
+                               struct sk_buff *prev, struct sk_buff *next,
+                               struct sk_buff_head *list)
+{
+       newsk->next = next;
+       newsk->prev = prev;
+       next->prev  = prev->next = newsk;
+       list->qlen++;
+}
+
+static inline void __skb_queue_splice(const struct sk_buff_head *list,
+                                     struct sk_buff *prev,
+                                     struct sk_buff *next)
+{
+       struct sk_buff *first = list->next;
+       struct sk_buff *last = list->prev;
+
+       first->prev = prev;
+       prev->next = first;
+
+       last->next = next;
+       next->prev = last;
+}
+
+/**
+ *     skb_queue_splice - join two skb lists, this is designed for stacks
+ *     @list: the new list to add
+ *     @head: the place to add it in the first list
+ */
+static inline void skb_queue_splice(const struct sk_buff_head *list,
+                                   struct sk_buff_head *head)
+{
+       if (!skb_queue_empty(list)) {
+               __skb_queue_splice(list, (struct sk_buff *) head, head->next);
+               head->qlen += list->qlen;
+       }
+}
+
+/**
+ *     skb_queue_splice - join two skb lists and reinitialise the emptied list
+ *     @list: the new list to add
+ *     @head: the place to add it in the first list
+ *
+ *     The list at @list is reinitialised
+ */
+static inline void skb_queue_splice_init(struct sk_buff_head *list,
+                                        struct sk_buff_head *head)
+{
+       if (!skb_queue_empty(list)) {
+               __skb_queue_splice(list, (struct sk_buff *) head, head->next);
+               head->qlen += list->qlen;
+               __skb_queue_head_init(list);
+       }
+}
+
+/**
+ *     skb_queue_splice_tail - join two skb lists, each list being a queue
+ *     @list: the new list to add
+ *     @head: the place to add it in the first list
+ */
+static inline void skb_queue_splice_tail(const struct sk_buff_head *list,
+                                        struct sk_buff_head *head)
+{
+       if (!skb_queue_empty(list)) {
+               __skb_queue_splice(list, head->prev, (struct sk_buff *) head);
+               head->qlen += list->qlen;
+       }
+}
+
+/**
+ *     skb_queue_splice_tail - join two skb lists and reinitialise the emptied list
+ *     @list: the new list to add
+ *     @head: the place to add it in the first list
+ *
+ *     Each of the lists is a queue.
+ *     The list at @list is reinitialised
+ */
+static inline void skb_queue_splice_tail_init(struct sk_buff_head *list,
+                                             struct sk_buff_head *head)
+{
+       if (!skb_queue_empty(list)) {
+               __skb_queue_splice(list, head->prev, (struct sk_buff *) head);
+               head->qlen += list->qlen;
+               __skb_queue_head_init(list);
+       }
+}
 
 /**
  *     __skb_queue_after - queue a buffer at the list head
@@ -628,13 +840,17 @@ static inline void __skb_queue_after(struct sk_buff_head *list,
                                     struct sk_buff *prev,
                                     struct sk_buff *newsk)
 {
-       struct sk_buff *next;
-       list->qlen++;
+       __skb_insert(newsk, prev, prev->next, list);
+}
 
-       next = prev->next;
-       newsk->next = next;
-       newsk->prev = prev;
-       next->prev  = prev->next = newsk;
+extern void skb_append(struct sk_buff *old, struct sk_buff *newsk,
+                      struct sk_buff_head *list);
+
+static inline void __skb_queue_before(struct sk_buff_head *list,
+                                     struct sk_buff *next,
+                                     struct sk_buff *newsk)
+{
+       __skb_insert(newsk, next->prev, next, list);
 }
 
 /**
@@ -668,66 +884,7 @@ extern void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
 static inline void __skb_queue_tail(struct sk_buff_head *list,
                                   struct sk_buff *newsk)
 {
-       struct sk_buff *prev, *next;
-
-       list->qlen++;
-       next = (struct sk_buff *)list;
-       prev = next->prev;
-       newsk->next = next;
-       newsk->prev = prev;
-       next->prev  = prev->next = newsk;
-}
-
-
-/**
- *     __skb_dequeue - remove from the head of the queue
- *     @list: list to dequeue from
- *
- *     Remove the head of the list. This function does not take any locks
- *     so must be used with appropriate locks held only. The head item is
- *     returned or %NULL if the list is empty.
- */
-extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
-static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
-{
-       struct sk_buff *next, *prev, *result;
-
-       prev = (struct sk_buff *) list;
-       next = prev->next;
-       result = NULL;
-       if (next != prev) {
-               result       = next;
-               next         = next->next;
-               list->qlen--;
-               next->prev   = prev;
-               prev->next   = next;
-               result->next = result->prev = NULL;
-       }
-       return result;
-}
-
-
-/*
- *     Insert a packet on a list.
- */
-extern void        skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
-static inline void __skb_insert(struct sk_buff *newsk,
-                               struct sk_buff *prev, struct sk_buff *next,
-                               struct sk_buff_head *list)
-{
-       newsk->next = next;
-       newsk->prev = prev;
-       next->prev  = prev->next = newsk;
-       list->qlen++;
-}
-
-/*
- *     Place a packet after a given packet in a list.
- */
-extern void       skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
-static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
-{
-       __skb_insert(newsk, old, old->next, list);
+       __skb_queue_before(list, (struct sk_buff *)list, newsk);
 }
 
 /*
@@ -747,8 +904,22 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
        prev->next = next;
 }
 
-
-/* XXX: more streamlined implementation */
+/**
+ *     __skb_dequeue - remove from the head of the queue
+ *     @list: list to dequeue from
+ *
+ *     Remove the head of the list. This function does not take any locks
+ *     so must be used with appropriate locks held only. The head item is
+ *     returned or %NULL if the list is empty.
+ */
+extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
+static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+{
+       struct sk_buff *skb = skb_peek(list);
+       if (skb)
+               __skb_unlink(skb, list);
+       return skb;
+}
 
 /**
  *     __skb_dequeue_tail - remove from the tail of the queue
@@ -798,42 +969,61 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
        skb_shinfo(skb)->nr_frags = i + 1;
 }
 
+extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
+                           int off, int size);
+
 #define SKB_PAGE_ASSERT(skb)   BUG_ON(skb_shinfo(skb)->nr_frags)
 #define SKB_FRAG_ASSERT(skb)   BUG_ON(skb_shinfo(skb)->frag_list)
 #define SKB_LINEAR_ASSERT(skb)  BUG_ON(skb_is_nonlinear(skb))
 
-/*
- *     Add data to an sk_buff
- */
-static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
 {
-       unsigned char *tmp = skb->tail;
-       SKB_LINEAR_ASSERT(skb);
-       skb->tail += len;
-       skb->len  += len;
-       return tmp;
+       return skb->head + skb->tail;
 }
 
-/**
- *     skb_put - add data to a buffer
- *     @skb: buffer to use
- *     @len: amount of data to add
- *
- *     This function extends the used data area of the buffer. If this would
- *     exceed the total buffer size the kernel will panic. A pointer to the
- *     first byte of the extra data is returned.
+static inline void skb_reset_tail_pointer(struct sk_buff *skb)
+{
+       skb->tail = skb->data - skb->head;
+}
+
+static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
+{
+       skb_reset_tail_pointer(skb);
+       skb->tail += offset;
+}
+#else /* NET_SKBUFF_DATA_USES_OFFSET */
+static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
+{
+       return skb->tail;
+}
+
+static inline void skb_reset_tail_pointer(struct sk_buff *skb)
+{
+       skb->tail = skb->data;
+}
+
+static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
+{
+       skb->tail = skb->data + offset;
+}
+
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+
+/*
+ *     Add data to an sk_buff
  */
-static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+extern unsigned char *skb_put(struct sk_buff *skb, unsigned int len);
+static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
 {
-       unsigned char *tmp = skb->tail;
+       unsigned char *tmp = skb_tail_pointer(skb);
        SKB_LINEAR_ASSERT(skb);
        skb->tail += len;
        skb->len  += len;
-       if (unlikely(skb->tail>skb->end))
-               skb_over_panic(skb, len, current_text_addr());
        return tmp;
 }
 
+extern unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
 static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
 {
        skb->data -= len;
@@ -841,24 +1031,7 @@ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
        return skb->data;
 }
 
-/**
- *     skb_push - add data to the start of a buffer
- *     @skb: buffer to use
- *     @len: amount of data to add
- *
- *     This function extends the used data area of the buffer at the buffer
- *     start. If this would exceed the total buffer headroom the kernel will
- *     panic. A pointer to the first byte of the extra data is returned.
- */
-static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
-{
-       skb->data -= len;
-       skb->len  += len;
-       if (unlikely(skb->data<skb->head))
-               skb_under_panic(skb, len, current_text_addr());
-       return skb->data;
-}
-
+extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
 static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
 {
        skb->len -= len;
@@ -866,27 +1039,12 @@ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
        return skb->data += len;
 }
 
-/**
- *     skb_pull - remove data from the start of a buffer
- *     @skb: buffer to use
- *     @len: amount of data to remove
- *
- *     This function removes data from the start of a buffer, returning
- *     the memory to the headroom. A pointer to the next data in the buffer
- *     is returned. Once the data has been pulled future pushes will overwrite
- *     the old data.
- */
-static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
-{
-       return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
-}
-
 extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
 
 static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
 {
        if (len > skb_headlen(skb) &&
-           !__pskb_pull_tail(skb, len-skb_headlen(skb)))
+           !__pskb_pull_tail(skb, len - skb_headlen(skb)))
                return NULL;
        skb->len -= len;
        return skb->data += len;
@@ -903,7 +1061,7 @@ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
                return 1;
        if (unlikely(len > skb->len))
                return 0;
-       return __pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL;
+       return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
 }
 
 /**
@@ -912,7 +1070,7 @@ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
  *
  *     Return the number of bytes of free space at the head of an &sk_buff.
  */
-static inline int skb_headroom(const struct sk_buff *skb)
+static inline unsigned int skb_headroom(const struct sk_buff *skb)
 {
        return skb->data - skb->head;
 }
@@ -942,50 +1100,92 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
        skb->tail += len;
 }
 
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 {
-       return skb->transport_header;
+       return skb->head + skb->transport_header;
 }
 
 static inline void skb_reset_transport_header(struct sk_buff *skb)
 {
-       skb->transport_header = skb->data;
+       skb->transport_header = skb->data - skb->head;
 }
 
 static inline void skb_set_transport_header(struct sk_buff *skb,
                                            const int offset)
 {
-       skb->transport_header = skb->data + offset;
-}
-
-static inline int skb_transport_offset(const struct sk_buff *skb)
-{
-       return skb->transport_header - skb->data;
+       skb_reset_transport_header(skb);
+       skb->transport_header += offset;
 }
 
 static inline unsigned char *skb_network_header(const struct sk_buff *skb)
 {
-       return skb->network_header;
+       return skb->head + skb->network_header;
 }
 
 static inline void skb_reset_network_header(struct sk_buff *skb)
 {
-       skb->network_header = skb->data;
+       skb->network_header = skb->data - skb->head;
 }
 
 static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
 {
-       skb->network_header = skb->data + offset;
+       skb_reset_network_header(skb);
+       skb->network_header += offset;
 }
 
-static inline int skb_network_offset(const struct sk_buff *skb)
+static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
 {
-       return skb->network_header - skb->data;
+       return skb->head + skb->mac_header;
 }
 
-static inline u32 skb_network_header_len(const struct sk_buff *skb)
+static inline int skb_mac_header_was_set(const struct sk_buff *skb)
 {
-       return skb->transport_header - skb->network_header;
+       return skb->mac_header != ~0U;
+}
+
+static inline void skb_reset_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->data - skb->head;
+}
+
+static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
+{
+       skb_reset_mac_header(skb);
+       skb->mac_header += offset;
+}
+
+#else /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
+{
+       return skb->transport_header;
+}
+
+static inline void skb_reset_transport_header(struct sk_buff *skb)
+{
+       skb->transport_header = skb->data;
+}
+
+static inline void skb_set_transport_header(struct sk_buff *skb,
+                                           const int offset)
+{
+       skb->transport_header = skb->data + offset;
+}
+
+static inline unsigned char *skb_network_header(const struct sk_buff *skb)
+{
+       return skb->network_header;
+}
+
+static inline void skb_reset_network_header(struct sk_buff *skb)
+{
+       skb->network_header = skb->data;
+}
+
+static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
+{
+       skb->network_header = skb->data + offset;
 }
 
 static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
@@ -1007,6 +1207,22 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
 {
        skb->mac_header = skb->data + offset;
 }
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline int skb_transport_offset(const struct sk_buff *skb)
+{
+       return skb_transport_header(skb) - skb->data;
+}
+
+static inline u32 skb_network_header_len(const struct sk_buff *skb)
+{
+       return skb->transport_header - skb->network_header;
+}
+
+static inline int skb_network_offset(const struct sk_buff *skb)
+{
+       return skb_network_header(skb) - skb->data;
+}
 
 /*
  * CPUs often take a performance hit when accessing unaligned memory
@@ -1059,25 +1275,11 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
                WARN_ON(1);
                return;
        }
-       skb->len  = len;
-       skb->tail = skb->data + len;
-}
-
-/**
- *     skb_trim - remove end from a buffer
- *     @skb: buffer to alter
- *     @len: new length
- *
- *     Cut the length of a buffer down by removing data from the tail. If
- *     the buffer is already under the length specified it is not modified.
- *     The skb must be linear.
- */
-static inline void skb_trim(struct sk_buff *skb, unsigned int len)
-{
-       if (skb->len > len)
-               __skb_trim(skb, len);
+       skb->len = len;
+       skb_set_tail_pointer(skb, len);
 }
 
+extern void skb_trim(struct sk_buff *skb, unsigned int len);
 
 static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
 {
@@ -1160,22 +1362,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
        return skb;
 }
 
-/**
- *     dev_alloc_skb - allocate an skbuff for receiving
- *     @length: length to allocate
- *
- *     Allocate a new &sk_buff and assign it a usage count of one. The
- *     buffer has unspecified headroom built in. Users should allocate
- *     the headroom they think they need without accounting for the
- *     built in space. The built in space is used for optimisations.
- *
- *     %NULL is returned if there is no free memory. Although this function
- *     allocates memory it can be called from an interrupt.
- */
-static inline struct sk_buff *dev_alloc_skb(unsigned int length)
-{
-       return __dev_alloc_skb(length, GFP_ATOMIC);
-}
+extern struct sk_buff *dev_alloc_skb(unsigned int length);
 
 extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
                unsigned int length, gfp_t gfp_mask);
@@ -1199,6 +1386,56 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
        return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
 }
 
+extern struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask);
+
+/**
+ *     netdev_alloc_page - allocate a page for ps-rx on a specific device
+ *     @dev: network device to receive on
+ *
+ *     Allocate a new page node local to the specified device.
+ *
+ *     %NULL is returned if there is no free memory.
+ */
+static inline struct page *netdev_alloc_page(struct net_device *dev)
+{
+       return __netdev_alloc_page(dev, GFP_ATOMIC);
+}
+
+static inline void netdev_free_page(struct net_device *dev, struct page *page)
+{
+       __free_page(page);
+}
+
+/**
+ *     skb_clone_writable - is the header of a clone writable
+ *     @skb: buffer to check
+ *     @len: length up to which to write
+ *
+ *     Returns true if modifying the header part of the cloned buffer
+ *     does not requires the data to be copied.
+ */
+static inline int skb_clone_writable(struct sk_buff *skb, unsigned int len)
+{
+       return !skb_header_cloned(skb) &&
+              skb_headroom(skb) + len <= skb->hdr_len;
+}
+
+static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
+                           int cloned)
+{
+       int delta = 0;
+
+       if (headroom < NET_SKB_PAD)
+               headroom = NET_SKB_PAD;
+       if (headroom > skb_headroom(skb))
+               delta = headroom - skb_headroom(skb);
+
+       if (delta || cloned)
+               return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
+                                       GFP_ATOMIC);
+       return 0;
+}
+
 /**
  *     skb_cow - copy header of skb when it is required
  *     @skb: buffer to cow
@@ -1213,16 +1450,22 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
  */
 static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
 {
-       int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) -
-                       skb_headroom(skb);
-
-       if (delta < 0)
-               delta = 0;
+       return __skb_cow(skb, headroom, skb_cloned(skb));
+}
 
-       if (delta || skb_cloned(skb))
-               return pskb_expand_head(skb, (delta + (NET_SKB_PAD-1)) &
-                               ~(NET_SKB_PAD-1), 0, GFP_ATOMIC);
-       return 0;
+/**
+ *     skb_cow_head - skb_cow but only making the head writable
+ *     @skb: buffer to cow
+ *     @headroom: needed headroom
+ *
+ *     This function is identical to skb_cow except that we replace the
+ *     skb_cloned check by skb_header_cloned.  It should be used when
+ *     you only need to push on some header and do not need to modify
+ *     the data.
+ */
+static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom)
+{
+       return __skb_cow(skb, headroom, skb_header_cloned(skb));
 }
 
 /**
@@ -1241,7 +1484,7 @@ static inline int skb_padto(struct sk_buff *skb, unsigned int len)
        unsigned int size = skb->len;
        if (likely(size >= len))
                return 0;
-       return skb_pad(skb, len-size);
+       return skb_pad(skb, len - size);
 }
 
 static inline int skb_add_data(struct sk_buff *skb,
@@ -1349,12 +1592,28 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
                     prefetch(skb->next), (skb != (struct sk_buff *)(queue));   \
                     skb = skb->next)
 
+#define skb_queue_walk_safe(queue, skb, tmp)                                   \
+               for (skb = (queue)->next, tmp = skb->next;                      \
+                    skb != (struct sk_buff *)(queue);                          \
+                    skb = tmp, tmp = skb->next)
+
+#define skb_queue_walk_from(queue, skb)                                                \
+               for (; prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \
+                    skb = skb->next)
+
+#define skb_queue_walk_from_safe(queue, skb, tmp)                              \
+               for (tmp = skb->next;                                           \
+                    skb != (struct sk_buff *)(queue);                          \
+                    skb = tmp, tmp = skb->next)
+
 #define skb_queue_reverse_walk(queue, skb) \
                for (skb = (queue)->prev;                                       \
                     prefetch(skb->prev), (skb != (struct sk_buff *)(queue));   \
                     skb = skb->prev)
 
 
+extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
+                                          int *peeked, int *err);
 extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
                                         int noblock, int *err);
 extern unsigned int    datagram_poll(struct file *file, struct socket *sock,
@@ -1365,18 +1624,27 @@ extern int             skb_copy_datagram_iovec(const struct sk_buff *from,
 extern int            skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
                                                        int hlen,
                                                        struct iovec *iov);
+extern int            skb_copy_datagram_from_iovec(struct sk_buff *skb,
+                                                   int offset,
+                                                   struct iovec *from,
+                                                   int len);
 extern void           skb_free_datagram(struct sock *sk, struct sk_buff *skb);
-extern void           skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
+extern int            skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
                                         unsigned int flags);
 extern __wsum         skb_checksum(const struct sk_buff *skb, int offset,
                                    int len, __wsum csum);
 extern int            skb_copy_bits(const struct sk_buff *skb, int offset,
                                     void *to, int len);
-extern int            skb_store_bits(const struct sk_buff *skb, int offset,
-                                     void *from, int len);
+extern int            skb_store_bits(struct sk_buff *skb, int offset,
+                                     const void *from, int len);
 extern __wsum         skb_copy_and_csum_bits(const struct sk_buff *skb,
                                              int offset, u8 *to, int len,
                                              __wsum csum);
+extern int             skb_splice_bits(struct sk_buff *skb,
+                                               unsigned int offset,
+                                               struct pipe_inode_info *pipe,
+                                               unsigned int len,
+                                               unsigned int flags);
 extern void           skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 extern void           skb_split(struct sk_buff *skb,
                                 struct sk_buff *skb1, const u32 len);
@@ -1397,8 +1665,36 @@ static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
        return buffer;
 }
 
+static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
+                                            void *to,
+                                            const unsigned int len)
+{
+       memcpy(to, skb->data, len);
+}
+
+static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb,
+                                                   const int offset, void *to,
+                                                   const unsigned int len)
+{
+       memcpy(to, skb->data + offset, len);
+}
+
+static inline void skb_copy_to_linear_data(struct sk_buff *skb,
+                                          const void *from,
+                                          const unsigned int len)
+{
+       memcpy(skb->data, from, len);
+}
+
+static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb,
+                                                 const int offset,
+                                                 const void *from,
+                                                 const unsigned int len)
+{
+       memcpy(skb->data + offset, from, len);
+}
+
 extern void skb_init(void);
-extern void skb_add_mtu(int mtu);
 
 /**
  *     skb_get_timestamp - get timestamp from a skb
@@ -1419,10 +1715,24 @@ static inline void __net_timestamp(struct sk_buff *skb)
        skb->tstamp = ktime_get_real();
 }
 
+static inline ktime_t net_timedelta(ktime_t t)
+{
+       return ktime_sub(ktime_get_real(), t);
+}
+
+static inline ktime_t net_invalid_timestamp(void)
+{
+       return ktime_set(0, 0);
+}
 
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
+static inline int skb_csum_unnecessary(const struct sk_buff *skb)
+{
+       return skb->ip_summed & CHECKSUM_UNNECESSARY;
+}
+
 /**
  *     skb_checksum_complete - Calculate checksum of an entire packet
  *     @skb: packet to process
@@ -1439,24 +1749,24 @@ extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
  *     if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the
  *     hardware has already verified the correctness of the checksum.
  */
-static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
+static inline __sum16 skb_checksum_complete(struct sk_buff *skb)
 {
-       return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-               __skb_checksum_complete(skb);
+       return skb_csum_unnecessary(skb) ?
+              0 : __skb_checksum_complete(skb);
 }
 
-#ifdef CONFIG_NETFILTER
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+extern void nf_conntrack_destroy(struct nf_conntrack *nfct);
 static inline void nf_conntrack_put(struct nf_conntrack *nfct)
 {
        if (nfct && atomic_dec_and_test(&nfct->use))
-               nfct->destroy(nfct);
+               nf_conntrack_destroy(nfct);
 }
 static inline void nf_conntrack_get(struct nf_conntrack *nfct)
 {
        if (nfct)
                atomic_inc(&nfct->use);
 }
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
 {
        if (skb)
@@ -1482,9 +1792,9 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
 #endif /* CONFIG_BRIDGE_NETFILTER */
 static inline void nf_reset(struct sk_buff *skb)
 {
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        nf_conntrack_put(skb->nfct);
        skb->nfct = NULL;
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        nf_conntrack_put_reasm(skb->nfct_reasm);
        skb->nfct_reasm = NULL;
 #endif
@@ -1497,10 +1807,10 @@ static inline void nf_reset(struct sk_buff *skb)
 /* Note: This doesn't put any conntrack and bridge info in dst. */
 static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 {
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        dst->nfct = src->nfct;
        nf_conntrack_get(src->nfct);
        dst->nfctinfo = src->nfctinfo;
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        dst->nfct_reasm = src->nfct_reasm;
        nf_conntrack_get_reasm(src->nfct_reasm);
 #endif
@@ -1512,8 +1822,8 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 
 static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 {
-       nf_conntrack_put(dst->nfct);
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+       nf_conntrack_put(dst->nfct);
        nf_conntrack_put_reasm(dst->nfct_reasm);
 #endif
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -1522,12 +1832,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
        __nf_copy(dst, src);
 }
 
-#else /* CONFIG_NETFILTER */
-static inline void nf_reset(struct sk_buff *skb) {}
-static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) {}
-static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) {}
-#endif /* CONFIG_NETFILTER */
-
 #ifdef CONFIG_NETWORK_SECMARK
 static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
 {
@@ -1546,10 +1850,64 @@ static inline void skb_init_secmark(struct sk_buff *skb)
 { }
 #endif
 
+static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
+{
+       skb->queue_mapping = queue_mapping;
+}
+
+static inline u16 skb_get_queue_mapping(struct sk_buff *skb)
+{
+       return skb->queue_mapping;
+}
+
+static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
+{
+       to->queue_mapping = from->queue_mapping;
+}
+
+#ifdef CONFIG_XFRM
+static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
+{
+       return skb->sp;
+}
+#else
+static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
+{
+       return NULL;
+}
+#endif
+
 static inline int skb_is_gso(const struct sk_buff *skb)
 {
        return skb_shinfo(skb)->gso_size;
 }
 
+static inline int skb_is_gso_v6(const struct sk_buff *skb)
+{
+       return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
+}
+
+extern void __skb_warn_lro_forwarding(const struct sk_buff *skb);
+
+static inline bool skb_warn_if_lro(const struct sk_buff *skb)
+{
+       /* LRO sets gso_size but not gso_type, whereas if GSO is really
+        * wanted then gso_type will be set. */
+       struct skb_shared_info *shinfo = skb_shinfo(skb);
+       if (shinfo->gso_size != 0 && unlikely(shinfo->gso_type == 0)) {
+               __skb_warn_lro_forwarding(skb);
+               return true;
+       }
+       return false;
+}
+
+static inline void skb_forward_csum(struct sk_buff *skb)
+{
+       /* Unfortunately we don't support this one.  Any brave souls? */
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+}
+
+bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */