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

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