root/net/core/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. skb_put
  11. skb_push
  12. skb_pull
  13. skb_headroom
  14. skb_tailroom
  15. skb_reserve
  16. skb_trim
  17. kfree_skb
  18. alloc_skb
  19. kfree_skbmem
  20. skb_clone
  21. skb_copy
  22. skb_device_lock
  23. skb_device_unlock
  24. dev_kfree_skb
  25. dev_alloc_skb
  26. 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  *      Richard Kooijman        :       Timestamp fixes.
  11  *              Alan Cox        :       Changed buffer format.
  12  *              Alan Cox        :       destructor hook for AF_UNIX etc.
  13  *              Linus Torvalds  :       Better skb_clone.
  14  *              Alan Cox        :       Added skb_copy.
  15  *
  16  *      This program is free software; you can redistribute it and/or
  17  *      modify it under the terms of the GNU General Public License
  18  *      as published by the Free Software Foundation; either version
  19  *      2 of the License, or (at your option) any later version.
  20  */
  21 
  22 /*
  23  *      Note: There are a load of cli()/sti() pairs protecting the net_memory type
  24  *      variables. Without them for some reason the ++/-- operators do not come out
  25  *      atomic. Also with gcc 2.4.5 these counts can come out wrong anyway - use 2.5.8!!
  26  */
  27 
  28 #include <linux/config.h>
  29 #include <linux/types.h>
  30 #include <linux/kernel.h>
  31 #include <linux/sched.h>
  32 #include <asm/segment.h>
  33 #include <asm/system.h>
  34 #include <linux/mm.h>
  35 #include <linux/interrupt.h>
  36 #include <linux/in.h>
  37 #include <linux/inet.h>
  38 #include <linux/netdevice.h>
  39 #include <net/ip.h>
  40 #include <net/protocol.h>
  41 #include <linux/string.h>
  42 #include <net/route.h>
  43 #include <net/tcp.h>
  44 #include <net/udp.h>
  45 #include <linux/skbuff.h>
  46 #include <net/sock.h>
  47 
  48 
  49 /*
  50  *      Resource tracking variables
  51  */
  52 
  53 volatile unsigned long net_skbcount = 0;
  54 volatile unsigned long net_locked = 0;
  55 volatile unsigned long net_allocs = 0;
  56 volatile unsigned long net_fails  = 0;
  57 volatile unsigned long net_free_locked = 0;
  58 
  59 extern unsigned long ip_frag_mem;
  60 
  61 void show_net_buffers(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         printk("Networking buffers in use          : %lu\n",net_skbcount);
  64         printk("Network buffers locked by drivers  : %lu\n",net_locked);
  65         printk("Total network buffer allocations   : %lu\n",net_allocs);
  66         printk("Total failed network buffer allocs : %lu\n",net_fails);
  67         printk("Total free while locked events     : %lu\n",net_free_locked);
  68 #ifdef CONFIG_INET
  69         printk("IP fragment buffer size            : %lu\n",ip_frag_mem);
  70 #endif  
  71 }
  72 
  73 #if CONFIG_SKB_CHECK
  74 
  75 /*
  76  *      Debugging paranoia. Can go later when this crud stack works
  77  */
  78 
  79 int skb_check(struct sk_buff *skb, int head, int line, char *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         if (head) {
  82                 if (skb->magic_debug_cookie != SK_HEAD_SKB) {
  83                         printk("File: %s Line %d, found a bad skb-head\n",
  84                                 file,line);
  85                         return -1;
  86                 }
  87                 if (!skb->next || !skb->prev) {
  88                         printk("skb_check: head without next or prev\n");
  89                         return -1;
  90                 }
  91                 if (skb->next->magic_debug_cookie != SK_HEAD_SKB
  92                         && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
  93                         printk("File: %s Line %d, bad next head-skb member\n",
  94                                 file,line);
  95                         return -1;
  96                 }
  97                 if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
  98                         && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
  99                         printk("File: %s Line %d, bad prev head-skb member\n",
 100                                 file,line);
 101                         return -1;
 102                 }
 103 #if 0
 104                 {
 105                 struct sk_buff *skb2 = skb->next;
 106                 int i = 0;
 107                 while (skb2 != skb && i < 5) {
 108                         if (skb_check(skb2, 0, line, file) < 0) {
 109                                 printk("bad queue element in whole queue\n");
 110                                 return -1;
 111                         }
 112                         i++;
 113                         skb2 = skb2->next;
 114                 }
 115                 }
 116 #endif
 117                 return 0;
 118         }
 119         if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
 120                 && skb->next->magic_debug_cookie != SK_GOOD_SKB) {
 121                 printk("File: %s Line %d, bad next skb member\n",
 122                         file,line);
 123                 return -1;
 124         }
 125         if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
 126                 && skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
 127                 printk("File: %s Line %d, bad prev skb member\n",
 128                         file,line);
 129                 return -1;
 130         }
 131 
 132 
 133         if(skb->magic_debug_cookie==SK_FREED_SKB)
 134         {
 135                 printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
 136                         file,line);
 137                 printk("skb=%p, real size=%d, free=%d\n",
 138                         skb,skb->truesize,skb->free);
 139                 return -1;
 140         }
 141         if(skb->magic_debug_cookie!=SK_GOOD_SKB)
 142         {
 143                 printk("File: %s Line %d, passed a non skb!\n", file,line);
 144                 printk("skb=%p, real size=%d, free=%d\n",
 145                         skb,skb->truesize,skb->free);
 146                 return -1;
 147         }
 148         if(skb->head>skb->data)
 149         {
 150                 printk("File: %s Line %d, head > data !\n", file,line);
 151                 printk("skb=%p, head=%p, data=%p\n",
 152                         skb,skb->head,skb->data);
 153                 return -1;
 154         }
 155         if(skb->tail>skb->end)
 156         {
 157                 printk("File: %s Line %d, tail > end!\n", file,line);
 158                 printk("skb=%p, tail=%p, end=%p\n",
 159                         skb,skb->tail,skb->end);
 160                 return -1;
 161         }
 162         if(skb->data>skb->tail)
 163         {
 164                 printk("File: %s Line %d, data > tail!\n", file,line);
 165                 printk("skb=%p, data=%p, tail=%p\n",
 166                         skb,skb->data,skb->tail);
 167                 return -1;
 168         }
 169         if(skb->tail-skb->data!=skb->len)
 170         {
 171                 printk("File: %s Line %d, wrong length\n", file,line);
 172                 printk("skb=%p, data=%p, end=%p len=%ld\n",
 173                         skb,skb->data,skb->end,skb->len);
 174                 return -1;
 175         }
 176         if((unsigned long) skb->end > (unsigned long) skb)
 177         {
 178                 printk("File: %s Line %d, control overrun\n", file,line);
 179                 printk("skb=%p, end=%p\n",
 180                         skb,skb->end);
 181                 return -1;
 182         }
 183 
 184         /* Guess it might be acceptable then */
 185         return 0;
 186 }
 187 #endif
 188 
 189 
 190 #if CONFIG_SKB_CHECK
 191 void skb_queue_head_init(struct sk_buff_head *list)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193         list->prev = (struct sk_buff *)list;
 194         list->next = (struct sk_buff *)list;
 195         list->qlen = 0;
 196         list->magic_debug_cookie = SK_HEAD_SKB;
 197 }
 198 
 199 
 200 /*
 201  *      Insert an sk_buff at the start of a list.
 202  */
 203 void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205         unsigned long flags;
 206         struct sk_buff *list = (struct sk_buff *)list_;
 207 
 208         save_flags(flags);
 209         cli();
 210 
 211         IS_SKB(newsk);
 212         IS_SKB_HEAD(list);
 213         if (newsk->next || newsk->prev)
 214                 printk("Suspicious queue head: sk_buff on list!\n");
 215 
 216         newsk->next = list->next;
 217         newsk->prev = list;
 218 
 219         newsk->next->prev = newsk;
 220         newsk->prev->next = newsk;
 221         newsk->list = list_;
 222         list_->qlen++;
 223 
 224         restore_flags(flags);
 225 }
 226 
 227 /*
 228  *      Insert an sk_buff at the end of a list.
 229  */
 230 void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         unsigned long flags;
 233         struct sk_buff *list = (struct sk_buff *)list_;
 234 
 235         save_flags(flags);
 236         cli();
 237 
 238         if (newsk->next || newsk->prev)
 239                 printk("Suspicious queue tail: sk_buff on list!\n");
 240         IS_SKB(newsk);
 241         IS_SKB_HEAD(list);
 242 
 243         newsk->next = list;
 244         newsk->prev = list->prev;
 245 
 246         newsk->next->prev = newsk;
 247         newsk->prev->next = newsk;
 248         
 249         newsk->list = list_;
 250         list_->qlen++;
 251 
 252         restore_flags(flags);
 253 }
 254 
 255 /*
 256  *      Remove an sk_buff from a list. This routine is also interrupt safe
 257  *      so you can grab read and free buffers as another process adds them.
 258  */
 259 
 260 struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262         long flags;
 263         struct sk_buff *result;
 264         struct sk_buff *list = (struct sk_buff *)list_;
 265 
 266         save_flags(flags);
 267         cli();
 268 
 269         IS_SKB_HEAD(list);
 270 
 271         result = list->next;
 272         if (result == list) {
 273                 restore_flags(flags);
 274                 return NULL;
 275         }
 276 
 277         result->next->prev = list;
 278         list->next = result->next;
 279 
 280         result->next = NULL;
 281         result->prev = NULL;
 282         list_->qlen--;
 283         result->list = NULL;
 284         
 285         restore_flags(flags);
 286 
 287         IS_SKB(result);
 288         return result;
 289 }
 290 
 291 /*
 292  *      Insert a packet before another one in a list.
 293  */
 294 void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         unsigned long flags;
 297 
 298         IS_SKB(old);
 299         IS_SKB(newsk);
 300 
 301         if(!old->next || !old->prev)
 302                 printk("insert before unlisted item!\n");
 303         if(newsk->next || newsk->prev)
 304                 printk("inserted item is already on a list.\n");
 305 
 306         save_flags(flags);
 307         cli();
 308         newsk->next = old;
 309         newsk->prev = old->prev;
 310         old->prev = newsk;
 311         newsk->prev->next = newsk;
 312         newsk->list = old->list;
 313         newsk->list->qlen++;
 314 
 315         restore_flags(flags);
 316 }
 317 
 318 /*
 319  *      Place a packet after a given packet in a list.
 320  */
 321 void skb_append(struct sk_buff *old, struct sk_buff *newsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323         unsigned long flags;
 324 
 325         IS_SKB(old);
 326         IS_SKB(newsk);
 327 
 328         if(!old->next || !old->prev)
 329                 printk("append before unlisted item!\n");
 330         if(newsk->next || newsk->prev)
 331                 printk("append item is already on a list.\n");
 332 
 333         save_flags(flags);
 334         cli();
 335 
 336         newsk->prev = old;
 337         newsk->next = old->next;
 338         newsk->next->prev = newsk;
 339         old->next = newsk;
 340         newsk->list = old->list;
 341         newsk->list->qlen++;
 342 
 343         restore_flags(flags);
 344 }
 345 
 346 /*
 347  *      Remove an sk_buff from its list. Works even without knowing the list it
 348  *      is sitting on, which can be handy at times. It also means that THE LIST
 349  *      MUST EXIST when you unlink. Thus a list must have its contents unlinked
 350  *      _FIRST_.
 351  */
 352 void skb_unlink(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 353 {
 354         unsigned long flags;
 355 
 356         save_flags(flags);
 357         cli();
 358 
 359         IS_SKB(skb);
 360 
 361         if(skb->list)
 362         {
 363                 skb->list->qlen--;
 364                 skb->next->prev = skb->prev;
 365                 skb->prev->next = skb->next;
 366                 skb->next = NULL;
 367                 skb->prev = NULL;
 368                 skb->list = NULL;
 369         }
 370 #ifdef PARANOID_BUGHUNT_MODE    /* This is legal but we sometimes want to watch it */
 371         else
 372                 printk("skb_unlink: not a linked element\n");
 373 #endif
 374         restore_flags(flags);
 375 }
 376 
 377 /*
 378  *      Add data to an sk_buff
 379  */
 380  
 381 unsigned char *skb_put(struct sk_buff *skb, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 382 {
 383         unsigned char *tmp=skb->tail;
 384         IS_SKB(skb);
 385         skb->tail+=len;
 386         skb->len+=len;
 387         IS_SKB(skb);
 388         if(skb->tail>skb->end)
 389                 panic("skput:over: %p:%d", __builtin_return_address(0),len);
 390         return tmp;
 391 }
 392 
 393 unsigned char *skb_push(struct sk_buff *skb, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 394 {
 395         IS_SKB(skb);
 396         skb->data-=len;
 397         skb->len+=len;
 398         IS_SKB(skb);
 399         if(skb->data<skb->head)
 400                 panic("skpush:under: %p:%d", __builtin_return_address(0),len);
 401         return skb->data;
 402 }
 403 
 404 unsigned char * skb_pull(struct sk_buff *skb, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 405 {
 406         IS_SKB(skb);
 407         if(len>skb->len)
 408                 return 0;
 409         skb->data+=len;
 410         skb->len-=len;
 411         return skb->data;
 412 }
 413 
 414 int skb_headroom(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 415 {
 416         IS_SKB(skb);
 417         return skb->data-skb->head;
 418 }
 419 
 420 int skb_tailroom(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 421 {
 422         IS_SKB(skb);
 423         return skb->end-skb->tail;
 424 }
 425 
 426 void skb_reserve(struct sk_buff *skb, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 427 {
 428         IS_SKB(skb);
 429         skb->data+=len;
 430         skb->tail+=len;
 431         if(skb->tail>skb->end)
 432                 panic("sk_res: over");
 433         if(skb->data<skb->head)
 434                 panic("sk_res: under");
 435         IS_SKB(skb);
 436 }
 437 
 438 void skb_trim(struct sk_buff *skb, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 439 {
 440         IS_SKB(skb);
 441         if(skb->len>len)
 442         {
 443                 skb->len=len;
 444                 skb->tail=skb->data+len;
 445         }
 446 }
 447 
 448 
 449 
 450 #endif
 451 
 452 /*
 453  *      Free an sk_buff. This still knows about things it should
 454  *      not need to like protocols and sockets.
 455  */
 456 
 457 void kfree_skb(struct sk_buff *skb, int rw)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459         if (skb == NULL)
 460         {
 461                 printk("kfree_skb: skb = NULL (from %p)\n",
 462                         __builtin_return_address(0));
 463                 return;
 464         }
 465 #if CONFIG_SKB_CHECK
 466         IS_SKB(skb);
 467 #endif
 468         if (skb->lock)
 469         {
 470                 skb->free = 3;    /* Free when unlocked */
 471                 net_free_locked++;
 472                 return;
 473         }
 474         if (skb->free == 2)
 475                 printk("Warning: kfree_skb passed an skb that nobody set the free flag on! (from %p)\n",
 476                         __builtin_return_address(0));
 477         if (skb->list)
 478                 printk("Warning: kfree_skb passed an skb still on a list (from %p).\n",
 479                         __builtin_return_address(0));
 480 
 481         if(skb->destructor)
 482                 skb->destructor(skb);
 483         if (skb->sk)
 484         {
 485                 if(skb->sk->prot!=NULL)
 486                 {
 487                         if (rw)
 488                                 sock_rfree(skb->sk, skb);
 489                         else
 490                                 sock_wfree(skb->sk, skb);
 491 
 492                 }
 493                 else
 494                 {
 495                         unsigned long flags;
 496                         /* Non INET - default wmalloc/rmalloc handler */
 497                         save_flags(flags);
 498                         cli();
 499                         if (rw)
 500                                 skb->sk->rmem_alloc-=skb->truesize;
 501                         else
 502                                 skb->sk->wmem_alloc-=skb->truesize;
 503                         restore_flags(flags);
 504                         if(!skb->sk->dead)
 505                                 skb->sk->write_space(skb->sk);
 506                         kfree_skbmem(skb);
 507                 }
 508         }
 509         else
 510                 kfree_skbmem(skb);
 511 }
 512 
 513 /*
 514  *      Allocate a new skbuff. We do this ourselves so we can fill in a few 'private'
 515  *      fields and also do memory statistics to find all the [BEEP] leaks.
 516  */
 517 struct sk_buff *alloc_skb(unsigned int size,int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 518 {
 519         struct sk_buff *skb;
 520         unsigned long flags;
 521         int len=size;
 522         unsigned char *bptr;
 523 
 524         if (intr_count && priority!=GFP_ATOMIC) 
 525         {
 526                 static int count = 0;
 527                 if (++count < 5) {
 528                         printk("alloc_skb called nonatomically from interrupt %p\n",
 529                                 __builtin_return_address(0));
 530                         priority = GFP_ATOMIC;
 531                 }
 532         }
 533 
 534         size=(size+15)&~15;             /* Allow for alignments. Make a multiple of 16 bytes */
 535         size+=sizeof(struct sk_buff);   /* And stick the control itself on the end */
 536         
 537         /*
 538          *      Allocate some space
 539          */
 540          
 541         bptr=(unsigned char *)kmalloc(size,priority);
 542         if (bptr == NULL)
 543         {
 544                 net_fails++;
 545                 return NULL;
 546         }
 547 #ifdef PARANOID_BUGHUNT_MODE
 548         if(skb->magic_debug_cookie == SK_GOOD_SKB)
 549                 printk("Kernel kmalloc handed us an existing skb (%p)\n",skb);
 550 #endif
 551         /*
 552          *      Now we play a little game with the caches. Linux kmalloc is
 553          *      a bit cache dumb, in fact its just about maximally non 
 554          *      optimal for typical kernel buffers. We actually run faster
 555          *      by doing the following. Which is to deliberately put the
 556          *      skb at the _end_ not the start of the memory block.
 557          */
 558         net_allocs++;
 559         
 560         skb=(struct sk_buff *)(bptr+size)-1;
 561 
 562         skb->count = 1;         /* only one reference to this */
 563         skb->data_skb = NULL;   /* and we're our own data skb */
 564 
 565         skb->free = 2;  /* Invalid so we pick up forgetful users */
 566         skb->lock = 0;
 567         skb->pkt_type = PACKET_HOST;    /* Default type */
 568         skb->prev = skb->next = skb->link3 = NULL;
 569         skb->list = NULL;
 570         skb->sk = NULL;
 571         skb->truesize=size;
 572         skb->localroute=0;
 573         skb->stamp.tv_sec=0;    /* No idea about time */
 574         skb->localroute = 0;
 575         skb->ip_summed = 0;
 576         memset(skb->proto_priv, 0, sizeof(skb->proto_priv));
 577         save_flags(flags);
 578         cli();
 579         net_skbcount++;
 580         restore_flags(flags);
 581 #if CONFIG_SKB_CHECK
 582         skb->magic_debug_cookie = SK_GOOD_SKB;
 583 #endif
 584         skb->users = 0;
 585         /* Load the data pointers */
 586         skb->head=bptr;
 587         skb->data=bptr;
 588         skb->tail=bptr;
 589         skb->end=bptr+len;
 590         skb->len=0;
 591         skb->destructor=NULL;
 592         return skb;
 593 }
 594 
 595 /*
 596  *      Free an skbuff by memory
 597  */
 598 
 599 void kfree_skbmem(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 600 {
 601         unsigned long flags;
 602         void * addr = skb->head;
 603 
 604         save_flags(flags);
 605         cli();
 606         /* don't do anything if somebody still uses us */
 607         if (--skb->count <= 0) {
 608                 /* free the skb that contains the actual data if we've clone()'d */
 609                 if (skb->data_skb) {
 610                         addr = skb;
 611                         kfree_skbmem(skb->data_skb);
 612                 }
 613                 kfree(addr);
 614                 net_skbcount--;
 615         }
 616         restore_flags(flags);
 617 }
 618 
 619 /*
 620  *      Duplicate an sk_buff. The new one is not owned by a socket or locked
 621  *      and will be freed on deletion.
 622  */
 623 
 624 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 625 {
 626         struct sk_buff *n;
 627         unsigned long flags;
 628 
 629         IS_SKB(skb);
 630         n = kmalloc(sizeof(*n), priority);
 631         if (!n)
 632                 return NULL;
 633         memcpy(n, skb, sizeof(*n));
 634         n->count = 1;
 635         if (skb->data_skb)
 636                 skb = skb->data_skb;
 637         save_flags(flags);
 638         cli();
 639         skb->count++;
 640         net_allocs++;
 641         net_skbcount++;
 642         restore_flags(flags);
 643         n->data_skb = skb;
 644         n->next = n->prev = n->link3 = NULL;
 645         n->list = NULL;
 646         n->sk = NULL;
 647         n->truesize = sizeof(*n);
 648         n->free = 1;
 649         n->tries = 0;
 650         n->lock = 0;
 651         n->users = 0;
 652         n->h.raw=skb->h.raw;
 653         n->mac.raw=skb->mac.raw;
 654         n->dev=skb->dev;
 655         n->ip_hdr=skb->ip_hdr;
 656         n->saddr=skb->saddr;
 657         n->daddr=skb->daddr;
 658         n->raddr=skb->raddr;
 659         n->seq=skb->seq;
 660         n->end_seq=skb->end_seq;
 661         n->ack_seq=skb->ack_seq;
 662         n->acked=skb->acked;
 663         memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
 664         n->used=skb->used;
 665         n->arp=skb->arp;
 666         n->pkt_type=skb->pkt_type;
 667         n->stamp=skb->stamp;
 668         return n;
 669 }
 670 
 671 /*
 672  *      This is slower, and copies the whole data area 
 673  */
 674  
 675 struct sk_buff *skb_copy(struct sk_buff *skb, int priority)
     /* [previous][next][first][last][top][bottom][index][help] */
 676 {
 677         struct sk_buff *n;
 678         unsigned long offset;
 679 
 680         /*
 681          *      Allocate the copy buffer
 682          */
 683          
 684         IS_SKB(skb);
 685         
 686         n=alloc_skb(skb->truesize-sizeof(struct sk_buff),priority);
 687         if(n==NULL)
 688                 return NULL;
 689 
 690         /*
 691          *      Shift between the two data areas in bytes
 692          */
 693          
 694         offset=n->head-skb->head;
 695 
 696         /* Set the data pointer */
 697         skb_reserve(n,skb->data-skb->head);
 698         /* Set the tail pointer and length */
 699         skb_put(n,skb->len);
 700         /* Copy the bytes */
 701         memcpy(n->head,skb->head,skb->end-skb->head);
 702         n->link3=NULL;
 703         n->list=NULL;
 704         n->sk=NULL;
 705         n->when=skb->when;
 706         n->dev=skb->dev;
 707         n->h.raw=skb->h.raw+offset;
 708         n->mac.raw=skb->mac.raw+offset;
 709         n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
 710         n->saddr=skb->saddr;
 711         n->daddr=skb->daddr;
 712         n->raddr=skb->raddr;
 713         n->seq=skb->seq;
 714         n->end_seq=skb->end_seq;
 715         n->ack_seq=skb->ack_seq;
 716         n->acked=skb->acked;
 717         memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
 718         n->used=skb->used;
 719         n->free=1;
 720         n->arp=skb->arp;
 721         n->tries=0;
 722         n->lock=0;
 723         n->users=0;
 724         n->pkt_type=skb->pkt_type;
 725         n->stamp=skb->stamp;
 726         
 727         IS_SKB(n);
 728         return n;
 729 }
 730 
 731 /*
 732  *     Skbuff device locking
 733  */
 734 
 735 void skb_device_lock(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 736 {
 737         if(skb->lock)
 738                 printk("double lock on device queue!\n");
 739         else
 740                 net_locked++;
 741         skb->lock++;
 742 }
 743 
 744 void skb_device_unlock(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 745 {
 746         if(skb->lock==0)
 747                 printk("double unlock on device queue!\n");
 748         skb->lock--;
 749         if(skb->lock==0)
 750                 net_locked--;
 751 }
 752 
 753 void dev_kfree_skb(struct sk_buff *skb, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 754 {
 755         unsigned long flags;
 756 
 757         save_flags(flags);
 758         cli();
 759         if(skb->lock==1)
 760                 net_locked--;
 761 
 762         if (!--skb->lock && (skb->free == 1 || skb->free == 3))
 763         {
 764                 restore_flags(flags);
 765                 kfree_skb(skb,mode);
 766         }
 767         else
 768                 restore_flags(flags);
 769 }
 770 
 771 struct sk_buff *dev_alloc_skb(unsigned int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 772 {
 773         struct sk_buff *skb;
 774 
 775         skb = alloc_skb(length+16, GFP_ATOMIC);
 776         if (skb)
 777                 skb_reserve(skb,16);
 778         return skb;
 779 }
 780 
 781 int skb_device_locked(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 782 {
 783         return skb->lock? 1 : 0;
 784 }

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