Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

pbuf.h File Reference

#include "arch/cc.h"

Include dependency graph for pbuf.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pbuf

Defines

#define PBUF_TRANSPORT_HLEN   20
#define PBUF_IP_HLEN   20
#define PBUF_FLAG_RAM   0x00
#define PBUF_FLAG_ROM   0x01
#define PBUF_FLAG_POOL   0x02
#define PBUF_FLAG_REF   0x04

Enumerations

enum  pbuf_layer { PBUF_TRANSPORT, PBUF_IP, PBUF_LINK, PBUF_RAW }
enum  pbuf_flag { PBUF_RAM, PBUF_ROM, PBUF_REF, PBUF_POOL }

Functions

void pbuf_init (void)
pbufpbuf_alloc (pbuf_layer l, u16_t size, pbuf_flag flag)
void pbuf_realloc (struct pbuf *p, u16_t size)
u8_t pbuf_header (struct pbuf *p, s16_t header_size)
void pbuf_ref (struct pbuf *p)
void pbuf_ref_chain (struct pbuf *p)
u8_t pbuf_free (struct pbuf *p)
u8_t pbuf_clen (struct pbuf *p)
void pbuf_chain (struct pbuf *h, struct pbuf *t)
pbufpbuf_dechain (struct pbuf *p)
pbufpbuf_take (struct pbuf *f)


Define Documentation

#define PBUF_FLAG_POOL   0x02
 

Definition at line 60 of file pbuf.h.

Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc().

#define PBUF_FLAG_RAM   0x00
 

Definition at line 58 of file pbuf.h.

Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc().

#define PBUF_FLAG_REF   0x04
 

Definition at line 61 of file pbuf.h.

Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), pbuf_realloc(), and pbuf_take().

#define PBUF_FLAG_ROM   0x01
 

Definition at line 59 of file pbuf.h.

Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc().

#define PBUF_IP_HLEN   20
 

Definition at line 40 of file pbuf.h.

Referenced by pbuf_alloc().

#define PBUF_TRANSPORT_HLEN   20
 

Definition at line 39 of file pbuf.h.

Referenced by pbuf_alloc().


Enumeration Type Documentation

enum pbuf_flag
 

Enumeration values:
PBUF_RAM 
PBUF_ROM 
PBUF_REF 
PBUF_POOL 

Definition at line 49 of file pbuf.h.

00049              {
00050   PBUF_RAM,
00051   PBUF_ROM,
00052   PBUF_REF,
00053   PBUF_POOL
00054 } pbuf_flag;

enum pbuf_layer
 

Enumeration values:
PBUF_TRANSPORT 
PBUF_IP 
PBUF_LINK 
PBUF_RAW 

Definition at line 42 of file pbuf.h.

00042              {
00043   PBUF_TRANSPORT,
00044   PBUF_IP,
00045   PBUF_LINK,
00046   PBUF_RAW
00047 } pbuf_layer;


Function Documentation

struct pbuf* pbuf_alloc pbuf_layer  l,
u16_t  length,
pbuf_flag  flag
 

Allocates a pbuf.

The actual memory allocated for the pbuf is determined by the layer at which the pbuf is allocated and the requested size (from the size parameter).

Parameters:
flag this parameter decides how and where the pbuf should be allocated as follows:
  • PBUF_RAM: buffer memory for pbuf is allocated as one large chunk. This includes protocol headers as well.
  • PBUF_ROM: no buffer memory is allocated for the pbuf, even for protocol headers. Additional headers must be prepended by allocating another pbuf and chain in to the front of the ROM pbuf. It is assumed that the memory used is really similar to ROM in that it is immutable and will not be changed. Memory which is dynamic should generally not be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
  • PBUF_REF: no buffer memory is allocated for the pbuf, even for protocol headers. It is assumed that the pbuf is only being used in a single thread. If the pbuf gets queued, then pbuf_take should be called to copy the buffer.
  • PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from the pbuf pool that is allocated during pbuf_init().

Returns:
the allocated pbuf. If multiple pbufs where allocated, this is the first pbuf of a pbuf chain.

Definition at line 231 of file pbuf.c.

References DBG_TRACE, DEBUGF, LWIP_ASSERT, MEM_ALIGN, MEM_ALIGN_SIZE, mem_malloc(), memp_mallocp(), MEMP_PBUF, NULL, PBUF_DEBUG, PBUF_FLAG_POOL, PBUF_FLAG_RAM, PBUF_FLAG_REF, PBUF_FLAG_ROM, PBUF_IP, PBUF_IP_HLEN, PBUF_LINK, PBUF_POOL, pbuf_pool_alloc(), pbuf_pool_free(), PBUF_RAM, PBUF_RAW, PBUF_REF, PBUF_ROM, PBUF_TRANSPORT, PBUF_TRANSPORT_HLEN, s32_t, u16_t, u32_t, and u8_t.

Referenced by arp_query(), dhcp_create_request(), etharp_query(), icmp_dest_unreach(), icmp_time_exceeded(), ip_frag(), ip_reass(), loopif_output(), netbuf_alloc(), netbuf_ref(), pbuf_take(), rt_3com905cif_low_level_input(), rt_rtl8139if_low_level_input(), and slipif_input().

00232 {
00233   struct pbuf *p, *q, *r;
00234   u16_t offset;
00235   s32_t rem_len; /* remaining length */
00236 
00237   /* determine header offset */
00238   offset = 0;
00239   switch (l) {
00240   case PBUF_TRANSPORT:
00241     /* add room for transport (often TCP) layer header */
00242     offset += PBUF_TRANSPORT_HLEN;
00243     /* FALLTHROUGH */
00244   case PBUF_IP:
00245     /* add room for IP layer header */
00246     offset += PBUF_IP_HLEN;
00247     /* FALLTHROUGH */
00248   case PBUF_LINK:
00249     /* add room for link layer header */
00250     offset += PBUF_LINK_HLEN;
00251     break;
00252   case PBUF_RAW:
00253     break;
00254   default:
00255     LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
00256     return NULL;
00257   }
00258 
00259   switch (flag) {
00260   case PBUF_POOL:
00261     /* allocate head of pbuf chain into p */
00262     p = pbuf_pool_alloc();
00263     if (p == NULL) {
00264 #ifdef PBUF_STATS
00265       ++lwip_stats.pbuf.err;
00266 #endif /* PBUF_STATS */
00267       return NULL;
00268     }
00269     p->next = NULL;
00270     
00271     /* make the payload pointer point 'offset' bytes into pbuf data memory */
00272     p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
00273     LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
00274             ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
00275     /* the total length of the pbuf chain is the requested size */
00276     p->tot_len = length;
00277     /* set the length of the first pbuf in the chain */
00278     p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
00279     /* set pbuf type */
00280     p->flags = PBUF_FLAG_POOL;
00281     
00282     /* now allocate the tail of the pbuf chain */
00283     
00284     /* remember first pbuf for linkage in next iteration */
00285     r = p;
00286     /* remaining length to be allocated */
00287     rem_len = length - p->len;
00288     /* any remaining pbufs to be allocated? */
00289     while(rem_len > 0) {      
00290       q = pbuf_pool_alloc();
00291       if (q == NULL) {
00292        DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
00293 #ifdef PBUF_STATS
00294         ++lwip_stats.pbuf.err;
00295 #endif /* PBUF_STATS */
00296         /* bail out unsuccesfully */
00297         pbuf_pool_free(p);
00298         return NULL;
00299       }
00300       //q->next = NULL;
00301       /* make previous pbuf point to this pbuf */
00302       r->next = q;
00303       /* set length of this pbuf */
00304       q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
00305       q->flags = PBUF_FLAG_POOL;
00306       q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
00307       LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
00308               ((u32_t)q->payload % MEM_ALIGNMENT) == 0);
00309       q->ref = 1;
00310       /* calculate remaining length to be allocated */
00311       rem_len -= q->len;
00312       /* remember this pbuf for linkage in next iteration */
00313       r = q;
00314     }
00315     /* end of chain */
00316     r->next = NULL;
00317 
00318     break;
00319   case PBUF_RAM:
00320     /* If pbuf is to be allocated in RAM, allocate memory for it. */
00321     p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
00322     if (p == NULL) {
00323       return NULL;
00324     }
00325     /* Set up internal structure of the pbuf. */
00326     p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
00327     p->len = p->tot_len = length;
00328     p->next = NULL;
00329     p->flags = PBUF_FLAG_RAM;
00330 
00331     LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
00332            ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
00333     break;
00334   /* pbuf references existing (static constant) ROM payload? */
00335   case PBUF_ROM:
00336   /* pbuf references existing (externally allocated) RAM payload? */
00337   case PBUF_REF:
00338     /* only allocate memory for the pbuf structure */
00339     p = memp_mallocp(MEMP_PBUF);
00340     if (p == NULL) {
00341       DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_REF.\n"));
00342       return NULL;
00343     }
00344     /* caller must set this field properly, afterwards */
00345     p->payload = NULL;
00346     p->len = p->tot_len = length;
00347     p->next = NULL;
00348     p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
00349     break;
00350   default:
00351     LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
00352     return NULL;
00353   }
00354   p->ref = 1;
00355   return p;
00356 }

Here is the call graph for this function:

void pbuf_chain struct pbuf h,
struct pbuf t
 

Link two pbufs (or chains) together.

Parameters:
h head pbuf (chain)
t tail pbuf (chain)
The ->tot_len field of the first pbuf (h) is adjusted.

Definition at line 719 of file pbuf.c.

References DBG_FRESH, DEBUGF, LWIP_ASSERT, pbuf::next, NULL, PBUF_DEBUG, pbuf_ref(), and pbuf::tot_len.

Referenced by ip_frag(), netbuf_chain(), and slipif_input().

00720 {
00721   struct pbuf *p;
00722 
00723   LWIP_ASSERT("h != NULL", h != NULL);
00724   LWIP_ASSERT("t != NULL", t != NULL);
00725   
00726   /* proceed to last pbuf of chain */
00727   for (p = h; p->next != NULL; p = p->next) {
00728     /* add total length of second chain to all totals of first chain */
00729     p->tot_len += t->tot_len;
00730   }
00731   /* p is last pbuf of first h chain */
00732   /* add total length of second chain to last pbuf total of first chain */
00733   p->tot_len += t->tot_len;
00734   /* chain last pbuf of h chain (p) with first of tail (t) */
00735   p->next = t;
00736   /* t is now referenced to one more time */
00737   pbuf_ref(t);
00738   DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: referencing tail %p\n", (void *) t));
00739 }

Here is the call graph for this function:

u8_t pbuf_clen struct pbuf p  ) 
 

Count number of pbufs in a chain

Parameters:
p first pbuf of chain
Returns:
the number of pbufs in a chain

Definition at line 658 of file pbuf.c.

References len, pbuf::next, NULL, and u8_t.

00659 {
00660   u8_t len;
00661 
00662   len = 0;  
00663   while (p != NULL) {
00664     ++len;
00665     p = p->next;
00666   }
00667   return len;
00668 }

struct pbuf* pbuf_dechain struct pbuf p  ) 
 

Dechains the first pbuf from its succeeding pbufs in the chain.

Makes p->tot_len field equal to p->len.

Parameters:
p pbuf to dechain
Returns:
remainder of the pbuf chain, or NULL if it was de-allocated.

Definition at line 749 of file pbuf.c.

References DBG_STATE, DEBUGF, pbuf::len, LWIP_ASSERT, pbuf::next, NULL, PBUF_DEBUG, pbuf_free(), pbuf::tot_len, and u8_t.

00750 {
00751   struct pbuf *q;
00752   u8_t tail_gone = 1;
00753   /* tail */  
00754   q = p->next;
00755   /* pbuf has successor in chain? */
00756   if (q != NULL) {
00757     /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
00758     LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
00759     /* enforce invariant if assertion is disabled */
00760     q->tot_len = p->tot_len - p->len;
00761     /* decouple pbuf from remainder */
00762     p->next = NULL;
00763     /* total length of pbuf p is its own length only */
00764     p->tot_len = p->len;
00765     /* q is no longer referenced by p, free it */
00766     DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *) q));
00767     tail_gone = pbuf_free(q);
00768     /* return remaining tail or NULL if deallocated */
00769   }
00770   /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
00771   LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
00772   return (tail_gone > 0? NULL: q);
00773 }

Here is the call graph for this function:

u8_t pbuf_free struct pbuf p  ) 
 

Free a pbuf (chain) from usage, de-allocate non-used head of chain.

Decrements the pbuf reference count. If it reaches zero, the pbuf is deallocated.

For a pbuf chain, this is repeated for each pbuf in the chain, until a non-zero reference count is encountered, or the end of the chain is reached.

Parameters:
pbuf pbuf (chain) to be freed from one user.
Returns:
the number of unreferenced pbufs that were de-allocated from the head of the chain.
Note:
the reference counter of a pbuf equals the number of pointers that refer to the pbuf (or into the pbuf).

For internal use only.

examples:

1->2->3 becomes ...1->3 3->3->3 becomes 2->3->3 1->1->2 becomes ....->1 2->1->1 becomes 1->1->1 1->1->1 becomes .......

Definition at line 589 of file pbuf.c.

References DBG_TRACE, DEBUGF, pbuf::flags, pbuf::len, LWIP_ASSERT, mem_free(), memp_freep(), MEMP_PBUF, pbuf::next, NULL, pbuf::payload, PBUF_DEBUG, PBUF_FLAG_POOL, PBUF_FLAG_RAM, PBUF_FLAG_REF, PBUF_FLAG_ROM, PBUF_POOL_FREE, pbuf_refresh(), pbuf::ref, sys_allow_interrupts(), sys_stop_interrupts(), pbuf::tot_len, and u8_t.

Referenced by arp_arp_input(), dhcp_delete_request(), dhcp_recv(), dhcp_stop(), etharp_arp_input(), etharp_query(), etharp_tmr(), http_recv(), icmp_dest_unreach(), icmp_input(), icmp_time_exceeded(), ip_forward(), ip_frag(), ip_input(), ip_reass(), netbuf_alloc(), netbuf_delete(), netbuf_free(), netbuf_ref(), netconn_delete(), pbuf_dechain(), pbuf_realloc(), pbuf_take(), rt_3c905cif_input(), rt_rtl8139if_input(), tcpip_input(), and update_arp_entry().

00590 {
00591   struct pbuf *q;
00592   u8_t count;
00593   unsigned int state;
00594 
00595   if (p == NULL) {
00596     DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
00597     return 0;
00598   }
00599 
00600 //  PERF_START;
00601 
00602   LWIP_ASSERT("pbuf_free: sane flags",
00603     p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||
00604     p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
00605 
00606   count = 0;
00607   /* Since decrementing ref cannot be guaranteed to be a single machine operation
00608    * we must protect it. Also, the later test of ref must be protected.
00609    */
00610   sys_stop_interrupts(&state);
00611   /* de-allocate all consecutive pbufs from the head of the chain that
00612    * obtain a zero reference count */
00613   while (p != NULL) {
00614     /* all pbufs in a chain are referenced at least once */
00615     LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
00616     p->ref--;
00617     /* this pbuf is no longer referenced to? */
00618     if (p->ref == 0) {
00619       /* remember next pbuf in chain for next iteration */
00620       q = p->next;
00621       /* is this a pbuf from the pool? */
00622       if (p->flags == PBUF_FLAG_POOL) {
00623         p->len = p->tot_len = PBUF_POOL_BUFSIZE;
00624         p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
00625         PBUF_POOL_FREE(p);
00626       /* a RAM/ROM referencing pbuf */
00627       } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
00628         memp_freep(MEMP_PBUF, p);
00629       /* pbuf with data */
00630       } else {
00631         mem_free(p);
00632       }
00633       count++;
00634       /* proceed to next pbuf */
00635       p = q;
00636     /* p->ref > 0, this pbuf is still referenced to */
00637     /* (so the remaining pbufs in chain as well)    */
00638     } else {
00639       /* stop walking through chain */
00640       p = NULL;
00641     }
00642   }
00643   sys_allow_interrupts(&state);
00644   pbuf_refresh();
00645 //  PERF_STOP("pbuf_free");
00646   /* return number of de-allocated pbufs */
00647   return count;
00648 }

Here is the call graph for this function:

u8_t pbuf_header struct pbuf p,
s16_t  header_size
 

Adjusts the payload pointer to hide or reveal headers in the payload.

Adjusts the ->payload pointer so that space for a header (dis)appears in the pbuf payload.

The ->payload, ->tot_len and ->len fields are adjusted.

Parameters:
hdr_size Number of bytes to increment header size which increases the size of the pbuf. New space is on the front. (Using a negative value decreases the header size.)
PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so the call will fail. A check is made that the increase in header size does not move the payload pointer in front of the start of the buffer.
Returns:
1 on failure, 0 on success.

Definition at line 520 of file pbuf.c.

References DEBUGF, pbuf::flags, pbuf::len, pbuf::payload, PBUF_DEBUG, PBUF_FLAG_POOL, PBUF_FLAG_RAM, PBUF_FLAG_REF, PBUF_FLAG_ROM, s16_t, pbuf::tot_len, and u8_t.

Referenced by etharp_output(), icmp_input(), ip_input(), ip_output_if(), rt_3c905cif_input(), and rt_rtl8139if_input().

00521 {
00522   void *payload;
00523 
00524   /* remember current payload pointer */
00525   payload = p->payload;
00526 
00527   /* pbuf types containing payloads? */
00528   if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
00529     /* set new payload pointer */
00530     p->payload = (u8_t *)p->payload - header_size;
00531     /* boundary check fails? */
00532     if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
00533       DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
00534         (u8_t *)p->payload,
00535         (u8_t *)p + sizeof(struct pbuf)) );\
00536       /* restore old payload pointer */
00537       p->payload = payload;
00538       /* bail out unsuccesfully */
00539       return 1;
00540     }
00541   /* pbuf types refering to payloads? */
00542   } else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
00543     /* hide a header in the payload? */
00544     if ((header_size < 0) && (header_size - p->len <= 0)) {
00545       /* increase payload pointer */
00546       p->payload = (u8_t *)p->payload - header_size;
00547     } else {
00548       /* cannot expand payload to front (yet!)
00549        * bail out unsuccesfully */
00550       return 1;
00551     }
00552   }
00553   DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size) );
00554   /* modify pbuf length fields */
00555   p->len += header_size;
00556   p->tot_len += header_size;
00557 
00558   return 0;
00559 }

void pbuf_init void   ) 
 

Initializes the pbuf module.

A large part of memory is allocated for holding the pool of pbufs. The size of the individual pbufs in the pool is given by the size parameter, and the number of pbufs in the pool by the num parameter.

After the memory has been allocated, the pbufs are set up. The ->next pointer in each pbuf is set up to point to the next pbuf in the pool.

Definition at line 86 of file pbuf.c.

References pbuf::len, LWIP_ASSERT, MEM_ALIGN, pbuf::next, NULL, pbuf_pool, pbuf_pool_alloc_lock, pbuf_pool_free_lock, pbuf_pool_free_sem, pbuf_pool_memory, sys_sem_new(), u16_t, and u8_t.

00087 {
00088   struct pbuf *p, *q = NULL;
00089   u16_t i;
00090 
00091   pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
00092   LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
00093    
00094 #ifdef PBUF_STATS
00095   lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
00096 #endif /* PBUF_STATS */
00097   
00098   /* Set up ->next pointers to link the pbufs of the pool together */
00099   p = pbuf_pool;
00100   
00101   for(i = 0; i < PBUF_POOL_SIZE; ++i) {
00102     p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
00103     p->len = p->tot_len = PBUF_POOL_BUFSIZE;
00104     p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
00105     q = p;
00106     p = p->next;
00107   }
00108   
00109   /* The ->next pointer of last pbuf is NULL to indicate that there
00110      are no more pbufs in the pool */
00111   q->next = NULL;
00112 
00113 #if !SYS_LIGHTWEIGHT_PROT  
00114   pbuf_pool_alloc_lock = 0;
00115   pbuf_pool_free_lock = 0;
00116   pbuf_pool_free_sem = sys_sem_new(1);
00117 #endif  
00118 }

Here is the call graph for this function:

void pbuf_realloc struct pbuf p,
u16_t  new_len
 

Shrink a pbuf chain to a desired length.

Parameters:
p pbuf to shrink.
new_len desired new length of pbuf chain
Depending on the desired length, the first few pbufs in a chain might be skipped and left unchanged. The new last pbuf in the chain will be resized, and any remaining pbufs will be freed.

Note:
If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.

Bug:
Cannot grow the size of a pbuf (chain) (yet).

Definition at line 445 of file pbuf.c.

References pbuf::flags, pbuf::len, LWIP_ASSERT, mem_realloc(), NULL, PBUF_FLAG_POOL, PBUF_FLAG_RAM, PBUF_FLAG_REF, PBUF_FLAG_ROM, pbuf_free(), pbuf_refresh(), s16_t, pbuf::tot_len, u16_t, and u8_t.

Referenced by dhcp_discover(), dhcp_inform(), dhcp_rebind(), dhcp_release(), dhcp_renew(), dhcp_select(), ip_frag(), ip_input(), and slipif_input().

00446 {
00447   struct pbuf *q;
00448   u16_t rem_len; /* remaining length */
00449   s16_t grow;
00450 
00451   LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
00452               p->flags == PBUF_FLAG_ROM ||
00453               p->flags == PBUF_FLAG_RAM ||
00454               p->flags == PBUF_FLAG_REF);
00455 
00456   /* desired length larger than current length? */
00457   if (new_len >= p->tot_len) {
00458     /* enlarging not yet supported */
00459     return;
00460   }
00461   
00462   /* the pbuf chain grows by (new_len - p->tot_len) bytes
00463    * (which may be negative in case of shrinking) */
00464   grow = new_len - p->tot_len;
00465   
00466   /* first, step over any pbufs that should remain in the chain */
00467   rem_len = new_len;
00468   q = p;  
00469   /* this pbuf should be kept? */
00470   while (rem_len > q->len) {
00471     /* decrease remaining length by pbuf length */
00472     rem_len -= q->len;
00473     /* decrease total length indicator */
00474     q->tot_len += grow;
00475     /* proceed to next pbuf in chain */
00476     q = q->next;
00477   }
00478   /* we have now reached the new last pbuf (in q) */
00479   /* rem_len == desired length for pbuf q */  
00480 
00481   /* shrink allocated memory for PBUF_RAM */
00482   /* (other types merely adjust their length fields */
00483   if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {
00484     /* reallocate and adjust the length of the pbuf that will be split */
00485     mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
00486   }
00487   /* adjust length fields for new last pbuf */
00488   q->len = rem_len;
00489   q->tot_len = q->len;
00490 
00491   /* any remaining pbufs in chain? */
00492   if (q->next != NULL) {
00493     /* free remaining pbufs in chain */
00494     pbuf_free(q->next);
00495   }
00496   /* q is last packet in chain */
00497   q->next = NULL;
00498 
00499   pbuf_refresh();
00500 }

Here is the call graph for this function:

void pbuf_ref struct pbuf p  ) 
 

Increment the reference count of the pbuf.

Parameters:
p pbuf to increase reference counter of

Definition at line 677 of file pbuf.c.

References NULL, pbuf::ref, sys_allow_interrupts(), and sys_stop_interrupts().

Referenced by etharp_query(), and pbuf_chain().

00678 {
00679   unsigned int state;
00680   /* pbuf given? */  
00681   if (p != NULL) {
00682     sys_stop_interrupts(&state);
00683     ++(p->ref);
00684     sys_allow_interrupts(&state);
00685   }
00686 }

Here is the call graph for this function:

void pbuf_ref_chain struct pbuf p  ) 
 

Increment the reference count of all pbufs in a chain.

Parameters:
p first pbuf of chain

Definition at line 696 of file pbuf.c.

References pbuf::next, NULL, pbuf::ref, sys_allow_interrupts(), and sys_stop_interrupts().

00697 {
00698   unsigned int state;
00699   sys_stop_interrupts(&state);
00700     
00701   while (p != NULL) {
00702     ++p->ref;
00703     p = p->next;
00704   }
00705   sys_allow_interrupts(&state);
00706 }

Here is the call graph for this function:

struct pbuf* pbuf_take struct pbuf p  ) 
 

Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.

Go through a pbuf chain and replace any PBUF_REF buffers with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of the referenced data.

Note:
You MUST explicitly use p = pbuf_take(p); The pbuf you give as argument, may have been replaced by pbuf_take()!

Any replaced pbufs will be freed through pbuf_free().

Used to queue packets on behalf of the lwIP stack, such as ARP based queueing.

Parameters:
p Head of pbuf chain to process
Returns:
Pointer to new head of pbuf chain

Definition at line 797 of file pbuf.c.

References DBG_TRACE, DEBUGF, LWIP_ASSERT, NULL, pbuf_alloc(), PBUF_DEBUG, PBUF_FLAG_REF, pbuf_free(), PBUF_POOL, PBUF_RAM, and PBUF_RAW.

Referenced by etharp_query().

00798 {
00799   struct pbuf *q , *prev, *head;
00800   LWIP_ASSERT("pbuf_take: p != NULL\n", p != NULL);
00801   DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)p));
00802 
00803   prev = NULL;
00804   head = p;
00805   /* iterate through pbuf chain */
00806   do
00807   {
00808     /* pbuf is of type PBUF_REF? */
00809     if (p->flags == PBUF_FLAG_REF) {
00810       DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));
00811       /* allocate a pbuf (w/ payload) fully in RAM */
00812       /* PBUF_POOL buffers are faster if we can use them */
00813       if (p->len <= PBUF_POOL_BUFSIZE) {
00814         q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
00815         if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
00816       } else {
00817         /* no replacement pbuf yet */
00818         q = NULL;
00819         DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
00820       }
00821       /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
00822       if (q == NULL) {
00823         q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
00824         if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
00825       }
00826       /* replacement pbuf could be allocated? */
00827       if (q != NULL)
00828       {
00829         /* copy p to q */  
00830         /* copy successor */
00831         q->next = p->next;
00832         /* remove linkage from original pbuf */
00833         p->next = NULL;
00834         /* remove linkage to original pbuf */
00835         if (prev != NULL) {
00836           /* prev->next == p at this point */
00837           LWIP_ASSERT("prev->next == p", prev->next == p);
00838           /* break chain and insert new pbuf instead */
00839           prev->next = q;
00840         /* prev == NULL, so we replaced the head pbuf of the chain */
00841         } else {
00842           head = q;
00843         }
00844         /* copy pbuf payload */
00845         memcpy(q->payload, p->payload, p->len);
00846         q->tot_len = p->tot_len;
00847         q->len = p->len;
00848         /* in case p was the first pbuf, it is no longer refered to by
00849          * our caller, as the caller MUST do p = pbuf_take(p);
00850          * in case p was not the first pbuf, it is no longer refered to
00851          * by prev. we can safely free the pbuf here.
00852          * (note that we have set p->next to NULL already so that
00853          * we will not free the rest of the chain by accident.)
00854          */
00855         pbuf_free(p);
00856         /* do not copy ref, since someone else might be using the old buffer */
00857         DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q));
00858         p = q;
00859       } else {
00860         /* deallocate chain */
00861         pbuf_free(head);
00862         DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p));
00863         return NULL;
00864       }
00865     /* p->flags != PBUF_FLAG_REF */
00866     } else {
00867       DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n"));
00868     }
00869     /* remember this pbuf */
00870     prev = p;
00871     /* proceed to next pbuf in original chain */
00872     p = p->next;
00873   } while (p);
00874   DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));
00875   
00876   return head;
00877 }

Here is the call graph for this function:


Generated on Wed Jan 14 12:59:08 2004 for RTL-lwIP-0.4 by doxygen 1.3.4