patch-1.3.6 linux/net/core/skbuff.c
Next file: linux/net/core/sock.c
Previous file: linux/net/core/dev.c
Back to the patch index
Back to the overall index
- Lines: 396
- Date:
Thu Jun 29 21:26:15 1995
- Orig file:
v1.3.5/linux/net/core/skbuff.c
- Orig date:
Tue Jun 6 12:16:43 1995
diff -u --recursive --new-file v1.3.5/linux/net/core/skbuff.c linux/net/core/skbuff.c
@@ -6,8 +6,9 @@
*
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
- * Dave Platt : Interrupt stacking fix
+ * Dave Platt : Interrupt stacking fix.
* Richard Kooijman : Timestamp fixes.
+ * Alan Cox : Changed buffer format.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -46,7 +47,6 @@
* Resource tracking variables
*/
-volatile unsigned long net_memory = 0;
volatile unsigned long net_skbcount = 0;
volatile unsigned long net_locked = 0;
volatile unsigned long net_allocs = 0;
@@ -56,7 +56,6 @@
void show_net_buffers(void)
{
printk("Networking buffers in use : %lu\n",net_skbcount);
- printk("Memory committed to network buffers: %lu\n",net_memory);
printk("Network buffers locked by drivers : %lu\n",net_locked);
printk("Total network buffer allocations : %lu\n",net_allocs);
printk("Total failed network buffer allocs : %lu\n",net_fails);
@@ -127,24 +126,53 @@
{
printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
+ printk("skb=%p, real size=%d, free=%d\n",
+ skb,skb->truesize,skb->free);
return -1;
}
if(skb->magic_debug_cookie!=SK_GOOD_SKB)
{
printk("File: %s Line %d, passed a non skb!\n", file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
+ printk("skb=%p, real size=%d, free=%d\n",
+ skb,skb->truesize,skb->free);
return -1;
}
- if(skb->mem_len!=skb->truesize)
+ if(skb->head>skb->data)
{
- printk("File: %s Line %d, Dubious size setting!\n",file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld\n",
- skb,skb->truesize,skb->mem_len);
+ printk("File: %s Line %d, head > data !\n", file,line);
+ printk("skb=%p, head=%p, data=%p\n",
+ skb,skb->head,skb->data);
return -1;
}
+ if(skb->tail>skb->end)
+ {
+ printk("File: %s Line %d, tail > end!\n", file,line);
+ printk("skb=%p, tail=%p, end=%p\n",
+ skb,skb->tail,skb->end);
+ return -1;
+ }
+ if(skb->data>skb->tail)
+ {
+ printk("File: %s Line %d, data > tail!\n", file,line);
+ printk("skb=%p, data=%p, tail=%p\n",
+ skb,skb->data,skb->tail);
+ return -1;
+ }
+ if(skb->tail-skb->data!=skb->len)
+ {
+ printk("File: %s Line %d, wrong length\n", file,line);
+ printk("skb=%p, data=%p, end=%p len=%ld\n",
+ skb,skb->data,skb->end,skb->len);
+ return -1;
+ }
+ if((unsigned long) skb->end > (unsigned long) skb)
+ {
+ printk("File: %s Line %d, control overrun\n", file,line);
+ printk("skb=%p, end=%p\n",
+ skb,skb->end);
+ return -1;
+ }
+
/* Guess it might be acceptable then */
return 0;
}
@@ -324,6 +352,79 @@
restore_flags(flags);
}
+/*
+ * Add data to an sk_buff
+ */
+
+unsigned char *skb_put(struct sk_buff *skb, int len)
+{
+ unsigned char *tmp=skb->tail;
+ IS_SKB(skb);
+ skb->tail+=len;
+ skb->len+=len;
+ IS_SKB(skb);
+ if(skb->tail>skb->end)
+ panic("skput:over: %p:%d", __builtin_return_address(0),len);
+ return tmp;
+}
+
+unsigned char *skb_push(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ skb->data-=len;
+ skb->len+=len;
+ IS_SKB(skb);
+ if(skb->data<skb->head)
+ panic("skpush:under: %p:%d", __builtin_return_address(0),len);
+ return skb->data;
+}
+
+int skb_pull(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ if(len>skb->len)
+ len=skb->len;
+ skb->data+=len;
+ skb->len-=len;
+ return len;
+}
+
+int skb_headroom(struct sk_buff *skb)
+{
+ IS_SKB(skb);
+ return skb->data-skb->head;
+}
+
+int skb_tailroom(struct sk_buff *skb)
+{
+ IS_SKB(skb);
+ return skb->end-skb->tail;
+}
+
+void skb_reserve(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ skb->data+=len;
+ skb->tail+=len;
+ if(skb->tail>skb->end)
+ panic("sk_res: over");
+ if(skb->data<skb->head)
+ panic("sk_res: under");
+ IS_SKB(skb);
+}
+
+void skb_trim(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ if(skb->len>len)
+ {
+ skb->len=len;
+ skb->tail=skb->data+len;
+ }
+}
+
+
+
#endif
/*
@@ -359,9 +460,9 @@
if(skb->sk->prot!=NULL)
{
if (rw)
- skb->sk->prot->rfree(skb->sk, skb, skb->mem_len);
+ skb->sk->prot->rfree(skb->sk, skb);
else
- skb->sk->prot->wfree(skb->sk, skb, skb->mem_len);
+ skb->sk->prot->wfree(skb->sk, skb);
}
else
@@ -371,17 +472,17 @@
save_flags(flags);
cli();
if (rw)
- skb->sk->rmem_alloc-=skb->mem_len;
+ skb->sk->rmem_alloc-=skb->truesize;
else
- skb->sk->wmem_alloc-=skb->mem_len;
+ skb->sk->wmem_alloc-=skb->truesize;
restore_flags(flags);
if(!skb->sk->dead)
skb->sk->write_space(skb->sk);
- kfree_skbmem(skb,skb->mem_len);
+ kfree_skbmem(skb);
}
}
else
- kfree_skbmem(skb, skb->mem_len);
+ kfree_skbmem(skb);
}
/*
@@ -392,8 +493,11 @@
{
struct sk_buff *skb;
unsigned long flags;
+ int len=size;
+ unsigned char *bptr;
- if (intr_count && priority!=GFP_ATOMIC) {
+ if (intr_count && priority!=GFP_ATOMIC)
+ {
static int count = 0;
if (++count < 5) {
printk("alloc_skb called nonatomically from interrupt %p\n",
@@ -402,9 +506,15 @@
}
}
- size+=sizeof(struct sk_buff);
- skb=(struct sk_buff *)kmalloc(size,priority);
- if (skb == NULL)
+ size=(size+15)&~15; /* Allow for alignments. Make a multiple of 16 bytes */
+ size+=sizeof(struct sk_buff); /* And stick the control itself on the end */
+
+ /*
+ * Allocate some space
+ */
+
+ bptr=(unsigned char *)kmalloc(size,priority);
+ if (bptr == NULL)
{
net_fails++;
return NULL;
@@ -413,34 +523,41 @@
if(skb->magic_debug_cookie == SK_GOOD_SKB)
printk("Kernel kmalloc handed us an existing skb (%p)\n",skb);
#endif
-
+ /*
+ * Now we play a little game with the caches. Linux kmalloc is
+ * a bit cache dumb, in fact its just about maximally non
+ * optimal for typical kernel buffers. We actually run faster
+ * by doing the following. Which is to deliberately put the
+ * skb at the _end_ not the start of the memory block.
+ */
net_allocs++;
+
+ skb=(struct sk_buff *)(bptr+size)-1;
skb->free = 2; /* Invalid so we pick up forgetful users */
skb->lock = 0;
skb->pkt_type = PACKET_HOST; /* Default type */
- skb->truesize = size;
- skb->mem_len = size;
- skb->mem_addr = skb;
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue = 0;
-#endif
- skb->fraglist = NULL;
skb->prev = skb->next = NULL;
skb->link3 = NULL;
skb->sk = NULL;
+ skb->truesize=size;
skb->localroute=0;
skb->stamp.tv_sec=0; /* No idea about time */
skb->localroute = 0;
save_flags(flags);
cli();
- net_memory += size;
net_skbcount++;
restore_flags(flags);
#if CONFIG_SKB_CHECK
skb->magic_debug_cookie = SK_GOOD_SKB;
#endif
skb->users = 0;
+ /* Load the data pointers */
+ skb->head=bptr;
+ skb->data=bptr;
+ skb->tail=bptr;
+ skb->end=bptr+len;
+ skb->len=0;
return skb;
}
@@ -448,42 +565,14 @@
* Free an skbuff by memory
*/
-void kfree_skbmem(struct sk_buff *skb,unsigned size)
+void kfree_skbmem(struct sk_buff *skb)
{
unsigned long flags;
-#ifdef CONFIG_SLAVE_BALANCING
- save_flags(flags);
- cli();
- if(skb->in_dev_queue && skb->dev!=NULL)
- skb->dev->pkt_queue--;
- restore_flags(flags);
-#endif
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
- if(size!=skb->truesize)
- printk("kfree_skbmem: size mismatch.\n");
-
- if(skb->magic_debug_cookie == SK_GOOD_SKB)
- {
- save_flags(flags);
- cli();
- IS_SKB(skb);
- skb->magic_debug_cookie = SK_FREED_SKB;
- kfree_s((void *)skb,size);
- net_skbcount--;
- net_memory -= size;
- restore_flags(flags);
- }
- else
- printk("kfree_skbmem: bad magic cookie\n");
-#else
save_flags(flags);
cli();
- kfree_s((void *)skb,size);
+ kfree((void *)skb->head);
net_skbcount--;
- net_memory -= size;
restore_flags(flags);
-#endif
}
/*
@@ -496,22 +585,34 @@
struct sk_buff *n;
unsigned long offset;
- n=alloc_skb(skb->mem_len-sizeof(struct sk_buff),priority);
+ /*
+ * Allocate the copy buffer
+ */
+
+ IS_SKB(skb);
+
+ n=alloc_skb(skb->truesize-sizeof(struct sk_buff),priority);
if(n==NULL)
return NULL;
- offset=((char *)n)-((char *)skb);
-
- memcpy(n->data,skb->data,skb->mem_len-sizeof(struct sk_buff));
- n->len=skb->len;
+ /*
+ * Shift between the two data areas in bytes
+ */
+
+ offset=n->head-skb->head;
+
+ /* Set the data pointer */
+ skb_reserve(n,skb->data-skb->head);
+ /* Set the tail pointer and length */
+ skb_put(n,skb->len);
+ /* Copy the bytes */
+ memcpy(n->head,skb->head,skb->end-skb->head);
n->link3=NULL;
n->sk=NULL;
n->when=skb->when;
n->dev=skb->dev;
n->h.raw=skb->h.raw+offset;
n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
- n->fraglen=skb->fraglen;
- n->fraglist=skb->fraglist;
n->saddr=skb->saddr;
n->daddr=skb->daddr;
n->raddr=skb->raddr;
@@ -524,6 +625,8 @@
n->users=0;
n->pkt_type=skb->pkt_type;
n->stamp=skb->stamp;
+
+ IS_SKB(n);
return n;
}
@@ -566,6 +669,13 @@
}
else
restore_flags(flags);
+}
+
+struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ struct sk_buff *skb=alloc_skb(length+16, GFP_ATOMIC);
+ skb_reserve(skb,16);
+ return skb;
}
int skb_device_locked(struct sk_buff *skb)
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