236 |
offset = 0; |
offset = 0; |
237 |
switch (l) { |
switch (l) { |
238 |
case PBUF_TRANSPORT: |
case PBUF_TRANSPORT: |
239 |
|
/* add room for transport (often TCP) layer header */ |
240 |
offset += PBUF_TRANSPORT_HLEN; |
offset += PBUF_TRANSPORT_HLEN; |
241 |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
242 |
case PBUF_IP: |
case PBUF_IP: |
243 |
|
/* add room for IP layer header */ |
244 |
offset += PBUF_IP_HLEN; |
offset += PBUF_IP_HLEN; |
245 |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
246 |
case PBUF_LINK: |
case PBUF_LINK: |
247 |
|
/* add room for link layer header */ |
248 |
offset += PBUF_LINK_HLEN; |
offset += PBUF_LINK_HLEN; |
249 |
break; |
break; |
250 |
case PBUF_RAW: |
case PBUF_RAW: |
266 |
} |
} |
267 |
p->next = NULL; |
p->next = NULL; |
268 |
|
|
269 |
/* make the payload pointer point offset bytes into pbuf data memory */ |
/* make the payload pointer point 'offset' bytes into pbuf data memory */ |
270 |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
271 |
/* the total length of the pbuf is the requested size */ |
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
272 |
|
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
273 |
|
/* the total length of the pbuf chain is the requested size */ |
274 |
p->tot_len = length; |
p->tot_len = length; |
275 |
/* set the length of the first pbuf in the chain */ |
/* set the length of the first pbuf in the chain */ |
276 |
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length; |
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length; |
277 |
|
/* set pbuf type */ |
278 |
p->flags = PBUF_FLAG_POOL; |
p->flags = PBUF_FLAG_POOL; |
279 |
|
|
280 |
/* allocate the tail of the pbuf chain. */ |
/* now allocate the tail of the pbuf chain */ |
281 |
|
|
282 |
|
/* remember first pbuf for linkage in next iteration */ |
283 |
r = p; |
r = p; |
284 |
/* remaining length to be allocated */ |
/* remaining length to be allocated */ |
285 |
rem_len = length - p->len; |
rem_len = length - p->len; |
287 |
while(rem_len > 0) { |
while(rem_len > 0) { |
288 |
q = pbuf_pool_alloc(); |
q = pbuf_pool_alloc(); |
289 |
if (q == NULL) { |
if (q == NULL) { |
290 |
DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n")); |
DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n")); |
291 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
292 |
++lwip_stats.pbuf.err; |
++lwip_stats.pbuf.err; |
293 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
295 |
pbuf_pool_free(p); |
pbuf_pool_free(p); |
296 |
return NULL; |
return NULL; |
297 |
} |
} |
298 |
q->next = NULL; |
//q->next = NULL; |
299 |
|
/* make previous pbuf point to this pbuf */ |
300 |
r->next = q; |
r->next = q; |
301 |
|
/* set length of this pbuf */ |
302 |
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len; |
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len; |
303 |
q->flags = PBUF_FLAG_POOL; |
q->flags = PBUF_FLAG_POOL; |
304 |
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf)); |
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf)); |
305 |
r = q; |
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", |
306 |
|
((u32_t)q->payload % MEM_ALIGNMENT) == 0); |
307 |
q->ref = 1; |
q->ref = 1; |
308 |
|
/* calculate remaining length to be allocated */ |
309 |
rem_len -= q->len; |
rem_len -= q->len; |
310 |
|
/* remember this pbuf for linkage in next iteration */ |
311 |
|
r = q; |
312 |
} |
} |
313 |
/* end of chain */ |
/* end of chain */ |
314 |
r->next = NULL; |
r->next = NULL; |
315 |
|
|
|
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", |
|
|
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
|
316 |
break; |
break; |
317 |
case PBUF_RAM: |
case PBUF_RAM: |
318 |
/* If pbuf is to be allocated in RAM, allocate memory for it. */ |
/* If pbuf is to be allocated in RAM, allocate memory for it. */ |
498 |
} |
} |
499 |
|
|
500 |
/** |
/** |
501 |
* Adjusts the payload pointer +/- for header. |
* Adjusts the payload pointer to hide or reveal headers in the payload. |
502 |
* |
* |
503 |
* Adjusts the ->payload pointer so that space for a header appears in |
* Adjusts the ->payload pointer so that space for a header |
504 |
* the pbuf. Also, the ->tot_len and ->len fields are adjusted. |
* (dis)appears in the pbuf payload. |
505 |
|
* |
506 |
|
* The ->payload, ->tot_len and ->len fields are adjusted. |
507 |
* |
* |
508 |
* @param hdr_size Number of bytes to increment header size which |
* @param hdr_size Number of bytes to increment header size which |
509 |
* increases the size of the pbuf. New space is on the front. |
* increases the size of the pbuf. New space is on the front. |
557 |
} |
} |
558 |
|
|
559 |
/** |
/** |
560 |
* Free a pbuf (chain) from its user, de-allocate if zero users. |
* Free a pbuf (chain) from usage, de-allocate non-used head of chain. |
561 |
* |
* |
562 |
* Decrements the pbuf reference count. If it reaches |
* Decrements the pbuf reference count. If it reaches |
563 |
* zero, the pbuf is deallocated. |
* zero, the pbuf is deallocated. |
564 |
* |
* |
565 |
* This is repeated for each pbuf in the chain, until a non-zero |
* For a pbuf chain, this is repeated for each pbuf in the chain, until |
566 |
* reference count is encountered, or the end of the chain is reached. |
* a non-zero reference count is encountered, or the end of the chain is |
567 |
|
* reached. |
568 |
* |
* |
569 |
* @param pbuf pbuf (chain) to be freed from its user. |
* @param pbuf pbuf (chain) to be freed from one user. |
570 |
* |
* |
571 |
* @return the number of unreferenced pbufs that were de-allocated |
* @return the number of unreferenced pbufs that were de-allocated |
572 |
* from the head of the chain. |
* from the head of the chain. |
729 |
/* add total length of second chain to all totals of first chain */ |
/* add total length of second chain to all totals of first chain */ |
730 |
p->tot_len += t->tot_len; |
p->tot_len += t->tot_len; |
731 |
} |
} |
732 |
|
/* p is last pbuf of first h chain */ |
733 |
/* add total length of second chain to last pbuf total of first chain */ |
/* add total length of second chain to last pbuf total of first chain */ |
734 |
p->tot_len += t->tot_len; |
p->tot_len += t->tot_len; |
735 |
/* chain last pbuf of h chain (p) with first of tail (t) */ |
/* chain last pbuf of h chain (p) with first of tail (t) */ |
764 |
/* total length of pbuf p is its own length only */ |
/* total length of pbuf p is its own length only */ |
765 |
p->tot_len = p->len; |
p->tot_len = p->len; |
766 |
/* q is no longer referenced by p, free it */ |
/* q is no longer referenced by p, free it */ |
767 |
DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dechain: unreferencing %p\n", (void *) q)); |
DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *) q)); |
768 |
tail_gone = pbuf_free(q); |
tail_gone = pbuf_free(q); |
769 |
/* return remaining tail or NULL if deallocated */ |
/* return remaining tail or NULL if deallocated */ |
770 |
} |
} |
781 |
* with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of |
* with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of |
782 |
* the referenced data. |
* the referenced data. |
783 |
* |
* |
784 |
* @note The pbuf you give as argument, may have been replaced |
* @note You MUST explicitly use p = pbuf_take(p); |
785 |
* by calling pbuf_take(p). You must therefore explicitly use |
* The pbuf you give as argument, may have been replaced |
786 |
* p = pbuf_take(p); |
* by pbuf_take()! |
787 |
|
* |
788 |
* @note Any replaced pbufs will be freed through pbuf_free(). |
* @note Any replaced pbufs will be freed through pbuf_free(). |
789 |
* |
* |
790 |
* Used to queue packets on behalf of the lwIP stack, such as |
* Used to queue packets on behalf of the lwIP stack, such as |
792 |
* |
* |
793 |
* @param f Head of pbuf chain to process |
* @param f Head of pbuf chain to process |
794 |
* |
* |
795 |
* @return Pointer to new head of pbuf chain (which may have been |
* @return Pointer to new head of pbuf chain |
|
* replaced itself). |
|
796 |
*/ |
*/ |
797 |
struct pbuf * |
struct pbuf * |
798 |
pbuf_take(struct pbuf *f) |
pbuf_take(struct pbuf *f) |
799 |
{ |
{ |
800 |
struct pbuf *p, *prev, *top; |
struct pbuf *p, *prev, *top; |
801 |
LWIP_ASSERT("pbuf_take: f != NULL", f != NULL); |
LWIP_ASSERT("pbuf_take: f != NULL\n", f != NULL); |
802 |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)f)); |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)f)); |
803 |
|
|
804 |
prev = NULL; |
prev = NULL; |
830 |
} |
} |
831 |
/* replacement pbuf could be allocated? */ |
/* replacement pbuf could be allocated? */ |
832 |
if (q != NULL) |
if (q != NULL) |
833 |
{ |
{ |
834 |
|
/* copy p to q */ |
835 |
/* copy successor */ |
/* copy successor */ |
836 |
q->next = p->next; |
q->next = p->next; |
837 |
/* remove linkage from original pbuf */ |
/* remove linkage from original pbuf */ |
842 |
/* break chain and insert new pbuf instead */ |
/* break chain and insert new pbuf instead */ |
843 |
prev->next = q; |
prev->next = q; |
844 |
/* prev == NULL, so we replaced the top pbuf of the chain */ |
/* prev == NULL, so we replaced the top pbuf of the chain */ |
845 |
} else |
} else { |
846 |
top = q; |
top = q; |
847 |
|
} |
848 |
/* copy pbuf payload */ |
/* copy pbuf payload */ |
849 |
memcpy(q->payload, p->payload, p->len); |
memcpy(q->payload, p->payload, p->len); |
850 |
q->tot_len = p->tot_len; |
q->tot_len = p->tot_len; |
851 |
q->len = p->len; |
q->len = p->len; |
852 |
|
/* in case p was the first pbuf, it is no longer refered to by |
853 |
|
* our caller, as the caller MUST do p = pbuf_take(p); |
854 |
|
* in case p was not the first pbuf, it is no longer refered to |
855 |
|
* by prev. we can safely free the pbuf here. |
856 |
|
* (note that we have set p->next to NULL already so that |
857 |
|
* we will not free the rest of the chain by accident.) |
858 |
|
*/ |
859 |
|
pbuf_free(p); |
860 |
/* do not copy ref, since someone else might be using the old buffer */ |
/* do not copy ref, since someone else might be using the old buffer */ |
|
/* pbuf is not freed, as this is the responsibility of the application */ |
|
861 |
DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q)); |
DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q)); |
862 |
/* p is no longer pointed to by prev or by our caller, |
/* p is no longer pointed to by prev or by our caller, |
863 |
* as the caller must do p = pbuf_take(p); so free it |
* as the caller must do p = pbuf_take(p); so free it |
873 |
DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p)); |
DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p)); |
874 |
return NULL; |
return NULL; |
875 |
} |
} |
876 |
|
/* p->flags != PBUF_FLAG_REF */ |
877 |
|
} else { |
878 |
|
DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n")); |
879 |
} |
} |
880 |
else { |
/* remember this pbuf */ |
|
DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: not PBUF_REF\n")); |
|
|
} |
|
|
|
|
881 |
prev = p; |
prev = p; |
882 |
|
/* proceed to next pbuf in original chain */ |
883 |
p = p->next; |
p = p->next; |
884 |
} while (p); |
} while (p); |
885 |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n")); |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n")); |