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

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