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

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

diff -u --recursive --new-file v1.3.43/linux/net/core/skbuff.c linux/net/core/skbuff.c
@@ -461,6 +461,7 @@
 	if (skb->next)
 	 	printk("Warning: kfree_skb passed an skb still on a list (from %p).\n",
 			__builtin_return_address(0));
+
 	if(skb->destructor)
 		skb->destructor(skb);
 	if (skb->sk)
@@ -542,6 +543,9 @@
 	
 	skb=(struct sk_buff *)(bptr+size)-1;
 
+	skb->count = 1;		/* only one reference to this */
+	skb->data_skb = NULL;	/* and we're our own data skb */
+
 	skb->free = 2;	/* Invalid so we pick up forgetful users */
 	skb->lock = 0;
 	skb->pkt_type = PACKET_HOST;	/* Default type */
@@ -579,10 +583,20 @@
 void kfree_skbmem(struct sk_buff *skb)
 {
 	unsigned long flags;
+	void * addr = skb->head;
+
 	save_flags(flags);
 	cli();
-	kfree((void *)skb->head);
-	net_skbcount--;
+	/* don't do anything if somebody still uses us */
+	if (--skb->count <= 0) {
+		/* free the skb that contains the actual data if we've clone()'d */
+		if (skb->data_skb) {
+			addr = skb;
+			kfree_skbmem(skb->data_skb);
+		}
+		kfree(addr);
+		net_skbcount--;
+	}
 	restore_flags(flags);
 }
 
@@ -590,7 +604,38 @@
  *	Duplicate an sk_buff. The new one is not owned by a socket or locked
  *	and will be freed on deletion.
  */
+#if 1
+struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
+{
+	struct sk_buff *n;
+	unsigned long flags;
 
+	IS_SKB(skb);
+	n = kmalloc(sizeof(*n), priority);
+	if (!n)
+		return NULL;
+	memcpy(n, skb, sizeof(*n));
+	n->count = 1;
+	if (skb->data_skb)
+		skb = skb->data_skb;
+	save_flags(flags);
+	cli();
+	skb->count++;
+	net_allocs++;
+	net_skbcount++;
+	restore_flags(flags);
+	n->data_skb = skb;
+	n->next = n->prev = n->link3 = NULL;
+	n->sk = NULL;
+	n->truesize = sizeof(*n);
+	n->free = 1;
+	n->tries = 0;
+	n->lock = 0;
+	n->users = 0;
+	return n;
+}
+#else
+/* this is slower, and copies the whole data area */
 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
 {
 	struct sk_buff *n;
@@ -628,6 +673,9 @@
 	n->saddr=skb->saddr;
 	n->daddr=skb->daddr;
 	n->raddr=skb->raddr;
+	n->raddr=skb->seq;
+	n->raddr=skb->end_seq;
+	n->raddr=skb->ack_seq;
 	n->acked=skb->acked;
 	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
 	n->used=skb->used;
@@ -642,7 +690,7 @@
 	IS_SKB(n);
 	return n;
 }
-
+#endif
 
 /*
  *     Skbuff device locking

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this