summaryrefslogtreecommitdiff
path: root/include/linux/skbuff.h
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-02-23 03:17:24 -0800
committerDavid S. Miller <davem@nuts.davemloft.net>2005-02-23 03:17:24 -0800
commit99a54de720dcd9902cd51a77d5275fa91850036c (patch)
tree6dfdf6f955081c57dc49becb1e76ced63d59a05a /include/linux/skbuff.h
parent6a135a53cb9ef5a17b5d52f9b49a5422257b2071 (diff)
[NET]: Add skb_header_release and use it in net/ipv4/tcp
This patch adds skb_header_release which can be called when the owner of an skb no longer needs to access the header at all. What constitutes the header is left up to the users of the skb to define. For instance, for outbound TCP packets we define the header to be anything in front of the TCP payload. Therefore we add skb_header_release calls to all the paths where outound TCP packets are produced. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/skbuff.h')
-rw-r--r--include/linux/skbuff.h36
1 files changed, 34 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 23e0b48b79a4..a8b55c4f4d2f 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -146,6 +146,20 @@ struct skb_shared_info {
skb_frag_t frags[MAX_SKB_FRAGS];
};
+/* 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.
+ *
+ * All users must obey the rule that the skb->data reference count must be
+ * greater than or equal to the payload reference count.
+ *
+ * Holding a reference to the payload part means that the user does not
+ * care about modifications to the header part of skb->data.
+ */
+#define SKB_DATAREF_SHIFT 16
+#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -167,6 +181,7 @@ struct skb_shared_info {
* @csum: Checksum
* @__unused: Dead field, may be reused
* @cloned: Head may be cloned (check refcnt to be sure)
+ * @nohdr: Payload reference only, must not modify header
* @pkt_type: Packet class
* @ip_summed: Driver fed us an IP checksum
* @priority: Packet queueing priority
@@ -238,7 +253,8 @@ struct sk_buff {
mac_len,
csum;
unsigned char local_df,
- cloned,
+ cloned:1,
+ nohdr:1,
pkt_type,
ip_summed;
__u32 priority;
@@ -370,7 +386,23 @@ static inline void kfree_skb(struct sk_buff *skb)
*/
static inline int skb_cloned(const struct sk_buff *skb)
{
- return skb->cloned && atomic_read(&skb_shinfo(skb)->dataref) != 1;
+ return skb->cloned &&
+ (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
+}
+
+/**
+ * skb_header_release - release reference to header
+ * @skb: buffer to operate on
+ *
+ * Drop a reference to the header part of the buffer. This is done
+ * by acquiring a payload reference. You must not read from the header
+ * part of skb->data after this.
+ */
+static inline void skb_header_release(struct sk_buff *skb)
+{
+ BUG_ON(skb->nohdr);
+ skb->nohdr = 1;
+ atomic_add(1 << SKB_DATAREF_SHIFT, &skb_shinfo(skb)->dataref);
}
/**