root/net/inet/skbuff.c

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

DEFINITIONS

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

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