patch-2.1.8 linux/net/core/skbuff.c

Next file: linux/net/core/sock.c
Previous file: linux/net/core/iovec.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.7/linux/net/core/skbuff.c linux/net/core/skbuff.c
@@ -40,12 +40,13 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/inet.h>
-#include <linux/netdevice.h>
 #include <linux/malloc.h>
+#include <linux/netdevice.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/protocol.h>
 #include <net/route.h>
 #include <net/tcp.h>
@@ -702,6 +703,7 @@
 	skb->end=bptr+len;
 	skb->len=0;
 	skb->destructor=NULL;
+	skb->inclone = 0;
 	return skb;
 }
 
@@ -729,7 +731,8 @@
 			addr = skb;
 			__kfree_skbmem(skb->data_skb);
 		}
-		kfree(addr);
+		if (!skb->inclone)
+			kfree(addr);
 		atomic_dec(&net_skbcount);
 	}
 }
@@ -742,11 +745,21 @@
 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
 {
 	struct sk_buff *n;
-
+	int inbuff = 0;
+	
 	IS_SKB(skb);
-	n = kmalloc(sizeof(*n), priority);
-	if (!n)
-		return NULL;
+	if (skb_tailroom(skb) >= sizeof(struct sk_buff))
+	{
+		n = ((struct sk_buff *) skb->end) - 1;
+		skb->end -= sizeof(struct sk_buff);
+		inbuff = 1;
+	}
+	else
+	{
+		n = kmalloc(sizeof(*n), priority);
+		if (!n)
+			return NULL;
+	}
 	memcpy(n, skb, sizeof(*n));
 	n->count = 1;
 	if (skb->data_skb)
@@ -762,6 +775,7 @@
 	n->tries = 0;
 	n->lock = 0;
 	n->users = 0;
+	n->inclone = inbuff;
 	return n;
 }
 
@@ -804,6 +818,10 @@
 	n->h.raw=skb->h.raw+offset;
 	n->mac.raw=skb->mac.raw+offset;
 	n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	n->ipv6_hdr=(struct ipv6hdr *)(((char *)skb->ipv6_hdr)+offset);
+	n->nexthop = skb->nexthop;
+#endif
 	n->saddr=skb->saddr;
 	n->daddr=skb->daddr;
 	n->raddr=skb->raddr;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov