]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - include/linux/skbuff.h
iwlwifi: dont pull too much payload in skb head
[mirror_ubuntu-bionic-kernel.git] / include / linux / skbuff.h
index 111f26b6e28b992bbebbe645819712bf8c07ab63..bb47314c7179655ed3ce0ea89cba6219bde5b1e4 100644 (file)
@@ -117,11 +117,11 @@ struct nf_conntrack {
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info {
-       atomic_t use;
-       struct net_device *physindev;
-       struct net_device *physoutdev;
-       unsigned int mask;
-       unsigned long data[32 / sizeof(unsigned long)];
+       atomic_t                use;
+       unsigned int            mask;
+       struct net_device       *physindev;
+       struct net_device       *physoutdev;
+       unsigned long           data[32 / sizeof(unsigned long)];
 };
 #endif
 
@@ -470,7 +470,8 @@ struct sk_buff {
        __u8                    wifi_acked_valid:1;
        __u8                    wifi_acked:1;
        __u8                    no_fcs:1;
-       /* 9/11 bit hole (depending on ndisc_nodetype presence) */
+       __u8                    head_frag:1;
+       /* 8/10 bit hole (depending on ndisc_nodetype presence) */
        kmemcheck_bitfield_end(flags2);
 
 #ifdef CONFIG_NET_DMA
@@ -560,9 +561,10 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
 extern void kfree_skb(struct sk_buff *skb);
 extern void consume_skb(struct sk_buff *skb);
 extern void           __kfree_skb(struct sk_buff *skb);
+extern struct kmem_cache *skbuff_head_cache;
 extern struct sk_buff *__alloc_skb(unsigned int size,
                                   gfp_t priority, int fclone, int node);
-extern struct sk_buff *build_skb(void *data);
+extern struct sk_buff *build_skb(void *data, unsigned int frag_size);
 static inline struct sk_buff *alloc_skb(unsigned int size,
                                        gfp_t priority)
 {
@@ -643,11 +645,21 @@ static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
        return skb->head + skb->end;
 }
+
+static inline unsigned int skb_end_offset(const struct sk_buff *skb)
+{
+       return skb->end;
+}
 #else
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
        return skb->end;
 }
+
+static inline unsigned int skb_end_offset(const struct sk_buff *skb)
+{
+       return skb->end - skb->head;
+}
 #endif
 
 /* Internal */
@@ -881,10 +893,11 @@ static inline struct sk_buff *skb_unshare(struct sk_buff *skb,
  */
 static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_)
 {
-       struct sk_buff *list = ((const struct sk_buff *)list_)->next;
-       if (list == (struct sk_buff *)list_)
-               list = NULL;
-       return list;
+       struct sk_buff *skb = list_->next;
+
+       if (skb == (struct sk_buff *)list_)
+               skb = NULL;
+       return skb;
 }
 
 /**
@@ -900,6 +913,7 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
                const struct sk_buff_head *list_)
 {
        struct sk_buff *next = skb->next;
+
        if (next == (struct sk_buff *)list_)
                next = NULL;
        return next;
@@ -920,10 +934,12 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
  */
 static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
 {
-       struct sk_buff *list = ((const struct sk_buff *)list_)->prev;
-       if (list == (struct sk_buff *)list_)
-               list = NULL;
-       return list;
+       struct sk_buff *skb = list_->prev;
+
+       if (skb == (struct sk_buff *)list_)
+               skb = NULL;
+       return skb;
+
 }
 
 /**
@@ -1963,8 +1979,8 @@ static inline int skb_add_data(struct sk_buff *skb,
        return -EFAULT;
 }
 
-static inline int skb_can_coalesce(struct sk_buff *skb, int i,
-                                  const struct page *page, int off)
+static inline bool skb_can_coalesce(struct sk_buff *skb, int i,
+                                   const struct page *page, int off)
 {
        if (i) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
@@ -1972,7 +1988,7 @@ static inline int skb_can_coalesce(struct sk_buff *skb, int i,
                return page == skb_frag_page(frag) &&
                       off == frag->page_offset + skb_frag_size(frag);
        }
-       return 0;
+       return false;
 }
 
 static inline int __skb_linearize(struct sk_buff *skb)
@@ -2552,7 +2568,7 @@ static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
                return false;
 
        skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
-       if (skb_end_pointer(skb) - skb->head < skb_size)
+       if (skb_end_offset(skb) < skb_size)
                return false;
 
        if (skb_shared(skb) || skb_cloned(skb))
@@ -2560,5 +2576,19 @@ static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
 
        return true;
 }
+
+/**
+ * skb_head_is_locked - Determine if the skb->head is locked down
+ * @skb: skb to check
+ *
+ * The head on skbs build around a head frag can be removed if they are
+ * not cloned.  This function returns true if the skb head is locked down
+ * due to either being allocated via kmalloc, or by being a clone with
+ * multiple references to the head.
+ */
+static inline bool skb_head_is_locked(const struct sk_buff *skb)
+{
+       return !skb->head_frag || skb_cloned(skb);
+}
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */