#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) |
pbuf * | pbuf_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) |
pbuf * | pbuf_dechain (struct pbuf *p) |
pbuf * | pbuf_take (struct pbuf *f) |
|
Definition at line 60 of file pbuf.h. Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc(). |
|
Definition at line 58 of file pbuf.h. Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc(). |
|
Definition at line 61 of file pbuf.h. Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), pbuf_realloc(), and pbuf_take(). |
|
Definition at line 59 of file pbuf.h. Referenced by pbuf_alloc(), pbuf_free(), pbuf_header(), and pbuf_realloc(). |
|
Definition at line 40 of file pbuf.h. Referenced by pbuf_alloc(). |
|
Definition at line 39 of file pbuf.h. Referenced by pbuf_alloc(). |
|
Definition at line 49 of file pbuf.h.
|
|
Definition at line 42 of file pbuf.h.
00042 { 00043 PBUF_TRANSPORT, 00044 PBUF_IP, 00045 PBUF_LINK, 00046 PBUF_RAW 00047 } pbuf_layer; |
|
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).
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:
|
Link two pbufs (or chains) together.
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:
|
Count number of pbufs in a chain
Definition at line 658 of file pbuf.c. References len, pbuf::next, NULL, and u8_t.
|
|
Dechains the first pbuf from its succeeding pbufs in the chain. Makes p->tot_len field equal to p->len.
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:
|
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.
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:
|
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.
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 } |
|
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:
|
Shrink a pbuf chain to a desired length.
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:
|
Increment the reference count of the pbuf.
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:
|
Increment the reference count of all pbufs in a 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:
|
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.
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: