netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Archie Cobbs <archie@precisionio.com>
To: netdev@oss.sgi.com
Cc: Archie Cobbs <archie@precisionio.com>
Subject: [PATCH] sk_buff's allocated from private pools
Date: Wed, 19 Mar 2003 14:08:34 -0800 (PST)	[thread overview]
Message-ID: <200303192208.h2JM8Yx1037110@bubba.precisionio.com> (raw)

Hello,

I'm submitting this patch for inclusion in the Linux kernel if deemed
generally useful.

The purpose of this patch is to add a new function called alloc_skb_custom()
(or whatever) that allows the data portion of an sk_buff to reside in any
memory region, not just a region returned by kmalloc(). For example, if a
networking device has a restriction on where receive buffers may reside,
then the device driver can avoid copying every incoming packet if it is
able to create an sk_buff that points to the receive buffer memory.

Basically this amounts to adding a 'free_data' function pointer to the
sk_buff structure. By default this points to kfree() but in general could
point to anywhere.

FYI FreeBSD has had equivalent functionality in its 'struct mbuf' for
many years (I'm also a FreeBSD developer).

Thanks for your review.

Cheers,
-Archie

__________________________________________________________________________
Archie Cobbs     *     Precision I/O      *     http://www.precisionio.com

Index: include/linux/skbuff.h
===================================================================
RCS file: /home/cvs/linux-2.4.20/include/linux/skbuff.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- include/linux/skbuff.h	3 Jan 2003 22:31:40 -0000	1.1.1.1
+++ include/linux/skbuff.h	15 Mar 2003 01:13:35 -0000	1.2
@@ -193,6 +193,7 @@
 	unsigned char	*tail;			/* Tail pointer					*/
 	unsigned char 	*end;			/* End pointer					*/
 
+	void 		(*free_data)(const void *);		/* Free data buffer function	*/
 	void 		(*destructor)(struct sk_buff *);	/* Destruct function		*/
 #ifdef CONFIG_NETFILTER
 	/* Can be used for communication between hooks. */
@@ -230,6 +231,8 @@
 
 extern void			__kfree_skb(struct sk_buff *skb);
 extern struct sk_buff *		alloc_skb(unsigned int size, int priority);
+extern struct sk_buff *		alloc_skb_custom(unsigned int size, int priority,
+					void (*free_data)(const void *), u8 *data);
 extern void			kfree_skbmem(struct sk_buff *skb);
 extern struct sk_buff *		skb_clone(struct sk_buff *skb, int priority);
 extern struct sk_buff *		skb_copy(const struct sk_buff *skb, int priority);
Index: net/netsyms.c
===================================================================
RCS file: /home/cvs/linux-2.4.20/net/netsyms.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- net/netsyms.c	3 Jan 2003 22:31:42 -0000	1.1.1.1
+++ net/netsyms.c	15 Mar 2003 01:13:35 -0000	1.2
@@ -489,6 +489,7 @@
 EXPORT_SYMBOL(eth_copy_and_sum);
 #endif
 EXPORT_SYMBOL(alloc_skb);
+EXPORT_SYMBOL(alloc_skb_custom);
 EXPORT_SYMBOL(__kfree_skb);
 EXPORT_SYMBOL(skb_clone);
 EXPORT_SYMBOL(skb_copy);
Index: net/core/skbuff.c
===================================================================
RCS file: /home/cvs/linux-2.4.20/net/core/skbuff.c,v
retrieving revision 1.1
retrieving revision 1.3
diff -u -r1.1 -r1.3
--- net/core/skbuff.c	7 Jan 2003 00:35:25 -0000	1.1
+++ net/core/skbuff.c	18 Mar 2003 23:14:54 -0000	1.3
@@ -149,7 +149,7 @@
  */
 
 /**
- *	alloc_skb	-	allocate a network buffer
+ *	alloc_skb	-	allocate a network buffer using kmalloc
  *	@size: size to allocate
  *	@gfp_mask: allocation mask
  *
@@ -169,8 +169,46 @@
 	if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
 		static int count = 0;
 		if (++count < 5) {
-			printk(KERN_ERR "alloc_skb called nonatomically "
-			       "from interrupt %p\n", NET_CALLER(size));
+			printk(KERN_ERR "%s called nonatomically from "
+			       "interrupt %p\n", "alloc_skb", NET_CALLER(size));
+ 			BUG();
+		}
+		gfp_mask &= ~__GFP_WAIT;
+	}
+
+	/* Get the DATA. Size must match skb_add_mtu(). */
+	size = SKB_DATA_ALIGN(size);
+	data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+	if (data == NULL)
+		return NULL;
+
+	/* Allocate the rest of the skb */
+	if ((skb = alloc_skb_custom(size, gfp_mask, kfree, data)) == NULL)
+		kfree(data);
+
+	/* Done */
+	return skb;
+}
+
+/**
+ *	alloc_skb_custom	-	allocate a network buffer
+ *					using the supplied data area
+ *
+ *	This assumes that size is aligned via SKB_DATA_ALIGN(), and
+ *	that 'data' points to size + sizeof(struct skb_shared_info)
+ *	bytes.
+ */
+ 
+struct sk_buff *alloc_skb_custom(unsigned int size, int gfp_mask,
+	void (*free_data)(const void *), u8 *data)
+{
+	struct sk_buff *skb;
+
+	if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
+		static int count = 0;
+		if (++count < 5) {
+			printk(KERN_ERR "%s called nonatomically from "
+			       "interrupt %p\n", "alloc_skb_custom", NET_CALLER(size));
  			BUG();
 		}
 		gfp_mask &= ~__GFP_WAIT;
@@ -184,11 +222,9 @@
 			goto nohead;
 	}
 
-	/* Get the DATA. Size must match skb_add_mtu(). */
-	size = SKB_DATA_ALIGN(size);
-	data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
-	if (data == NULL)
-		goto nodata;
+	/* Size must match skb_add_mtu(). */
+	if (size != SKB_DATA_ALIGN(size))
+		BUG();
 
 	/* XXX: does not include slab overhead */ 
 	skb->truesize = size + sizeof(struct sk_buff);
@@ -198,6 +234,7 @@
 	skb->data = data;
 	skb->tail = data;
 	skb->end = data + size;
+	skb->free_data = free_data;
 
 	/* Set up other state */
 	skb->len = 0;
@@ -210,8 +247,6 @@
 	skb_shinfo(skb)->frag_list = NULL;
 	return skb;
 
-nodata:
-	skb_head_to_pool(skb);
 nohead:
 	return NULL;
 }
@@ -285,7 +320,10 @@
 		if (skb_shinfo(skb)->frag_list)
 			skb_drop_fraglist(skb);
 
-		kfree(skb->head);
+		if (skb->free_data == NULL)
+			BUG();
+		(*skb->free_data)(skb->head);
+		skb->free_data = NULL;
 	}
 }
 
@@ -384,6 +422,7 @@
 	C(tail);
 	C(end);
 	n->destructor = NULL;
+	C(free_data);
 #ifdef CONFIG_NETFILTER
 	C(nfmark);
 	C(nfcache);
@@ -520,6 +559,7 @@
 
 	skb->head = data;
 	skb->end  = data + size;
+	skb->free_data = kfree;
 
 	/* Set up new pointers */
 	skb->h.raw += offset;
@@ -647,6 +687,7 @@
 
 	skb->head = data;
 	skb->end  = data+size;
+	skb->free_data = kfree;
 
 	skb->data += off;
 	skb->tail += off;

             reply	other threads:[~2003-03-19 22:08 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-03-19 22:08 Archie Cobbs [this message]
2003-03-20  9:33 ` [PATCH] sk_buff's allocated from private pools Robert Olsson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200303192208.h2JM8Yx1037110@bubba.precisionio.com \
    --to=archie@precisionio.com \
    --cc=netdev@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).