/[lwip]/lwip/src/core/pbuf.c
ViewVC logotype

Diff of /lwip/src/core/pbuf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.29 by likewise, Mon Mar 31 08:34:02 2003 UTC revision 1.30 by likewise, Mon Mar 31 10:32:35 2003 UTC
# Line 1  Line 1 
1  /**  /**
2   * @file   * @file
3   * Packet buffers/chains management module   * Packet buffer management
4     *
5     * Packets are represented by the pbuf data structure. It supports dynamic
6     * memory allocation for packet contents or can reference externally
7     * managed packet contents both in RAM and ROM. Quick allocation for
8     * incoming packets is provided through pools with fixed sized pbufs.
9     *
10     * Pbufs can be chained as a singly linked list, called a pbuf chain, so
11     * that a packet may span over several pbufs.
12     *
13   */   */
14    
15  /*  /*
# Line 60  static struct pbuf *pbuf_pool_alloc_cach Line 69  static struct pbuf *pbuf_pool_alloc_cach
69  static struct pbuf *pbuf_pool_free_cache = NULL;  static struct pbuf *pbuf_pool_free_cache = NULL;
70    
71  /**  /**
  *  
72   * Initializes the pbuf module.   * Initializes the pbuf module.
73   *   *
74   * A large part of memory is allocated for holding the pool of pbufs.   * A large part of memory is allocated for holding the pool of pbufs.
# Line 189  pbuf_pool_free(struct pbuf *p) Line 197  pbuf_pool_free(struct pbuf *p)
197  }  }
198    
199  /**  /**
200     * Allocates a pbuf.
201   *   *
  * Allocates a pbuf at protocol layer l.  
202   * The actual memory allocated for the pbuf is determined by the   * The actual memory allocated for the pbuf is determined by the
203   * layer at which the pbuf is allocated and the requested size   * layer at which the pbuf is allocated and the requested size
204   * (from the size parameter). The flag parameter decides how and   * (from the size parameter).
205   * where the pbuf should be allocated as follows:   *
206     * @param flag this parameter decides how and where the pbuf
207     * should be allocated as follows:
208   *   *
209   * - PBUF_RAM: buffer memory for pbuf is allocated as one large   * - PBUF_RAM: buffer memory for pbuf is allocated as one large
210   *             chunk. This includes protocol headers as well.   *             chunk. This includes protocol headers as well.
# Line 211  pbuf_pool_free(struct pbuf *p) Line 221  pbuf_pool_free(struct pbuf *p)
221   *             then pbuf_take should be called to copy the buffer.   *             then pbuf_take should be called to copy the buffer.
222   * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from   * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
223   *              the pbuf pool that is allocated during pbuf_init().   *              the pbuf pool that is allocated during pbuf_init().
224     *
225     * @return the allocated pbuf. If multiple pbufs where allocated, this
226     * is the first pbuf of a pbuf chain.
227   */   */
228  struct pbuf *  struct pbuf *
229  pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)  pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
230  {  {
231    struct pbuf *p, *q, *r;    struct pbuf *p, *q, *r;
232    u16_t offset;    u16_t offset;
233    s32_t rem_len;    s32_t rem_len; /* remaining length */
234    
235    /* determine header offset */    /* determine header offset */
236    offset = 0;    offset = 0;
# Line 250  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 263  pbuf_alloc(pbuf_layer l, u16_t size, pbu
263      }      }
264      p->next = NULL;      p->next = NULL;
265            
266      /* make the payload pointer points offset bytes into pbuf data memory */      /* make the payload pointer point offset bytes into pbuf data memory */
267      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));      p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
268      /* the total length of the pbuf is the requested size */      /* the total length of the pbuf is the requested size */
269      p->tot_len = size;      p->tot_len = length;
270      /* set the length of the first pbuf is the chain */      /* set the length of the first pbuf in the chain */
271      p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;      p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
272      p->flags = PBUF_FLAG_POOL;      p->flags = PBUF_FLAG_POOL;
273            
274      /* allocate the tail of the pbuf chain. */      /* allocate the tail of the pbuf chain. */
275      r = p;      r = p;
276      rem_len = size - p->len;      /* remaining length to be allocated */
277        rem_len = length - p->len;
278        /* any remaining pbufs to be allocated? */
279      while(rem_len > 0) {            while(rem_len > 0) {      
280        q = pbuf_pool_alloc();        q = pbuf_pool_alloc();
281        if (q == NULL) {        if (q == NULL) {
# Line 279  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 294  pbuf_alloc(pbuf_layer l, u16_t size, pbu
294        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));        q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
295        r = q;        r = q;
296        q->ref = 1;        q->ref = 1;
297        rem_len -= PBUF_POOL_BUFSIZE;        rem_len -= q->len;
298      }      }
299      /* end of chain */      /* end of chain */
300      r->next = NULL;      r->next = NULL;
# Line 289  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 304  pbuf_alloc(pbuf_layer l, u16_t size, pbu
304      break;      break;
305    case PBUF_RAM:    case PBUF_RAM:
306      /* If pbuf is to be allocated in RAM, allocate memory for it. */      /* If pbuf is to be allocated in RAM, allocate memory for it. */
307      p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + size + offset));      p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
308      if (p == NULL) {      if (p == NULL) {
309        return NULL;        return NULL;
310      }      }
311      /* Set up internal structure of the pbuf. */      /* Set up internal structure of the pbuf. */
312      p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));      p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
313      p->len = p->tot_len = size;      p->len = p->tot_len = length;
314      p->next = NULL;      p->next = NULL;
315      p->flags = PBUF_FLAG_RAM;      p->flags = PBUF_FLAG_RAM;
316    
# Line 314  pbuf_alloc(pbuf_layer l, u16_t size, pbu Line 329  pbuf_alloc(pbuf_layer l, u16_t size, pbu
329      }      }
330      /* caller must set this field properly, afterwards */      /* caller must set this field properly, afterwards */
331      p->payload = NULL;      p->payload = NULL;
332      p->len = p->tot_len = size;      p->len = p->tot_len = length;
333      p->next = NULL;      p->next = NULL;
334      p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);      p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
335      break;      break;
# Line 471  pbuf_realloc(struct pbuf *p, u16_t new_l Line 486  pbuf_realloc(struct pbuf *p, u16_t new_l
486  }  }
487    
488  /**  /**
489   * Tries to decrease the payload pointer by the given header size.   * Tries to add a header to the payload.
490   *   *
491   * Adjusts the ->payload pointer so that space for a header appears in   * Adjusts the ->payload pointer so that space for a header appears in
492   * the pbuf. Also, the ->tot_len and ->len fields are adjusted.   * the pbuf. Also, the ->tot_len and ->len fields are adjusted.
# Line 485  u8_t Line 500  u8_t
500  pbuf_header(struct pbuf *p, s16_t header_size)  pbuf_header(struct pbuf *p, s16_t header_size)
501  {  {
502    void *payload;    void *payload;
503    /* referencing pbufs cannot be realloc()ed */  
504    /* TODO: WHY NOT? just adjust payload, tot_len and len? */    /* remember current payload pointer */
   if (p->flags == PBUF_FLAG_ROM ||  
       p->flags == PBUF_FLAG_REF) {  
     /* failure */  
     return 1;  
   }  
     
505    payload = p->payload;    payload = p->payload;
506      /* set new payload pointer */
507    p->payload = (u8_t *)p->payload - header_size;    p->payload = (u8_t *)p->payload - header_size;
508    
509    DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size));    /* pbuf types containing payloads? */
510        if (p->flags == PBUF_FLAG_RAM ||
511    /* */      p->flags == PBUF_FLAG_POOL) {
512    if((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {      /* boundary check fails? */
513      DEBUGF(PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",      if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
514                          (u8_t *)p->payload,        DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
515                          (u8_t *)p + sizeof(struct pbuf)));\          (u8_t *)p->payload,
516      /* restore old payload pointer */          (u8_t *)p + sizeof(struct pbuf)) );\
517      p->payload = payload;        /* restore old payload pointer */
518      return 1;        p->payload = payload;/
519          /* bail out unsuccesfully */
520          return 1;
521        }
522    }    }
523    
524      DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size) );
525      /* modify pbuf length fields */
526    p->len += header_size;    p->len += header_size;
527    p->tot_len += header_size;    p->tot_len += header_size;
528      
529    return 0;    return 0;
530  }  }
531    
# Line 547  pbuf_free(struct pbuf *p) Line 563  pbuf_free(struct pbuf *p)
563    SYS_ARCH_DECL_PROTECT(old_level);    SYS_ARCH_DECL_PROTECT(old_level);
564    
565    if (p == NULL) {    if (p == NULL) {
566      DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p==NULL) was called.\n"));      DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
567      return 0;      return 0;
568    }    }
569    
# Line 575  pbuf_free(struct pbuf *p) Line 591  pbuf_free(struct pbuf *p)
591      {      {
592        /* remember next pbuf in chain for next iteration */        /* remember next pbuf in chain for next iteration */
593        q = p->next;        q = p->next;
     
594        /* is this a pbuf from the pool? */        /* is this a pbuf from the pool? */
595        if (p->flags == PBUF_FLAG_POOL) {        if (p->flags == PBUF_FLAG_POOL) {
596          p->len = p->tot_len = PBUF_POOL_BUFSIZE;          p->len = p->tot_len = PBUF_POOL_BUFSIZE;
# Line 680  pbuf_chain(struct pbuf *h, struct pbuf * Line 695  pbuf_chain(struct pbuf *h, struct pbuf *
695        
696    /* proceed to last pbuf of chain */    /* proceed to last pbuf of chain */
697    for (p = h; p->next != NULL; p = p->next) {    for (p = h; p->next != NULL; p = p->next) {
698      /* add length of second chain to totals of first chain */      /* add total length of second chain to each total of first chain */
699      p->tot_len += t->tot_len;      p->tot_len += t->tot_len;
700    }    }
701    /* chain last pbuf of h chain (p) with first of tail (t) */    /* chain last pbuf of h chain (p) with first of tail (t) */
# Line 747  pbuf_take(struct pbuf *f) Line 762  pbuf_take(struct pbuf *f)
762  {  {
763    struct pbuf *p, *prev, *top;    struct pbuf *p, *prev, *top;
764    LWIP_ASSERT("pbuf_take: f != NULL", f != NULL);    LWIP_ASSERT("pbuf_take: f != NULL", f != NULL);
765    DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)", (void*)f));    DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)f));
766    
767    prev = NULL;    prev = NULL;
768    p = f;    p = f;
# Line 760  pbuf_take(struct pbuf *f) Line 775  pbuf_take(struct pbuf *f)
775      {      {
776        /* the replacement pbuf */        /* the replacement pbuf */
777        struct pbuf *q;        struct pbuf *q;
778        DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p", (void *)p));        DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));
779        /* allocate a pbuf (w/ payload) fully in RAM */        /* allocate a pbuf (w/ payload) fully in RAM */
780        /* PBUF_POOL buffers are faster if we can use them */        /* PBUF_POOL buffers are faster if we can use them */
781        if (p->len <= PBUF_POOL_BUFSIZE) {        if (p->len <= PBUF_POOL_BUFSIZE) {
782          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
783          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL"));          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
784        } else {        } else {
785          /* no replacement pbuf yet */          /* no replacement pbuf yet */
786          q = NULL;          q = NULL;
787          DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF"));          DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
788        }        }
789        /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */        /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
790        if (q == NULL) {        if (q == NULL) {
791          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);          q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
792          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM"));          if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
793        }        }
794        /* replacement pbuf could be allocated? */        /* replacement pbuf could be allocated? */
795        if (q != NULL)        if (q != NULL)
# Line 816  pbuf_take(struct pbuf *f) Line 831  pbuf_take(struct pbuf *f)
831        }        }
832      }      }
833      else {      else {
834        DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: not PBUF_REF"));        DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: not PBUF_REF\n"));
835      }      }
836    
837      prev = p;      prev = p;
838      p = p->next;      p = p->next;
839    } while (p);    } while (p);
840    DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached."));    DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));
841        
842    return top;    return top;
843  }  }

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.30

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26