summaryrefslogtreecommitdiff
path: root/include/linux/skbuff.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/skbuff.h')
-rw-r--r--include/linux/skbuff.h74
1 files changed, 70 insertions, 4 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 320e976d5ab8..441f5bfdab8e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -230,6 +230,13 @@ enum {
/* generate wifi status information (where possible) */
SKBTX_WIFI_STATUS = 1 << 4,
+
+ /* This indicates at least one fragment might be overwritten
+ * (as in vmsplice(), sendfile() ...)
+ * If we need to compute a TX checksum, we'll need to copy
+ * all frags to avoid possible bad checksum
+ */
+ SKBTX_SHARED_FRAG = 1 << 5,
};
/*
@@ -307,6 +314,8 @@ enum {
SKB_GSO_TCPV6 = 1 << 4,
SKB_GSO_FCOE = 1 << 5,
+
+ SKB_GSO_GRE = 1 << 6,
};
#if BITS_PER_LONG > 32
@@ -491,7 +500,7 @@ struct sk_buff {
union {
__u32 mark;
__u32 dropcount;
- __u32 avail_size;
+ __u32 reserved_tailroom;
};
sk_buff_data_t inner_transport_header;
@@ -797,6 +806,16 @@ static inline int skb_cloned(const struct sk_buff *skb)
(atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
}
+static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
+{
+ might_sleep_if(pri & __GFP_WAIT);
+
+ if (skb_cloned(skb))
+ return pskb_expand_head(skb, 0, 0, pri);
+
+ return 0;
+}
+
/**
* skb_header_cloned - is the header a clone
* @skb: buffer to check
@@ -1269,11 +1288,13 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
* do not lose pfmemalloc information as the pages would not be
* allocated using __GFP_MEMALLOC.
*/
- if (page->pfmemalloc && !page->mapping)
- skb->pfmemalloc = true;
frag->page.p = page;
frag->page_offset = off;
skb_frag_size_set(frag, size);
+
+ page = compound_head(page);
+ if (page->pfmemalloc && !page->mapping)
+ skb->pfmemalloc = true;
}
/**
@@ -1428,7 +1449,10 @@ static inline int skb_tailroom(const struct sk_buff *skb)
*/
static inline int skb_availroom(const struct sk_buff *skb)
{
- return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len;
+ if (skb_is_nonlinear(skb))
+ return 0;
+
+ return skb->end - skb->tail - skb->reserved_tailroom;
}
/**
@@ -1492,6 +1516,11 @@ static inline void skb_set_inner_network_header(struct sk_buff *skb,
skb->inner_network_header += offset;
}
+static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
+{
+ return skb->transport_header != ~0U;
+}
+
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
return skb->head + skb->transport_header;
@@ -1580,6 +1609,11 @@ static inline void skb_set_inner_network_header(struct sk_buff *skb,
skb->inner_network_header = skb->data + offset;
}
+static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
+{
+ return skb->transport_header != NULL;
+}
+
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
return skb->transport_header;
@@ -1815,6 +1849,10 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
kfree_skb(skb);
}
+#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
+#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER)
+#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE
+
extern void *netdev_alloc_frag(unsigned int fragsz);
extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
@@ -2191,6 +2229,19 @@ static inline int skb_linearize(struct sk_buff *skb)
}
/**
+ * skb_has_shared_frag - can any frag be overwritten
+ * @skb: buffer to test
+ *
+ * Return true if the skb has at least one frag that might be modified
+ * by an external entity (as in vmsplice()/sendfile())
+ */
+static inline bool skb_has_shared_frag(const struct sk_buff *skb)
+{
+ return skb_is_nonlinear(skb) &&
+ skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
+}
+
+/**
* skb_linearize_cow - make sure skb is linear and writable
* @skb: buffer to process
*
@@ -2688,6 +2739,21 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
}
#endif
+/* Keeps track of mac header offset relative to skb->head.
+ * It is useful for TSO of Tunneling protocol. e.g. GRE.
+ * For non-tunnel skb it points to skb_mac_header() and for
+ * tunnel skb it points to outer mac header. */
+struct skb_gso_cb {
+ int mac_offset;
+};
+#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb)
+
+static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
+{
+ return (skb_mac_header(inner_skb) - inner_skb->head) -
+ SKB_GSO_CB(inner_skb)->mac_offset;
+}
+
static inline bool skb_is_gso(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_size;