patch-2.1.15 linux/net/core/skbuff.c
Next file: linux/net/core/sock.c
Previous file: linux/net/core/scm.c
Back to the patch index
Back to the overall index
- Lines: 354
- Date:
Thu Dec 12 16:54:23 1996
- Orig file:
v2.1.14/linux/net/core/skbuff.c
- Orig date:
Thu Dec 12 17:02:47 1996
diff -u --recursive --new-file v2.1.14/linux/net/core/skbuff.c linux/net/core/skbuff.c
@@ -15,12 +15,13 @@
* Alan Cox : Added all the changed routines Linus
* only put in the headers
* Ray VanTassle : Fixed --skb->lock in free
+ * Alan Cox : skb_copy copy arp field
*
- * TO FIX:
- * The __skb_ routines ought to check interrupts are disabled
- * when called, and bitch like crazy if not. Unfortunately I don't think
- * we currently have a portable way to check if interrupts are off -
- * Linus ???
+ * NOTE:
+ * The __skb_ routines should be called with interrupts
+ * disabled, or you better be *real* sure that the operation is atomic
+ * with respect to whatever list is being frobbed (e.g. via lock_sock()
+ * or via disabling bottom half handlers, etc).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -48,7 +49,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/protocol.h>
-#include <net/route.h>
+#include <net/dst.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/sock.h>
@@ -61,10 +62,8 @@
*/
atomic_t net_skbcount = 0;
-atomic_t net_locked = 0;
atomic_t net_allocs = 0;
atomic_t net_fails = 0;
-atomic_t net_free_locked = 0;
extern atomic_t ip_frag_mem;
@@ -78,10 +77,8 @@
void show_net_buffers(void)
{
printk(KERN_INFO "Networking buffers in use : %u\n",net_skbcount);
- printk(KERN_INFO "Network buffers locked by drivers : %u\n",net_locked);
printk(KERN_INFO "Total network buffer allocations : %u\n",net_allocs);
printk(KERN_INFO "Total failed network buffer allocs : %u\n",net_fails);
- printk(KERN_INFO "Total free while locked events : %u\n",net_free_locked);
#ifdef CONFIG_INET
printk(KERN_INFO "IP fragment buffer size : %u\n",ip_frag_mem);
#endif
@@ -581,57 +578,26 @@
* not need to like protocols and sockets.
*/
-void kfree_skb(struct sk_buff *skb, int rw)
+void __kfree_skb(struct sk_buff *skb)
{
+#if CONFIG_SKB_CHECK
if (skb == NULL)
{
printk(KERN_CRIT "kfree_skb: skb = NULL (from %p)\n",
- __builtin_return_address(0));
+ __builtin_return_address(0));
return;
}
-#if CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
- if (skb->lock)
- {
- skb->free = 3; /* Free when unlocked */
- net_free_locked++;
- return;
- }
- if (skb->free == 2)
- printk(KERN_WARNING "Warning: kfree_skb passed an skb that nobody set the free flag on! (from %p)\n",
- __builtin_return_address(0));
if (skb->list)
printk(KERN_WARNING "Warning: kfree_skb passed an skb still on a list (from %p).\n",
__builtin_return_address(0));
+ dst_release(skb->dst);
+
if(skb->destructor)
skb->destructor(skb);
- if (skb->sk)
- {
- struct sock * sk = skb->sk;
- if(sk->prot!=NULL)
- {
- if (rw)
- sock_rfree(sk, skb);
- else
- sock_wfree(sk, skb);
-
- }
- else
- {
- if (rw)
- atomic_sub(skb->truesize, &sk->rmem_alloc);
- else {
- if(!sk->dead)
- sk->write_space(sk);
- atomic_sub(skb->truesize, &sk->wmem_alloc);
- }
- kfree_skbmem(skb);
- }
- }
- else
- kfree_skbmem(skb);
+ kfree_skbmem(skb);
}
/*
@@ -685,33 +651,31 @@
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->data_skb = skb; /* 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 */
skb->pkt_bridged = 0; /* Not bridged */
- skb->prev = skb->next = skb->link3 = NULL;
+ skb->prev = skb->next = NULL;
skb->list = NULL;
skb->sk = NULL;
skb->truesize=size;
- skb->localroute=0;
skb->stamp.tv_sec=0; /* No idea about time */
- skb->localroute = 0;
skb->ip_summed = 0;
- memset(skb->proto_priv, 0, sizeof(skb->proto_priv));
+ skb->dst = NULL;
+ skb->destructor = NULL;
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->priority = SOPRI_NORMAL;
net_skbcount++;
#if CONFIG_SKB_CHECK
skb->magic_debug_cookie = SK_GOOD_SKB;
#endif
- skb->users = 0;
+ skb->users = 1;
/* Load the data pointers */
skb->head=bptr;
skb->data=bptr;
skb->tail=bptr;
skb->end=bptr+len;
skb->len=0;
- skb->destructor=NULL;
skb->inclone = 0;
return skb;
}
@@ -741,7 +705,7 @@
free_head = (skb->inclone != SKB_CLONE_INLINE);
/* free the skb that contains the actual data if we've clone()'d */
- if (skb->data_skb) {
+ if (skb->data_skb != skb) {
addr = skb;
__kfree_skbmem(skb->data_skb);
}
@@ -752,8 +716,7 @@
}
/*
- * Duplicate an sk_buff. The new one is not owned by a socket or locked
- * and will be freed on deletion.
+ * Duplicate an sk_buff. The new one is not owned by a socket.
*/
struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
@@ -777,20 +740,19 @@
}
memcpy(n, skb, sizeof(*n));
n->count = 1;
- if (skb->data_skb)
- skb = skb->data_skb;
+ skb = skb->data_skb;
atomic_inc(&skb->count);
atomic_inc(&net_allocs);
atomic_inc(&net_skbcount);
+ dst_clone(n->dst);
n->data_skb = skb;
- n->next = n->prev = n->link3 = NULL;
+ n->next = n->prev = NULL;
n->list = NULL;
n->sk = NULL;
- n->free = 1;
n->tries = 0;
- n->lock = 0;
- n->users = 0;
+ n->users = 1;
n->inclone = inbuff;
+ n->destructor = NULL;
return n;
}
@@ -825,82 +787,95 @@
skb_put(n,skb->len);
/* Copy the bytes */
memcpy(n->head,skb->head,skb->end-skb->head);
- n->link3=NULL;
n->list=NULL;
n->sk=NULL;
n->when=skb->when;
n->dev=skb->dev;
+ n->priority=skb->priority;
+ n->protocol=skb->protocol;
+ n->dst=dst_clone(skb->dst);
n->h.raw=skb->h.raw+offset;
+ n->nh.raw=skb->nh.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;
n->seq=skb->seq;
n->end_seq=skb->end_seq;
n->ack_seq=skb->ack_seq;
n->acked=skb->acked;
- memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
+ memcpy(n->cb, skb->cb, sizeof(skb->cb));
n->used=skb->used;
- n->free=1;
n->arp=skb->arp;
n->tries=0;
- n->lock=0;
- n->users=0;
+ n->users=1;
n->pkt_type=skb->pkt_type;
n->stamp=skb->stamp;
+ n->arp=skb->arp;
+ n->destructor = NULL;
IS_SKB(n);
return n;
}
-/*
- * Skbuff device locking
- */
-
-void skb_device_lock(struct sk_buff *skb)
+struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
{
- if(skb->lock)
- printk("double lock on device queue, lock=%d caller=%p\n",
- skb->lock, (&skb)[-1]);
- else
- net_locked++;
- skb->lock++;
-}
+ struct sk_buff *n;
+ unsigned long offset;
+ int headroom = skb_headroom(skb);
-void skb_device_unlock(struct sk_buff *skb)
-{
- if(skb->lock==0)
- printk("double unlock on device queue!\n");
- skb->lock--;
- if(skb->lock==0)
- net_locked--;
-}
+ /*
+ * Allocate the copy buffer
+ */
+
+ IS_SKB(skb);
+
+ n=alloc_skb(skb->truesize+newheadroom-headroom-sizeof(struct sk_buff), GFP_ATOMIC);
+ if(n==NULL)
+ return NULL;
-void dev_kfree_skb(struct sk_buff *skb, int mode)
-{
- unsigned long flags;
+ skb_reserve(n,newheadroom);
- save_flags(flags);
- cli();
- if(skb->lock)
- {
- net_locked--;
- skb->lock--;
- }
- if (!skb->lock && (skb->free == 1 || skb->free == 3))
- {
- restore_flags(flags);
- kfree_skb(skb,mode);
- }
- else
- restore_flags(flags);
-}
+ /*
+ * Shift between the two data areas in bytes
+ */
+
+ offset=n->data-skb->data;
+ /* Set the tail pointer and length */
+ skb_put(n,skb->len);
+ /* Copy the bytes */
+ memcpy(n->data,skb->data,skb->len);
+ n->list=NULL;
+ n->sk=NULL;
+ n->when=skb->when;
+ n->priority=skb->priority;
+ n->protocol=skb->protocol;
+ n->dev=skb->dev;
+ n->dst=dst_clone(skb->dst);
+ n->h.raw=skb->h.raw+offset;
+ n->nh.raw=skb->nh.raw+offset;
+ n->mac.raw=skb->mac.raw+offset;
+ memcpy(n->cb, skb->cb, sizeof(skb->cb));
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ n->nexthop = skb->nexthop;
+#endif
+ n->seq=skb->seq;
+ n->end_seq=skb->end_seq;
+ n->ack_seq=skb->ack_seq;
+ n->acked=skb->acked;
+ n->used=skb->used;
+ n->arp=skb->arp;
+ n->tries=0;
+ n->users=1;
+ n->pkt_type=skb->pkt_type;
+ n->stamp=skb->stamp;
+ n->destructor = NULL;
+
+ IS_SKB(n);
+ return n;
+}
+
struct sk_buff *dev_alloc_skb(unsigned int length)
{
struct sk_buff *skb;
@@ -909,9 +884,4 @@
if (skb)
skb_reserve(skb,16);
return skb;
-}
-
-int skb_device_locked(struct sk_buff *skb)
-{
- return skb->lock? 1 : 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov