root/net/inet/skbuff.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. skb_check
  2. skb_queue_head_init
  3. skb_queue_head
  4. skb_queue_tail
  5. skb_dequeue
  6. skb_insert
  7. skb_append
  8. skb_unlink
  9. skb_peek_copy
  10. kfree_skb
  11. alloc_skb
  12. kfree_skbmem
  13. skb_clone
  14. skb_kept_by_device
  15. skb_device_release
  16. skb_device_locked

   1 /*
   2  *      Routines having to do with the 'struct sk_buff' memory handlers.
   3  *
   4  *      Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
   5  *                      Florian La Roche <rzsfl@rz.uni-sb.de>
   6  *
   7  *      This program is free software; you can redistribute it and/or
   8  *      modify it under the terms of the GNU General Public License
   9  *      as published by the Free Software Foundation; either version
  10  *      2 of the License, or (at your option) any later version.
  11  */
  12  
  13 #include <linux/config.h>
  14 #include <linux/types.h>
  15 #include <linux/kernel.h>
  16 #include <linux/sched.h>
  17 #include <asm/segment.h>
  18 #include <asm/system.h>
  19 #include <linux/mm.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/in.h>
  22 #include <linux/inet.h>
  23 #include <linux/netdevice.h>
  24 #include "ip.h"
  25 #include "protocol.h"
  26 #include <linux/string.h>
  27 #include "route.h"
  28 #include "tcp.h"
  29 #include "udp.h"
  30 #include <linux/skbuff.h>
  31 #include "sock.h"
  32 
  33 
  34 /*
  35  *      Resource tracking variables
  36  */
  37  
  38 volatile unsigned long net_memory = 0;
  39 volatile unsigned long net_skbcount = 0;
  40 
  41 
  42 #if CONFIG_SKB_CHECK
  43 
  44 /*
  45  *      Debugging paranoia. Can go later when this crud stack works
  46  */ 
  47 
  48 int skb_check(struct sk_buff *skb, int head, int line, char *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         if (head) {
  51                 if (skb->magic_debug_cookie != SK_HEAD_SKB) {
  52                         printk("File: %s Line %d, found a bad skb-head\n",
  53                                 file,line);
  54                         return -1;
  55                 }
  56                 if (!skb->next || !skb->prev) {
  57                         printk("skb_check: head without next or prev\n");
  58                         return -1;
  59                 }
  60                 if (skb->next->magic_debug_cookie != SK_HEAD_SKB
  61                         && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
  62                         printk("File: %s Line %d, bad next head-skb member\n",
  63                                 file,line);
  64                         return -1;
  65                 }
  66                 if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
  67                         && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
  68                         printk("File: %s Line %d, bad prev head-skb member\n",
  69                                 file,line);
  70                         return -1;
  71                 }
  72 #if 0
  73                 {
  74                 struct sk_buff *skb2 = skb->next;
  75                 int i = 0;
  76                 while (skb2 != skb && i < 5) {
  77                         if (skb_check(skb2, 0, line, file) < 0) {
  78                                 printk("bad queue element in whole queue\n");
  79                                 return -1;
  80                         }
  81                         i++;
  82                         skb2 = skb2->next;
  83                 }
  84                 }
  85 #endif
  86                 return 0;
  87         }
  88         if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
  89                 && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
  90                 printk("File: %s Line %d, bad next skb member\n",
  91                         file,line);
  92                 return -1;
  93         }
  94         if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
  95                 && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
  96                 printk("File: %s Line %d, bad prev skb member\n",
  97                         file,line);
  98                 return -1;
  99         }
 100 
 101 
 102         if(skb->magic_debug_cookie==SK_FREED_SKB)
 103         {
 104                 printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
 105                         file,line);
 106                 printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
 107                         skb,skb->truesize,skb->mem_len,skb->free);
 108                 return -1;
 109         }
 110         if(skb->magic_debug_cookie!=SK_GOOD_SKB)
 111         {
 112                 printk("File: %s Line %d, passed a non skb!\n", file,line);
 113                 printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
 114                         skb,skb->truesize,skb->mem_len,skb->free);
 115                 return -1;
 116         }
 117         if(skb->mem_len!=skb->truesize)
 118         {
 119                 printk("File: %s Line %d, Dubious size setting!\n",file,line);
 120                 printk("skb=%p, real size=%ld, claimed size=%ld\n",
 121                         skb,skb->truesize,skb->mem_len);
 122                 return -1;
 123         }
 124         /* Guess it might be acceptable then */
 125         return 0;
 126 }
 127 #endif
 128 
 129 
 130 void skb_queue_head_init(struct sk_buff_head *list)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         list->prev = (struct sk_buff *)list;
 133         list->next = (struct sk_buff *)list;
 134 #if CONFIG_SKB_CHECK
 135         list->magic_debug_cookie = SK_HEAD_SKB;
 136 #endif
 137 }
 138 
 139 
 140 /*
 141  *      Insert an sk_buff at the start of a list.
 142  */
 143     
 144 void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         unsigned long flags;
 147         struct sk_buff *list = (struct sk_buff *)list_;
 148 
 149         save_flags(flags);
 150         cli();
 151 
 152 #if CONFIG_SKB_CHECK
 153         IS_SKB(newsk);
 154         IS_SKB_HEAD(list);
 155         if (newsk->next || newsk->prev)
 156                 printk("Suspicious queue head: sk_buff on list!\n");
 157 #endif
 158 
 159         newsk->next = list->next;
 160         newsk->prev = list;
 161 
 162         newsk->next->prev = newsk;
 163         newsk->prev->next = newsk;
 164         
 165         restore_flags(flags);
 166 }
 167 
 168 /*
 169  *      Insert an sk_buff at the end of a list.
 170  */
 171  
 172 void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         unsigned long flags;
 175         struct sk_buff *list = (struct sk_buff *)list_;
 176 
 177         save_flags(flags);
 178         cli();
 179 
 180 #if CONFIG_SKB_CHECK
 181         if (newsk->next || newsk->prev)
 182                 printk("Suspicious queue tail: sk_buff on list!\n");
 183         IS_SKB(newsk);
 184         IS_SKB_HEAD(list);
 185 #endif
 186 
 187         newsk->next = list;
 188         newsk->prev = list->prev;
 189 
 190         newsk->next->prev = newsk;
 191         newsk->prev->next = newsk;
 192 
 193         restore_flags(flags);
 194 }
 195 
 196 /*
 197  *      Remove an sk_buff from a list. This routine is also interrupt safe
 198  *      so you can grab read and free buffers as another process adds them.
 199  */
 200 
 201 struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203         long flags;
 204         struct sk_buff *result;
 205         struct sk_buff *list = (struct sk_buff *)list_;
 206 
 207         save_flags(flags);
 208         cli();
 209 
 210         IS_SKB_HEAD(list);
 211         
 212         result = list->next;
 213         if (result == list) {
 214                 restore_flags(flags);
 215                 return NULL;
 216         }
 217         
 218         result->next->prev = list;
 219         list->next = result->next;
 220 
 221         result->next = NULL;
 222         result->prev = NULL;
 223 
 224         restore_flags(flags);
 225         
 226         return result;
 227 }
 228 
 229 /*
 230  *      Insert a packet before another one in a list.
 231  */
 232  
 233 void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         unsigned long flags;
 236 
 237 #if CONFIG_SKB_CHECK
 238         IS_SKB(old);
 239         IS_SKB(newsk);
 240 
 241         if(!old->next || !old->prev)
 242                 printk("insert before unlisted item!\n");
 243         if(newsk->next || newsk->prev)
 244                 printk("inserted item is already on a list.\n");
 245 #endif
 246 
 247         save_flags(flags);
 248         cli();
 249         newsk->next = old;
 250         newsk->prev = old->prev;
 251         old->prev = newsk;
 252         newsk->prev->next = newsk;
 253         
 254         restore_flags(flags);
 255 }
 256 
 257 /*
 258  *      Place a packet after a given packet in a list.
 259  */
 260  
 261 void skb_append(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263         unsigned long flags;
 264 
 265 #if CONFIG_SKB_CHECK
 266         IS_SKB(old);
 267         IS_SKB(newsk);
 268 
 269         if(!old->next || !old->prev)
 270                 printk("append before unlisted item!\n");
 271         if(newsk->next || newsk->prev)
 272                 printk("append item is already on a list.\n");
 273 #endif
 274 
 275         save_flags(flags);
 276         cli();
 277 
 278         newsk->prev = old;
 279         newsk->next = old->next;
 280         newsk->next->prev = newsk;
 281         old->next = newsk;
 282 
 283         restore_flags(flags);
 284 }
 285 
 286 /*
 287  *      Remove an sk_buff from its list. Works even without knowing the list it
 288  *      is sitting on, which can be handy at times. It also means that THE LIST
 289  *      MUST EXIST when you unlink. Thus a list must have its contents unlinked
 290  *      _FIRST_.
 291  */
 292  
 293 void skb_unlink(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295         unsigned long flags;
 296 
 297         save_flags(flags);
 298         cli();
 299 
 300         IS_SKB(skb);
 301 
 302         if(skb->prev && skb->next)
 303         {
 304                 skb->next->prev = skb->prev;
 305                 skb->prev->next = skb->next;
 306                 skb->next = NULL;
 307                 skb->prev = NULL;
 308         }
 309 #ifdef PARANOID_BUGHUNT_MODE    /* This is legal but we sometimes want to watch it */
 310         else
 311                 printk("skb_unlink: not a linked element\n");
 312 #endif          
 313         restore_flags(flags);
 314 }
 315 
 316 /*
 317  *      Get a clone of an sk_buff. This is the safe way to peek at
 318  *      a socket queue without accidents. Its a bit long but most
 319  *      of it acutally ends up as tiny bits of inline assembler
 320  *      anyway. Only the memcpy of upto 4K with ints off is not
 321  *      as nice as I'd like.
 322  */
 323  
 324 struct sk_buff *skb_peek_copy(struct sk_buff_head *list_)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326         struct sk_buff *list = (struct sk_buff *)list_;
 327         struct sk_buff *orig,*newsk;
 328         unsigned long flags;
 329         unsigned int len;
 330         /* Now for some games to avoid races */
 331 
 332         IS_SKB_HEAD(list);
 333         do
 334         {
 335                 save_flags(flags);
 336                 cli();
 337                 orig = list->next;
 338                 if (orig == list) {
 339                         restore_flags(flags);
 340                         return NULL;
 341                 }
 342                 IS_SKB(orig);
 343                 len = orig->truesize;
 344                 restore_flags(flags);
 345 
 346                 newsk = alloc_skb(len,GFP_KERNEL);      /* May sleep */
 347 
 348                 if (newsk == NULL)              /* Oh dear... not to worry */
 349                         return NULL;
 350         
 351                 save_flags(flags);
 352                 cli();
 353                 if (list->next != orig) /* List changed go around another time */
 354                 {
 355                         restore_flags(flags);
 356                         newsk->sk = NULL;
 357                         newsk->free = 1;
 358                         newsk->mem_addr = newsk;
 359                         newsk->mem_len = len;
 360                         kfree_skb(newsk, FREE_WRITE);
 361                         continue;
 362                 }
 363                 
 364                 IS_SKB(orig);
 365                 IS_SKB(newsk);
 366                 memcpy(newsk,orig,len);
 367                 newsk->next = NULL;
 368                 newsk->prev = NULL;
 369                 newsk->mem_addr = newsk;
 370                 newsk->h.raw += ((char *)newsk - (char *)orig);
 371                 newsk->link3 = NULL;
 372                 newsk->sk = NULL;
 373                 newsk->free = 1;
 374         }
 375         while(0);
 376         
 377         restore_flags(flags);
 378         return newsk;
 379 }       
 380 
 381 /*
 382  *      Free an sk_buff. This still knows about things it should
 383  *      not need to like protocols and sockets.
 384  */
 385 
 386 void kfree_skb(struct sk_buff *skb, int rw)
     /* [previous][next][first][last][top][bottom][index][help] */
 387 {
 388         if (skb == NULL) 
 389         {
 390                 printk("kfree_skb: skb = NULL (from %08lx)\n",
 391                         ((unsigned long *) &skb)[-1]);
 392                 return;
 393         }
 394         IS_SKB(skb);
 395         if (skb->lock) 
 396         {
 397                 skb->free = 1;    /* Free when unlocked */
 398                 return;
 399         }
 400         if (skb->free == 2)
 401                 printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %08lx)\n",
 402                         ((unsigned long *) &skb)[-1]);
 403         if (skb->next)
 404                 printk("Warning: kfree_skb passed an skb still on a list (from %08lx).\n",
 405                         ((unsigned long *) &skb)[-1]);
 406         if (skb->sk) 
 407         {
 408                 if(skb->sk->prot!=NULL)
 409                 {
 410                         if (rw)
 411                                 skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
 412                         else
 413                                 skb->sk->prot->wfree(skb->sk, skb->mem_addr, skb->mem_len);
 414 
 415                 }
 416                 else
 417                 {
 418                         /* Non INET - default wmalloc/rmalloc handler */
 419                         if (rw)
 420                                 skb->sk->rmem_alloc-=skb->mem_len;
 421                         else
 422                                 skb->sk->wmem_alloc-=skb->mem_len;
 423                         if(!skb->sk->dead)
 424                                 skb->sk->write_space(skb->sk);
 425 #ifdef CONFIG_SLAVE_BALANCING                           
 426                         if(skb->in_dev_queue && skb->dev!=NULL)
 427                                 skb->dev->pkt_queue--;
 428 #endif
 429                         kfree_skbmem(skb->mem_addr,skb->mem_len);
 430                 }
 431         } 
 432         else 
 433         {
 434 #ifdef CONFIG_SLAVE_BALANCING                           
 435                 if(skb->in_dev_queue && skb->dev!=NULL)
 436                         skb->dev->pkt_queue--;
 437 #endif
 438                 kfree_skbmem(skb->mem_addr, skb->mem_len);
 439         }
 440 }
 441 
 442 /*
 443  *      Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
 444  *      fields and also do memory statistics to find all the [BEEP] leaks.
 445  */
 446  
 447  struct sk_buff *alloc_skb(unsigned int size,int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 448  {
 449         struct sk_buff *skb;
 450                 
 451         if (intr_count && priority!=GFP_ATOMIC) {
 452                 static int count = 0;
 453                 if (++count < 5) {
 454                         printk("alloc_skb called nonatomically from interrupt %08lx\n",
 455                                 ((unsigned long *)&size)[-1]);
 456                         priority = GFP_ATOMIC;
 457                 }
 458         }
 459         
 460         size+=sizeof(struct sk_buff);
 461         skb=(struct sk_buff *)kmalloc(size,priority);
 462         if (skb == NULL)
 463                 return NULL;
 464 
 465         skb->free = 2;  /* Invalid so we pick up forgetful users */
 466         skb->lock = 0;
 467         skb->truesize = size;
 468         skb->mem_len = size;
 469         skb->mem_addr = skb;
 470 #ifdef CONFIG_SLAVE_BALANCING   
 471         skb->in_dev_queue = 0;
 472 #endif  
 473         skb->fraglist = NULL;
 474         skb->prev = skb->next = NULL;
 475         skb->link3 = NULL;
 476         skb->sk = NULL;
 477         skb->stamp.tv_sec=0;    /* No idea about time */
 478         net_memory += size;
 479         net_skbcount++;
 480 #if CONFIG_SKB_CHECK
 481         skb->magic_debug_cookie = SK_GOOD_SKB;
 482 #endif
 483         skb->users = 0;
 484         return skb;
 485 }
 486 
 487 /*
 488  *      Free an skbuff by memory
 489  */     
 490 
 491 void kfree_skbmem(void *mem,unsigned size)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493 #ifdef CONFIG_SLAVE_BALANCING
 494         struct sk_buff *x = mem;
 495         unsigned long flags;
 496         save_flags(flags);
 497         cli();
 498         if(x->in_dev_queue && x->dev!=NULL)
 499                 x->dev->pkt_queue--;
 500         restore_flags(flags);
 501 #endif  
 502 #if CONFIG_SKB_CHECK
 503 #ifndef CONFIG_SLAVE_BALANCING
 504         struct sk_buff *x = mem;
 505 #endif  
 506         IS_SKB(x);
 507         if(x->magic_debug_cookie == SK_GOOD_SKB)
 508         {
 509                 x->magic_debug_cookie = SK_FREED_SKB;
 510                 kfree_s(mem,size);
 511                 net_skbcount--;
 512                 net_memory -= size;
 513         }
 514         else
 515                 printk("kfree_skbmem: bad magic cookie\n");
 516 #else
 517         kfree_s(mem, size);
 518 #endif
 519 }
 520 
 521 /*
 522  *      Duplicate an sk_buff. The new one is not owned by a socket or locked
 523  *      and will be freed on deletion.
 524  */
 525 
 526 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528         struct sk_buff *n;
 529         unsigned long offset;
 530         
 531         n=alloc_skb(skb->mem_len-sizeof(struct sk_buff),priority);
 532         if(n==NULL)
 533                 return NULL;
 534                 
 535         offset=((char *)n)-((char *)skb);
 536                 
 537         memcpy(n->data,skb->data,skb->mem_len-sizeof(struct sk_buff));
 538         n->len=skb->len;
 539         n->link3=NULL;
 540         n->sk=NULL;
 541         n->when=skb->when;
 542         n->dev=skb->dev;
 543         n->h.raw=skb->h.raw+offset;
 544         n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
 545         n->fraglen=skb->fraglen;
 546         n->fraglist=skb->fraglist;
 547         n->saddr=skb->saddr;
 548         n->daddr=skb->daddr;
 549         n->raddr=skb->raddr;
 550         n->acked=skb->acked;
 551         n->used=skb->used;
 552         n->free=1;
 553         n->arp=skb->arp;
 554         n->tries=0;
 555         n->lock=0;
 556         n->users=0;
 557         return n;
 558 }
 559         
 560         
 561 /*
 562  *     Skbuff device locking
 563  */
 564 
 565 void skb_kept_by_device(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 566 {
 567         skb->lock++;
 568 }
 569 
 570 void skb_device_release(struct sk_buff *skb, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572         unsigned long flags;
 573 
 574         save_flags(flags);
 575         cli();
 576         if (!--skb->lock && skb->free == 1)
 577                 kfree_skb(skb,mode);
 578         restore_flags(flags);
 579 }
 580 
 581 int skb_device_locked(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 582 {
 583         return skb->lock? 1 : 0;
 584 }
 585 

/* [previous][next][first][last][top][bottom][index][help] */