]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/linux/skbuff.h
Merge branch 'work.read_write' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[karo-tx-linux.git] / include / linux / skbuff.h
index a098d95b3d84d0246adc88651af9978d6810fb01..dbe29b6c9bd6097b4a7e5763ad39d26921780270 100644 (file)
  *       may perform further validation in this case.
  *     GRE: only if the checksum is present in the header.
  *     SCTP: indicates the CRC in SCTP header has been validated.
+ *     FCOE: indicates the CRC in FC frame has been validated.
  *
  *   skb->csum_level indicates the number of consecutive checksums found in
  *   the packet minus one that have been verified as CHECKSUM_UNNECESSARY.
  *   packet as seen by netif_rx() and fills out in skb->csum. Meaning, the
  *   hardware doesn't need to parse L3/L4 headers to implement this.
  *
- *   Note: Even if device supports only some protocols, but is able to produce
- *   skb->csum, it MUST use CHECKSUM_COMPLETE, not CHECKSUM_UNNECESSARY.
+ *   Notes:
+ *   - Even if device supports only some protocols, but is able to produce
+ *     skb->csum, it MUST use CHECKSUM_COMPLETE, not CHECKSUM_UNNECESSARY.
+ *   - CHECKSUM_COMPLETE is not applicable to SCTP and FCoE protocols.
  *
  * CHECKSUM_PARTIAL:
  *
  *
  *   NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM are being deprecated in favor of
  *   NETIF_F_HW_CSUM. New devices should use NETIF_F_HW_CSUM to indicate
- *   checksum offload capability. If a device has limited checksum capabilities
- *   (for instance can only perform NETIF_F_IP_CSUM or NETIF_F_IPV6_CSUM as
- *   described above) a helper function can be called to resolve
- *   CHECKSUM_PARTIAL. The helper functions are skb_csum_off_chk*. The helper
- *   function takes a spec argument that describes the protocol layer that is
- *   supported for checksum offload and can be called for each packet. If a
- *   packet does not match the specification for offload, skb_checksum_help
- *   is called to resolve the checksum.
+ *   checksum offload capability.
+ *   skb_csum_hwoffload_help() can be called to resolve CHECKSUM_PARTIAL based
+ *   on network device checksumming capabilities: if a packet does not match
+ *   them, skb_checksum_help or skb_crc32c_help (depending on the value of
+ *   csum_not_inet, see item D.) is called to resolve the checksum.
  *
  * CHECKSUM_NONE:
  *
  *
  *   NETIF_F_SCTP_CRC - This feature indicates that a device is capable of
  *     offloading the SCTP CRC in a packet. To perform this offload the stack
- *     will set ip_summed to CHECKSUM_PARTIAL and set csum_start and csum_offset
- *     accordingly. Note the there is no indication in the skbuff that the
- *     CHECKSUM_PARTIAL refers to an SCTP checksum, a driver that supports
- *     both IP checksum offload and SCTP CRC offload must verify which offload
- *     is configured for a packet presumably by inspecting packet headers.
+ *     will set set csum_start and csum_offset accordingly, set ip_summed to
+ *     CHECKSUM_PARTIAL and set csum_not_inet to 1, to provide an indication in
+ *     the skbuff that the CHECKSUM_PARTIAL refers to CRC32c.
+ *     A driver that supports both IP checksum offload and SCTP CRC32c offload
+ *     must verify which offload is configured for a packet by testing the
+ *     value of skb->csum_not_inet; skb_crc32c_csum_help is provided to resolve
+ *     CHECKSUM_PARTIAL on skbs where csum_not_inet is set to 1.
  *
  *   NETIF_F_FCOE_CRC - This feature indicates that a device is capable of
  *     offloading the FCOE CRC in a packet. To perform this offload the stack
@@ -250,7 +252,7 @@ struct nf_conntrack {
 
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 struct nf_bridge_info {
-       atomic_t                use;
+       refcount_t              use;
        enum {
                BRNF_PROTO_UNCHANGED,
                BRNF_PROTO_8021Q,
@@ -506,66 +508,6 @@ typedef unsigned int sk_buff_data_t;
 typedef unsigned char *sk_buff_data_t;
 #endif
 
-/**
- * struct skb_mstamp - multi resolution time stamps
- * @stamp_us: timestamp in us resolution
- * @stamp_jiffies: timestamp in jiffies
- */
-struct skb_mstamp {
-       union {
-               u64             v64;
-               struct {
-                       u32     stamp_us;
-                       u32     stamp_jiffies;
-               };
-       };
-};
-
-/**
- * skb_mstamp_get - get current timestamp
- * @cl: place to store timestamps
- */
-static inline void skb_mstamp_get(struct skb_mstamp *cl)
-{
-       u64 val = local_clock();
-
-       do_div(val, NSEC_PER_USEC);
-       cl->stamp_us = (u32)val;
-       cl->stamp_jiffies = (u32)jiffies;
-}
-
-/**
- * skb_mstamp_delta - compute the difference in usec between two skb_mstamp
- * @t1: pointer to newest sample
- * @t0: pointer to oldest sample
- */
-static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1,
-                                     const struct skb_mstamp *t0)
-{
-       s32 delta_us = t1->stamp_us - t0->stamp_us;
-       u32 delta_jiffies = t1->stamp_jiffies - t0->stamp_jiffies;
-
-       /* If delta_us is negative, this might be because interval is too big,
-        * or local_clock() drift is too big : fallback using jiffies.
-        */
-       if (delta_us <= 0 ||
-           delta_jiffies >= (INT_MAX / (USEC_PER_SEC / HZ)))
-
-               delta_us = jiffies_to_usecs(delta_jiffies);
-
-       return delta_us;
-}
-
-static inline bool skb_mstamp_after(const struct skb_mstamp *t1,
-                                   const struct skb_mstamp *t0)
-{
-       s32 diff = t1->stamp_jiffies - t0->stamp_jiffies;
-
-       if (!diff)
-               diff = t1->stamp_us - t0->stamp_us;
-       return diff > 0;
-}
-
 /** 
  *     struct sk_buff - socket buffer
  *     @next: Next buffer in list
@@ -616,6 +558,7 @@ static inline bool skb_mstamp_after(const struct skb_mstamp *t1,
  *     @wifi_acked_valid: wifi_acked was set
  *     @wifi_acked: whether frame was acked on wifi or not
  *     @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
+ *     @csum_not_inet: use CRC32c to resolve CHECKSUM_PARTIAL
  *     @dst_pending_confirm: need to confirm neighbour
   *    @napi_id: id of the NAPI struct this skb came from
  *     @secmark: security marking
@@ -646,7 +589,7 @@ struct sk_buff {
 
                        union {
                                ktime_t         tstamp;
-                               struct skb_mstamp skb_mstamp;
+                               u64             skb_mstamp;
                        };
                };
                struct rb_node  rbnode; /* used in netem & tcp stack */
@@ -744,7 +687,7 @@ struct sk_buff {
        __u8                    csum_valid:1;
        __u8                    csum_complete_sw:1;
        __u8                    csum_level:2;
-       __u8                    csum_bad:1;
+       __u8                    csum_not_inet:1;
 
        __u8                    dst_pending_confirm:1;
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
@@ -818,7 +761,7 @@ struct sk_buff {
        unsigned char           *head,
                                *data;
        unsigned int            truesize;
-       atomic_t                users;
+       refcount_t              users;
 };
 
 #ifdef __KERNEL__
@@ -915,10 +858,34 @@ static inline bool skb_pkt_type_ok(u32 ptype)
        return ptype <= PACKET_OTHERHOST;
 }
 
+static inline unsigned int skb_napi_id(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_RX_BUSY_POLL
+       return skb->napi_id;
+#else
+       return 0;
+#endif
+}
+
+/* decrement the reference count and return true if we can free the skb */
+static inline bool skb_unref(struct sk_buff *skb)
+{
+       if (unlikely(!skb))
+               return false;
+       if (likely(refcount_read(&skb->users) == 1))
+               smp_rmb();
+       else if (likely(!refcount_dec_and_test(&skb->users)))
+               return false;
+
+       return true;
+}
+
+void skb_release_head_state(struct sk_buff *skb);
 void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
 void skb_tx_error(struct sk_buff *skb);
 void consume_skb(struct sk_buff *skb);
+void consume_stateless_skb(struct sk_buff *skb);
 void  __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
 
@@ -948,7 +915,7 @@ struct sk_buff_fclones {
 
        struct sk_buff  skb2;
 
-       atomic_t        fclone_ref;
+       refcount_t      fclone_ref;
 };
 
 /**
@@ -968,7 +935,7 @@ static inline bool skb_fclone_busy(const struct sock *sk,
        fclones = container_of(skb, struct sk_buff_fclones, skb1);
 
        return skb->fclone == SKB_FCLONE_ORIG &&
-              atomic_read(&fclones->fclone_ref) > 1 &&
+              refcount_read(&fclones->fclone_ref) > 1 &&
               fclones->skb2.sk == sk;
 }
 
@@ -1001,10 +968,10 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
                                     unsigned int headroom);
 struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
                                int newtailroom, gfp_t priority);
-int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
-                       int offset, int len);
-int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset,
-                int len);
+int __must_check skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
+                                    int offset, int len);
+int __must_check skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg,
+                             int offset, int len);
 int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
 int skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)       consume_skb(a)
@@ -1316,7 +1283,7 @@ static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list,
  */
 static inline struct sk_buff *skb_get(struct sk_buff *skb)
 {
-       atomic_inc(&skb->users);
+       refcount_inc(&skb->users);
        return skb;
 }
 
@@ -1417,7 +1384,7 @@ static inline void __skb_header_release(struct sk_buff *skb)
  */
 static inline int skb_shared(const struct sk_buff *skb)
 {
-       return atomic_read(&skb->users) != 1;
+       return refcount_read(&skb->users) != 1;
 }
 
 /**
@@ -1926,41 +1893,87 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
 /*
  *     Add data to an sk_buff
  */
-unsigned char *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
-unsigned char *skb_put(struct sk_buff *skb, unsigned int len);
-static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
+void *skb_put(struct sk_buff *skb, unsigned int len);
+static inline void *__skb_put(struct sk_buff *skb, unsigned int len)
 {
-       unsigned char *tmp = skb_tail_pointer(skb);
+       void *tmp = skb_tail_pointer(skb);
        SKB_LINEAR_ASSERT(skb);
        skb->tail += len;
        skb->len  += len;
        return tmp;
 }
 
-unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
-static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+static inline void *__skb_put_zero(struct sk_buff *skb, unsigned int len)
+{
+       void *tmp = __skb_put(skb, len);
+
+       memset(tmp, 0, len);
+       return tmp;
+}
+
+static inline void *__skb_put_data(struct sk_buff *skb, const void *data,
+                                  unsigned int len)
+{
+       void *tmp = __skb_put(skb, len);
+
+       memcpy(tmp, data, len);
+       return tmp;
+}
+
+static inline void __skb_put_u8(struct sk_buff *skb, u8 val)
+{
+       *(u8 *)__skb_put(skb, 1) = val;
+}
+
+static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len)
+{
+       void *tmp = skb_put(skb, len);
+
+       memset(tmp, 0, len);
+
+       return tmp;
+}
+
+static inline void *skb_put_data(struct sk_buff *skb, const void *data,
+                                unsigned int len)
+{
+       void *tmp = skb_put(skb, len);
+
+       memcpy(tmp, data, len);
+
+       return tmp;
+}
+
+static inline void skb_put_u8(struct sk_buff *skb, u8 val)
+{
+       *(u8 *)skb_put(skb, 1) = val;
+}
+
+void *skb_push(struct sk_buff *skb, unsigned int len);
+static inline void *__skb_push(struct sk_buff *skb, unsigned int len)
 {
        skb->data -= len;
        skb->len  += len;
        return skb->data;
 }
 
-unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
-static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
+void *skb_pull(struct sk_buff *skb, unsigned int len);
+static inline void *__skb_pull(struct sk_buff *skb, unsigned int len)
 {
        skb->len -= len;
        BUG_ON(skb->len < skb->data_len);
        return skb->data += len;
 }
 
-static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int len)
+static inline void *skb_pull_inline(struct sk_buff *skb, unsigned int len)
 {
        return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
 }
 
-unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
+void *__pskb_pull_tail(struct sk_buff *skb, int delta);
 
-static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
+static inline void *__pskb_pull(struct sk_buff *skb, unsigned int len)
 {
        if (len > skb_headlen(skb) &&
            !__pskb_pull_tail(skb, len - skb_headlen(skb)))
@@ -1969,7 +1982,7 @@ static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
        return skb->data += len;
 }
 
-static inline unsigned char *pskb_pull(struct sk_buff *skb, unsigned int len)
+static inline void *pskb_pull(struct sk_buff *skb, unsigned int len)
 {
        return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len);
 }
@@ -2193,6 +2206,11 @@ static inline int skb_mac_offset(const struct sk_buff *skb)
        return skb_mac_header(skb) - skb->data;
 }
 
+static inline u32 skb_mac_header_len(const struct sk_buff *skb)
+{
+       return skb->network_header - skb->mac_header;
+}
+
 static inline int skb_mac_header_was_set(const struct sk_buff *skb)
 {
        return skb->mac_header != (typeof(skb->mac_header))~0U;
@@ -2691,7 +2709,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio);
  * @offset: the offset within the fragment (starting at the
  *          fragment's own offset)
  * @size: the number of bytes to map
- * @dir: the direction of the mapping (%PCI_DMA_*)
+ * @dir: the direction of the mapping (``PCI_DMA_*``)
  *
  * Maps the page associated with @frag to @device.
  */
@@ -2952,7 +2970,7 @@ static inline void skb_postpush_rcsum(struct sk_buff *skb,
        __skb_postpush_rcsum(skb, start, len, 0);
 }
 
-unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
+void *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
 
 /**
  *     skb_push_rcsum - push skb and update receive checksum
@@ -2965,8 +2983,7 @@ unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
  *     that the checksum difference is zero (e.g., a valid IP header)
  *     or you are setting ip_summed to CHECKSUM_NONE.
  */
-static inline unsigned char *skb_push_rcsum(struct sk_buff *skb,
-                                           unsigned int len)
+static inline void *skb_push_rcsum(struct sk_buff *skb, unsigned int len)
 {
        skb_push(skb, len);
        skb_postpush_rcsum(skb, skb->data, len);
@@ -3056,6 +3073,13 @@ static inline void skb_frag_list_init(struct sk_buff *skb)
 
 int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
                                const struct sk_buff *skb);
+struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
+                                         struct sk_buff_head *queue,
+                                         unsigned int flags,
+                                         void (*destructor)(struct sock *sk,
+                                                          struct sk_buff *skb),
+                                         int *peeked, int *off, int *err,
+                                         struct sk_buff **last);
 struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned flags,
                                        void (*destructor)(struct sock *sk,
                                                           struct sk_buff *skb),
@@ -3129,6 +3153,8 @@ struct skb_checksum_ops {
        __wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len);
 };
 
+extern const struct skb_checksum_ops *crc32c_csum_stub __read_mostly;
+
 __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
                      __wsum csum, const struct skb_checksum_ops *ops);
 __wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
@@ -3298,13 +3324,6 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
 void skb_tstamp_tx(struct sk_buff *orig_skb,
                   struct skb_shared_hwtstamps *hwtstamps);
 
-static inline void sw_tx_timestamp(struct sk_buff *skb)
-{
-       if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP &&
-           !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
-               skb_tstamp_tx(skb, NULL);
-}
-
 /**
  * skb_tx_timestamp() - Driver hook for transmit timestamping
  *
@@ -3320,7 +3339,8 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
 static inline void skb_tx_timestamp(struct sk_buff *skb)
 {
        skb_clone_tx_timestamp(skb);
-       sw_tx_timestamp(skb);
+       if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP)
+               skb_tstamp_tx(skb, NULL);
 }
 
 /**
@@ -3386,21 +3406,6 @@ static inline void __skb_incr_checksum_unnecessary(struct sk_buff *skb)
        }
 }
 
-static inline void __skb_mark_checksum_bad(struct sk_buff *skb)
-{
-       /* Mark current checksum as bad (typically called from GRO
-        * path). In the case that ip_summed is CHECKSUM_NONE
-        * this must be the first checksum encountered in the packet.
-        * When ip_summed is CHECKSUM_UNNECESSARY, this is the first
-        * checksum after the last one validated. For UDP, a zero
-        * checksum can not be marked as bad.
-        */
-
-       if (skb->ip_summed == CHECKSUM_NONE ||
-           skb->ip_summed == CHECKSUM_UNNECESSARY)
-               skb->csum_bad = 1;
-}
-
 /* Check if we need to perform checksum complete validation.
  *
  * Returns true if checksum complete is needed, false otherwise
@@ -3454,9 +3459,6 @@ static inline __sum16 __skb_checksum_validate_complete(struct sk_buff *skb,
                        skb->csum_valid = 1;
                        return 0;
                }
-       } else if (skb->csum_bad) {
-               /* ip_summed == CHECKSUM_NONE in this case */
-               return (__force __sum16)1;
        }
 
        skb->csum = psum;
@@ -3516,8 +3518,7 @@ static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto)
 
 static inline bool __skb_checksum_convert_check(struct sk_buff *skb)
 {
-       return (skb->ip_summed == CHECKSUM_NONE &&
-               skb->csum_valid && !skb->csum_bad);
+       return (skb->ip_summed == CHECKSUM_NONE && skb->csum_valid);
 }
 
 static inline void __skb_checksum_convert(struct sk_buff *skb,
@@ -3593,13 +3594,13 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
 {
-       if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
+       if (nf_bridge && refcount_dec_and_test(&nf_bridge->use))
                kfree(nf_bridge);
 }
 static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
 {
        if (nf_bridge)
-               atomic_inc(&nf_bridge->use);
+               refcount_inc(&nf_bridge->use);
 }
 #endif /* CONFIG_BRIDGE_NETFILTER */
 static inline void nf_reset(struct sk_buff *skb)