]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/pbuf.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / pbuf.c
1 /**\r
2  * @file\r
3  * Packet buffer management\r
4  *\r
5  * Packets are built from the pbuf data structure. It supports dynamic\r
6  * memory allocation for packet contents or can reference externally\r
7  * managed packet contents both in RAM and ROM. Quick allocation for\r
8  * incoming packets is provided through pools with fixed sized pbufs.\r
9  *\r
10  * A packet may span over multiple pbufs, chained as a singly linked\r
11  * list. This is called a "pbuf chain".\r
12  *\r
13  * Multiple packets may be queued, also using this singly linked list.\r
14  * This is called a "packet queue".\r
15  * \r
16  * So, a packet queue consists of one or more pbuf chains, each of\r
17  * which consist of one or more pbufs. Currently, queues are only\r
18  * supported in a limited section of lwIP, this is the etharp queueing\r
19  * code. Outside of this section no packet queues are supported yet.\r
20  * \r
21  * The differences between a pbuf chain and a packet queue are very\r
22  * precise but subtle. \r
23  *\r
24  * The last pbuf of a packet has a ->tot_len field that equals the\r
25  * ->len field. It can be found by traversing the list. If the last\r
26  * pbuf of a packet has a ->next field other than NULL, more packets\r
27  * are on the queue.\r
28  *\r
29  * Therefore, looping through a pbuf of a single packet, has an\r
30  * loop end condition (tot_len == p->len), NOT (next == NULL).\r
31  */\r
32 \r
33 /*\r
34  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
35  * All rights reserved.\r
36  *\r
37  * Redistribution and use in source and binary forms, with or without modification,\r
38  * are permitted provided that the following conditions are met:\r
39  *\r
40  * 1. Redistributions of source code must retain the above copyright notice,\r
41  *    this list of conditions and the following disclaimer.\r
42  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
43  *    this list of conditions and the following disclaimer in the documentation\r
44  *    and/or other materials provided with the distribution.\r
45  * 3. The name of the author may not be used to endorse or promote products\r
46  *    derived from this software without specific prior written permission.\r
47  *\r
48  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
49  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
50  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
51  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
52  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
53  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
56  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
57  * OF SUCH DAMAGE.\r
58  *\r
59  * This file is part of the lwIP TCP/IP stack.\r
60  *\r
61  * Author: Adam Dunkels <adam@sics.se>\r
62  *\r
63  */\r
64 \r
65 #include "lwip/opt.h"\r
66 \r
67 #include "lwip/stats.h"\r
68 \r
69 #include "lwip/def.h"\r
70 #include "lwip/mem.h"\r
71 #include "lwip/memp.h"\r
72 #include "lwip/pbuf.h"\r
73 \r
74 #include "lwip/sys.h"\r
75 \r
76 #include "arch/perf.h"\r
77 \r
78 #include <string.h>\r
79 \r
80 static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];\r
81 \r
82 #if !SYS_LIGHTWEIGHT_PROT\r
83 static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;\r
84 static sys_sem_t pbuf_pool_free_sem;\r
85 #endif\r
86 \r
87 static struct pbuf *pbuf_pool = NULL;\r
88 \r
89 /**\r
90  * Initializes the pbuf module.\r
91  *\r
92  * A large part of memory is allocated for holding the pool of pbufs.\r
93  * The size of the individual pbufs in the pool is given by the size\r
94  * parameter, and the number of pbufs in the pool by the num parameter.\r
95  *\r
96  * After the memory has been allocated, the pbufs are set up. The\r
97  * ->next pointer in each pbuf is set up to point to the next pbuf in\r
98  * the pool.\r
99  *\r
100  */\r
101 void\r
102 pbuf_init(void)\r
103 {\r
104   struct pbuf *p, *q = NULL;\r
105   u16_t i;\r
106 \r
107   pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];\r
108   LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);\r
109 \r
110 #if PBUF_STATS\r
111   lwip_stats.pbuf.avail = PBUF_POOL_SIZE;\r
112 #endif /* PBUF_STATS */\r
113 \r
114   /* Set up ->next pointers to link the pbufs of the pool together */\r
115   p = pbuf_pool;\r
116 \r
117   for(i = 0; i < PBUF_POOL_SIZE; ++i) {\r
118     p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));\r
119     p->len = p->tot_len = PBUF_POOL_BUFSIZE;\r
120     p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));\r
121     p->flags = PBUF_FLAG_POOL;\r
122     q = p;\r
123     p = p->next;\r
124   }\r
125 \r
126   /* The ->next pointer of last pbuf is NULL to indicate that there\r
127      are no more pbufs in the pool */\r
128   q->next = NULL;\r
129 \r
130 #if !SYS_LIGHTWEIGHT_PROT\r
131   pbuf_pool_alloc_lock = 0;\r
132   pbuf_pool_free_lock = 0;\r
133   pbuf_pool_free_sem = sys_sem_new(1);\r
134 #endif\r
135 }\r
136 \r
137 /**\r
138  * @internal only called from pbuf_alloc()\r
139  */\r
140 static struct pbuf *\r
141 pbuf_pool_alloc(void)\r
142 {\r
143   struct pbuf *p = NULL;\r
144 \r
145   SYS_ARCH_DECL_PROTECT(old_level);\r
146   SYS_ARCH_PROTECT(old_level);\r
147 \r
148 #if !SYS_LIGHTWEIGHT_PROT\r
149   /* Next, check the actual pbuf pool, but if the pool is locked, we\r
150      pretend to be out of buffers and return NULL. */\r
151   if (pbuf_pool_free_lock) {\r
152 #if PBUF_STATS\r
153     ++lwip_stats.pbuf.alloc_locked;\r
154 #endif /* PBUF_STATS */\r
155     return NULL;\r
156   }\r
157   pbuf_pool_alloc_lock = 1;\r
158   if (!pbuf_pool_free_lock) {\r
159 #endif /* SYS_LIGHTWEIGHT_PROT */\r
160     p = pbuf_pool;\r
161     if (p) {\r
162       pbuf_pool = p->next;\r
163     }\r
164 #if !SYS_LIGHTWEIGHT_PROT\r
165 #if PBUF_STATS\r
166   } else {\r
167     ++lwip_stats.pbuf.alloc_locked;\r
168 #endif /* PBUF_STATS */\r
169   }\r
170   pbuf_pool_alloc_lock = 0;\r
171 #endif /* SYS_LIGHTWEIGHT_PROT */\r
172 \r
173 #if PBUF_STATS\r
174   if (p != NULL) {\r
175     ++lwip_stats.pbuf.used;\r
176     if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {\r
177       lwip_stats.pbuf.max = lwip_stats.pbuf.used;\r
178     }\r
179   }\r
180 #endif /* PBUF_STATS */\r
181 \r
182   SYS_ARCH_UNPROTECT(old_level);\r
183   return p;\r
184 }\r
185 \r
186 \r
187 /**\r
188  * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).\r
189  *\r
190  * The actual memory allocated for the pbuf is determined by the\r
191  * layer at which the pbuf is allocated and the requested size\r
192  * (from the size parameter).\r
193  *\r
194  * @param flag this parameter decides how and where the pbuf\r
195  * should be allocated as follows:\r
196  *\r
197  * - PBUF_RAM: buffer memory for pbuf is allocated as one large\r
198  *             chunk. This includes protocol headers as well.\r
199  * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for\r
200  *             protocol headers. Additional headers must be prepended\r
201  *             by allocating another pbuf and chain in to the front of\r
202  *             the ROM pbuf. It is assumed that the memory used is really\r
203  *             similar to ROM in that it is immutable and will not be\r
204  *             changed. Memory which is dynamic should generally not\r
205  *             be attached to PBUF_ROM pbufs. Use PBUF_REF instead.\r
206  * - PBUF_REF: no buffer memory is allocated for the pbuf, even for\r
207  *             protocol headers. It is assumed that the pbuf is only\r
208  *             being used in a single thread. If the pbuf gets queued,\r
209  *             then pbuf_take should be called to copy the buffer.\r
210  * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from\r
211  *              the pbuf pool that is allocated during pbuf_init().\r
212  *\r
213  * @return the allocated pbuf. If multiple pbufs where allocated, this\r
214  * is the first pbuf of a pbuf chain.\r
215  */\r
216 struct pbuf *\r
217 pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)\r
218 {\r
219   struct pbuf *p, *q, *r;\r
220   u16_t offset;\r
221   s32_t rem_len; /* remaining length */\r
222   LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length));\r
223 \r
224   /* determine header offset */\r
225   offset = 0;\r
226   switch (l) {\r
227   case PBUF_TRANSPORT:\r
228     /* add room for transport (often TCP) layer header */\r
229     offset += PBUF_TRANSPORT_HLEN;\r
230     /* FALLTHROUGH */\r
231   case PBUF_IP:\r
232     /* add room for IP layer header */\r
233     offset += PBUF_IP_HLEN;\r
234     /* FALLTHROUGH */\r
235   case PBUF_LINK:\r
236     /* add room for link layer header */\r
237     offset += PBUF_LINK_HLEN;\r
238     break;\r
239   case PBUF_RAW:\r
240     break;\r
241   default:\r
242     LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);\r
243     return NULL;\r
244   }\r
245 \r
246   switch (flag) {\r
247   case PBUF_POOL:\r
248     /* allocate head of pbuf chain into p */\r
249     p = pbuf_pool_alloc();\r
250     LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));\r
251     if (p == NULL) {\r
252 #if PBUF_STATS\r
253       ++lwip_stats.pbuf.err;\r
254 #endif /* PBUF_STATS */\r
255       return NULL;\r
256     }\r
257     p->next = NULL;\r
258 \r
259     /* make the payload pointer point 'offset' bytes into pbuf data memory */\r
260     p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));\r
261     LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",\r
262             ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);\r
263     /* the total length of the pbuf chain is the requested size */\r
264     p->tot_len = length;\r
265     /* set the length of the first pbuf in the chain */\r
266     p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;\r
267     /* set reference count (needed here in case we fail) */\r
268     p->ref = 1;\r
269 \r
270     /* now allocate the tail of the pbuf chain */\r
271 \r
272     /* remember first pbuf for linkage in next iteration */\r
273     r = p;\r
274     /* remaining length to be allocated */\r
275     rem_len = length - p->len;\r
276     /* any remaining pbufs to be allocated? */\r
277     while (rem_len > 0) {\r
278       q = pbuf_pool_alloc();\r
279       if (q == NULL) {\r
280        LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));\r
281 #if PBUF_STATS\r
282         ++lwip_stats.pbuf.err;\r
283 #endif /* PBUF_STATS */\r
284         /* free chain so far allocated */\r
285         pbuf_free(p);\r
286         /* bail out unsuccesfully */\r
287         return NULL;\r
288       }\r
289       q->next = NULL;\r
290       /* make previous pbuf point to this pbuf */\r
291       r->next = q;\r
292       /* set total length of this pbuf and next in chain */\r
293       q->tot_len = rem_len;\r
294       /* this pbuf length is pool size, unless smaller sized tail */\r
295       q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;\r
296       q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));\r
297       LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",\r
298               ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);\r
299       q->ref = 1;\r
300       /* calculate remaining length to be allocated */\r
301       rem_len -= q->len;\r
302       /* remember this pbuf for linkage in next iteration */\r
303       r = q;\r
304     }\r
305     /* end of chain */\r
306     /*r->next = NULL;*/\r
307 \r
308     break;\r
309   case PBUF_RAM:\r
310     /* If pbuf is to be allocated in RAM, allocate memory for it. */\r
311     p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));\r
312     if (p == NULL) {\r
313       return NULL;\r
314     }\r
315     /* Set up internal structure of the pbuf. */\r
316     p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));\r
317     p->len = p->tot_len = length;\r
318     p->next = NULL;\r
319     p->flags = PBUF_FLAG_RAM;\r
320 \r
321     LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",\r
322            ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);\r
323     break;\r
324   /* pbuf references existing (non-volatile static constant) ROM payload? */\r
325   case PBUF_ROM:\r
326   /* pbuf references existing (externally allocated) RAM payload? */\r
327   case PBUF_REF:\r
328     /* only allocate memory for the pbuf structure */\r
329     p = memp_malloc(MEMP_PBUF);\r
330     if (p == NULL) {\r
331       LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));\r
332       return NULL;\r
333     }\r
334     /* caller must set this field properly, afterwards */\r
335     p->payload = NULL;\r
336     p->len = p->tot_len = length;\r
337     p->next = NULL;\r
338     p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);\r
339     break;\r
340   default:\r
341     LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);\r
342     return NULL;\r
343   }\r
344   /* set reference count */\r
345   p->ref = 1;\r
346   LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p));\r
347   return p;\r
348 }\r
349 \r
350 \r
351 #if PBUF_STATS\r
352 #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)\r
353 #else /* PBUF_STATS */\r
354 #define DEC_PBUF_STATS\r
355 #endif /* PBUF_STATS */\r
356 \r
357 #define PBUF_POOL_FAST_FREE(p)  do {                                    \\r
358                                   p->next = pbuf_pool;                  \\r
359                                   pbuf_pool = p;                        \\r
360                                   DEC_PBUF_STATS;                       \\r
361                                 } while (0)\r
362 \r
363 #if SYS_LIGHTWEIGHT_PROT\r
364 #define PBUF_POOL_FREE(p)  do {                                         \\r
365                                 SYS_ARCH_DECL_PROTECT(old_level);       \\r
366                                 SYS_ARCH_PROTECT(old_level);            \\r
367                                 PBUF_POOL_FAST_FREE(p);                 \\r
368                                 SYS_ARCH_UNPROTECT(old_level);          \\r
369                                } while (0)\r
370 #else /* SYS_LIGHTWEIGHT_PROT */\r
371 #define PBUF_POOL_FREE(p)  do {                                         \\r
372                              sys_sem_wait(pbuf_pool_free_sem);          \\r
373                              PBUF_POOL_FAST_FREE(p);                    \\r
374                              sys_sem_signal(pbuf_pool_free_sem);        \\r
375                            } while (0)\r
376 #endif /* SYS_LIGHTWEIGHT_PROT */\r
377 \r
378 /**\r
379  * Shrink a pbuf chain to a desired length.\r
380  *\r
381  * @param p pbuf to shrink.\r
382  * @param new_len desired new length of pbuf chain\r
383  *\r
384  * Depending on the desired length, the first few pbufs in a chain might\r
385  * be skipped and left unchanged. The new last pbuf in the chain will be\r
386  * resized, and any remaining pbufs will be freed.\r
387  *\r
388  * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.\r
389  * @note May not be called on a packet queue.\r
390  *\r
391  * @bug Cannot grow the size of a pbuf (chain) (yet).\r
392  */\r
393 void\r
394 pbuf_realloc(struct pbuf *p, u16_t new_len)\r
395 {\r
396   struct pbuf *q;\r
397   u16_t rem_len; /* remaining length */\r
398   s16_t grow;\r
399 \r
400   LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||\r
401               p->flags == PBUF_FLAG_ROM ||\r
402               p->flags == PBUF_FLAG_RAM ||\r
403               p->flags == PBUF_FLAG_REF);\r
404 \r
405   /* desired length larger than current length? */\r
406   if (new_len >= p->tot_len) {\r
407     /* enlarging not yet supported */\r
408     return;\r
409   }\r
410 \r
411   /* the pbuf chain grows by (new_len - p->tot_len) bytes\r
412    * (which may be negative in case of shrinking) */\r
413   grow = new_len - p->tot_len;\r
414 \r
415   /* first, step over any pbufs that should remain in the chain */\r
416   rem_len = new_len;\r
417   q = p;\r
418   /* should this pbuf be kept? */\r
419   while (rem_len > q->len) {\r
420     /* decrease remaining length by pbuf length */\r
421     rem_len -= q->len;\r
422     /* decrease total length indicator */\r
423     q->tot_len += grow;\r
424     /* proceed to next pbuf in chain */\r
425     q = q->next;\r
426   }\r
427   /* we have now reached the new last pbuf (in q) */\r
428   /* rem_len == desired length for pbuf q */\r
429 \r
430   /* shrink allocated memory for PBUF_RAM */\r
431   /* (other types merely adjust their length fields */\r
432   if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {\r
433     /* reallocate and adjust the length of the pbuf that will be split */\r
434     mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);\r
435   }\r
436   /* adjust length fields for new last pbuf */\r
437   q->len = rem_len;\r
438   q->tot_len = q->len;\r
439 \r
440   /* any remaining pbufs in chain? */\r
441   if (q->next != NULL) {\r
442     /* free remaining pbufs in chain */\r
443     pbuf_free(q->next);\r
444   }\r
445   /* q is last packet in chain */\r
446   q->next = NULL;\r
447 \r
448 }\r
449 \r
450 /**\r
451  * Adjusts the payload pointer to hide or reveal headers in the payload.\r
452  *\r
453  * Adjusts the ->payload pointer so that space for a header\r
454  * (dis)appears in the pbuf payload.\r
455  *\r
456  * The ->payload, ->tot_len and ->len fields are adjusted.\r
457  *\r
458  * @param hdr_size_inc Number of bytes to increment header size which\r
459  * increases the size of the pbuf. New space is on the front.\r
460  * (Using a negative value decreases the header size.)\r
461  * If hdr_size_inc is 0, this function does nothing and returns succesful.\r
462  *\r
463  * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so\r
464  * the call will fail. A check is made that the increase in header size does\r
465  * not move the payload pointer in front of the start of the buffer.\r
466  * @return non-zero on failure, zero on success.\r
467  *\r
468  */\r
469 u8_t\r
470 pbuf_header(struct pbuf *p, s16_t header_size_increment)\r
471 {\r
472   void *payload;\r
473 \r
474   LWIP_ASSERT("p != NULL", p != NULL);\r
475   if ((header_size_increment == 0) || (p == NULL)) return 0;\r
476  \r
477   /* remember current payload pointer */\r
478   payload = p->payload;\r
479 \r
480   /* pbuf types containing payloads? */\r
481   if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {\r
482     /* set new payload pointer */\r
483     p->payload = (u8_t *)p->payload - header_size_increment;\r
484     /* boundary check fails? */\r
485     if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {\r
486       LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",\r
487         (void *)p->payload,\r
488         (void *)(p + 1)));\\r
489       /* restore old payload pointer */\r
490       p->payload = payload;\r
491       /* bail out unsuccesfully */\r
492       return 1;\r
493     }\r
494   /* pbuf types refering to external payloads? */\r
495   } else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {\r
496     /* hide a header in the payload? */\r
497     if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {\r
498       /* increase payload pointer */\r
499       p->payload = (u8_t *)p->payload - header_size_increment;\r
500     } else {\r
501       /* cannot expand payload to front (yet!)\r
502        * bail out unsuccesfully */\r
503       return 1;\r
504     }\r
505   }\r
506   /* modify pbuf length fields */\r
507   p->len += header_size_increment;\r
508   p->tot_len += header_size_increment;\r
509 \r
510   LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n",\r
511     (void *)payload, (void *)p->payload, header_size_increment));\r
512 \r
513   return 0;\r
514 }\r
515 \r
516 /**\r
517  * Dereference a pbuf chain or queue and deallocate any no-longer-used\r
518  * pbufs at the head of this chain or queue.\r
519  *\r
520  * Decrements the pbuf reference count. If it reaches zero, the pbuf is\r
521  * deallocated.\r
522  *\r
523  * For a pbuf chain, this is repeated for each pbuf in the chain,\r
524  * up to the first pbuf which has a non-zero reference count after\r
525  * decrementing. So, when all reference counts are one, the whole\r
526  * chain is free'd.\r
527  *\r
528  * @param pbuf The pbuf (chain) to be dereferenced.\r
529  *\r
530  * @return the number of pbufs that were de-allocated\r
531  * from the head of the chain.\r
532  *\r
533  * @note MUST NOT be called on a packet queue (Not verified to work yet).\r
534  * @note the reference counter of a pbuf equals the number of pointers\r
535  * that refer to the pbuf (or into the pbuf).\r
536  *\r
537  * @internal examples:\r
538  *\r
539  * Assuming existing chains a->b->c with the following reference\r
540  * counts, calling pbuf_free(a) results in:\r
541  * \r
542  * 1->2->3 becomes ...1->3\r
543  * 3->3->3 becomes 2->3->3\r
544  * 1->1->2 becomes ......1\r
545  * 2->1->1 becomes 1->1->1\r
546  * 1->1->1 becomes .......\r
547  *\r
548  */\r
549 u8_t\r
550 pbuf_free(struct pbuf *p)\r
551 {\r
552   struct pbuf *q;\r
553   u8_t count;\r
554   SYS_ARCH_DECL_PROTECT(old_level);\r
555 \r
556   LWIP_ASSERT("p != NULL", p != NULL);\r
557   /* if assertions are disabled, proceed with debug output */\r
558   if (p == NULL) {\r
559     LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));\r
560     return 0;\r
561   }\r
562   LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));\r
563 \r
564   PERF_START;\r
565 \r
566   LWIP_ASSERT("pbuf_free: sane flags",\r
567     p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||\r
568     p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);\r
569 \r
570   count = 0;\r
571   /* Since decrementing ref cannot be guaranteed to be a single machine operation\r
572    * we must protect it. Also, the later test of ref must be protected.\r
573    */\r
574   SYS_ARCH_PROTECT(old_level);\r
575   /* de-allocate all consecutive pbufs from the head of the chain that\r
576    * obtain a zero reference count after decrementing*/\r
577   while (p != NULL) {\r
578     /* all pbufs in a chain are referenced at least once */\r
579     LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);\r
580     /* decrease reference count (number of pointers to pbuf) */\r
581     p->ref--;\r
582     /* this pbuf is no longer referenced to? */\r
583     if (p->ref == 0) {\r
584       /* remember next pbuf in chain for next iteration */\r
585       q = p->next;\r
586       LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));\r
587       /* is this a pbuf from the pool? */\r
588       if (p->flags == PBUF_FLAG_POOL) {\r
589         p->len = p->tot_len = PBUF_POOL_BUFSIZE;\r
590         p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));\r
591         PBUF_POOL_FREE(p);\r
592       /* is this a ROM or RAM referencing pbuf? */\r
593       } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {\r
594         memp_free(MEMP_PBUF, p);\r
595       /* p->flags == PBUF_FLAG_RAM */\r
596       } else {\r
597         mem_free(p);\r
598       }\r
599       count++;\r
600       /* proceed to next pbuf */\r
601       p = q;\r
602     /* p->ref > 0, this pbuf is still referenced to */\r
603     /* (and so the remaining pbufs in chain as well) */\r
604     } else {\r
605       LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));\r
606       /* stop walking through the chain */\r
607       p = NULL;\r
608     }\r
609   }\r
610   SYS_ARCH_UNPROTECT(old_level);\r
611   PERF_STOP("pbuf_free");\r
612   /* return number of de-allocated pbufs */\r
613   return count;\r
614 }\r
615 \r
616 /**\r
617  * Count number of pbufs in a chain\r
618  *\r
619  * @param p first pbuf of chain\r
620  * @return the number of pbufs in a chain\r
621  */\r
622 \r
623 u8_t\r
624 pbuf_clen(struct pbuf *p)\r
625 {\r
626   u8_t len;\r
627 \r
628   len = 0;\r
629   while (p != NULL) {\r
630     ++len;\r
631     p = p->next;\r
632   }\r
633   return len;\r
634 }\r
635 \r
636 /**\r
637  * Increment the reference count of the pbuf.\r
638  *\r
639  * @param p pbuf to increase reference counter of\r
640  *\r
641  */\r
642 void\r
643 pbuf_ref(struct pbuf *p)\r
644 {\r
645   SYS_ARCH_DECL_PROTECT(old_level);\r
646   /* pbuf given? */\r
647   if (p != NULL) {\r
648     SYS_ARCH_PROTECT(old_level);\r
649     ++(p->ref);\r
650     SYS_ARCH_UNPROTECT(old_level);\r
651   }\r
652 }\r
653 \r
654 /**\r
655  * Concatenate two pbufs (each may be a pbuf chain) and take over\r
656  * the caller's reference of the tail pbuf.\r
657  * \r
658  * @note The caller MAY NOT reference the tail pbuf afterwards.\r
659  * Use pbuf_chain() for that purpose.\r
660  * \r
661  * @see pbuf_chain()\r
662  */\r
663 \r
664 void\r
665 pbuf_cat(struct pbuf *h, struct pbuf *t)\r
666 {\r
667   struct pbuf *p;\r
668 \r
669   LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);\r
670   LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);\r
671   if ((h == NULL) || (t == NULL)) return;\r
672 \r
673   /* proceed to last pbuf of chain */\r
674   for (p = h; p->next != NULL; p = p->next) {\r
675     /* add total length of second chain to all totals of first chain */\r
676     p->tot_len += t->tot_len;\r
677   }\r
678   /* { p is last pbuf of first h chain, p->next == NULL } */\r
679   LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);\r
680   LWIP_ASSERT("p->next == NULL", p->next == NULL);\r
681   /* add total length of second chain to last pbuf total of first chain */\r
682   p->tot_len += t->tot_len;\r
683   /* chain last pbuf of head (p) with first of tail (t) */\r
684   p->next = t;\r
685   /* p->next now references t, but the caller will drop its reference to t,\r
686    * so netto there is no change to the reference count of t.\r
687    */\r
688 }\r
689 \r
690 /**\r
691  * Chain two pbufs (or pbuf chains) together.\r
692  * \r
693  * The caller MUST call pbuf_free(t) once it has stopped\r
694  * using it. Use pbuf_cat() instead if you no longer use t.\r
695  * \r
696  * @param h head pbuf (chain)\r
697  * @param t tail pbuf (chain)\r
698  * @note The pbufs MUST belong to the same packet.\r
699  * @note MAY NOT be called on a packet queue.\r
700  *\r
701  * The ->tot_len fields of all pbufs of the head chain are adjusted.\r
702  * The ->next field of the last pbuf of the head chain is adjusted.\r
703  * The ->ref field of the first pbuf of the tail chain is adjusted.\r
704  *\r
705  */\r
706 void\r
707 pbuf_chain(struct pbuf *h, struct pbuf *t)\r
708 {\r
709   pbuf_cat(h, t);\r
710   /* t is now referenced by h */\r
711   pbuf_ref(t);\r
712   LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));\r
713 }\r
714 \r
715 /* For packet queueing. Note that queued packets MUST be dequeued first\r
716  * using pbuf_dequeue() before calling other pbuf_() functions. */\r
717 #if ARP_QUEUEING\r
718 /**\r
719  * Add a packet to the end of a queue.\r
720  *\r
721  * @param q pointer to first packet on the queue\r
722  * @param n packet to be queued\r
723  *\r
724  * Both packets MUST be given, and must be different.\r
725  */\r
726 void\r
727 pbuf_queue(struct pbuf *p, struct pbuf *n)\r
728 {\r
729 #if PBUF_DEBUG /* remember head of queue */\r
730   struct pbuf *q = p;\r
731 #endif\r
732   /* programmer stupidity checks */\r
733   LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);\r
734   LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);\r
735   LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);\r
736   if ((p == NULL) || (n == NULL) || (p == n)){\r
737     LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"))\r
738     return;\r
739   }\r
740 \r
741   /* iterate through all packets on queue */\r
742   while (p->next != NULL) {\r
743 /* be very picky about pbuf chain correctness */\r
744 #if PBUF_DEBUG\r
745     /* iterate through all pbufs in packet */\r
746     while (p->tot_len != p->len) {\r
747       /* make sure invariant condition holds */\r
748       LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);\r
749       /* make sure each packet is complete */\r
750       LWIP_ASSERT("p->next != NULL", p->next != NULL);\r
751       p = p->next;\r
752       /* { p->tot_len == p->len => p is last pbuf of a packet } */\r
753     }\r
754     /* { p is last pbuf of a packet } */\r
755     /* proceed to next packet on queue */\r
756 #endif\r
757     /* proceed to next pbuf */\r
758     if (p->next != NULL) p = p->next;\r
759   }\r
760   /* { p->tot_len == p->len and p->next == NULL } ==>\r
761    * { p is last pbuf of last packet on queue } */\r
762   /* chain last pbuf of queue with n */\r
763   p->next = n;\r
764   /* n is now referenced to by the (packet p in the) queue */\r
765   pbuf_ref(n);\r
766 #if PBUF_DEBUG\r
767   LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,\r
768     ("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",\r
769     (void *)n, (void *)p, (void *)q));\r
770 #endif\r
771 }\r
772 \r
773 /**\r
774  * Remove a packet from the head of a queue.\r
775  *\r
776  * The caller MUST reference the remainder of the queue (as returned). The\r
777  * caller MUST NOT call pbuf_ref() as it implicitly takes over the reference\r
778  * from p.\r
779  * \r
780  * @param p pointer to first packet on the queue which will be dequeued.\r
781  * @return first packet on the remaining queue (NULL if no further packets).\r
782  *\r
783  */\r
784 struct pbuf *\r
785 pbuf_dequeue(struct pbuf *p)\r
786 {\r
787   struct pbuf *q;\r
788   LWIP_ASSERT("p != NULL", p != NULL);\r
789 \r
790   /* iterate through all pbufs in packet p */\r
791   while (p->tot_len != p->len) {\r
792     /* make sure invariant condition holds */\r
793     LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);\r
794     /* make sure each packet is complete */\r
795     LWIP_ASSERT("p->next != NULL", p->next != NULL);\r
796     p = p->next;\r
797   }\r
798   /* { p->tot_len == p->len } => p is the last pbuf of the first packet */\r
799   /* remember next packet on queue in q */\r
800   q = p->next;\r
801   /* dequeue packet p from queue */\r
802   p->next = NULL;\r
803   /* any next packet on queue? */\r
804   if (q != NULL) {\r
805     /* although q is no longer referenced by p, it MUST be referenced by\r
806      * the caller, who is maintaining this packet queue. So, we do not call\r
807      * pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */\r
808     LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));\r
809   } else {\r
810     LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));\r
811   }\r
812   return q;\r
813 }\r
814 #endif\r
815 \r
816 /**\r
817  *\r
818  * Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.\r
819  *\r
820  * Used to queue packets on behalf of the lwIP stack, such as\r
821  * ARP based queueing.\r
822  *\r
823  * Go through a pbuf chain and replace any PBUF_REF buffers\r
824  * with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of\r
825  * the referenced data.\r
826  *\r
827  * @note You MUST explicitly use p = pbuf_take(p);\r
828  * The pbuf you give as argument, may have been replaced\r
829  * by a (differently located) copy through pbuf_take()!\r
830  *\r
831  * @note Any replaced pbufs will be freed through pbuf_free().\r
832  * This may deallocate them if they become no longer referenced.\r
833  *\r
834  * @param p Head of pbuf chain to process\r
835  *\r
836  * @return Pointer to head of pbuf chain\r
837  */\r
838 struct pbuf *\r
839 pbuf_take(struct pbuf *p)\r
840 {\r
841   struct pbuf *q , *prev, *head;\r
842   LWIP_ASSERT("pbuf_take: p != NULL\n", p != NULL);\r
843   LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)p));\r
844 \r
845   prev = NULL;\r
846   head = p;\r
847   /* iterate through pbuf chain */\r
848   do\r
849   {\r
850     /* pbuf is of type PBUF_REF? */\r
851     if (p->flags == PBUF_FLAG_REF) {\r
852       LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));\r
853       /* allocate a pbuf (w/ payload) fully in RAM */\r
854       /* PBUF_POOL buffers are faster if we can use them */\r
855       if (p->len <= PBUF_POOL_BUFSIZE) {\r
856         q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);\r
857         if (q == NULL) {\r
858           LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));\r
859         }\r
860       } else {\r
861         /* no replacement pbuf yet */\r
862         q = NULL;\r
863         LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));\r
864       }\r
865       /* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */\r
866       if (q == NULL) {\r
867         q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);\r
868         if (q == NULL) {\r
869           LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));\r
870         }\r
871       }\r
872       /* replacement pbuf could be allocated? */\r
873       if (q != NULL)\r
874       {\r
875         /* copy p to q */\r
876         /* copy successor */\r
877         q->next = p->next;\r
878         /* remove linkage from original pbuf */\r
879         p->next = NULL;\r
880         /* remove linkage to original pbuf */\r
881         if (prev != NULL) {\r
882           /* prev->next == p at this point */\r
883           LWIP_ASSERT("prev->next == p", prev->next == p);\r
884           /* break chain and insert new pbuf instead */\r
885           prev->next = q;\r
886         /* prev == NULL, so we replaced the head pbuf of the chain */\r
887         } else {\r
888           head = q;\r
889         }\r
890         /* copy pbuf payload */\r
891         memcpy(q->payload, p->payload, p->len);\r
892         q->tot_len = p->tot_len;\r
893         q->len = p->len;\r
894         /* in case p was the first pbuf, it is no longer refered to by\r
895          * our caller, as the caller MUST do p = pbuf_take(p);\r
896          * in case p was not the first pbuf, it is no longer refered to\r
897          * by prev. we can safely free the pbuf here.\r
898          * (note that we have set p->next to NULL already so that\r
899          * we will not free the rest of the chain by accident.)\r
900          */\r
901         pbuf_free(p);\r
902         /* do not copy ref, since someone else might be using the old buffer */\r
903         LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q));\r
904         p = q;\r
905       } else {\r
906         /* deallocate chain */\r
907         pbuf_free(head);\r
908         LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p));\r
909         return NULL;\r
910       }\r
911     /* p->flags != PBUF_FLAG_REF */\r
912     } else {\r
913       LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n"));\r
914     }\r
915     /* remember this pbuf */\r
916     prev = p;\r
917     /* proceed to next pbuf in original chain */\r
918     p = p->next;\r
919   } while (p);\r
920   LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));\r
921 \r
922   return head;\r
923 }\r
924 \r
925 /**\r
926  * Dechains the first pbuf from its succeeding pbufs in the chain.\r
927  *\r
928  * Makes p->tot_len field equal to p->len.\r
929  * @param p pbuf to dechain\r
930  * @return remainder of the pbuf chain, or NULL if it was de-allocated.\r
931  * @note May not be called on a packet queue.\r
932  */\r
933 struct pbuf *\r
934 pbuf_dechain(struct pbuf *p)\r
935 {\r
936   struct pbuf *q;\r
937   u8_t tail_gone = 1;\r
938   /* tail */\r
939   q = p->next;\r
940   /* pbuf has successor in chain? */\r
941   if (q != NULL) {\r
942     /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */\r
943     LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);\r
944     /* enforce invariant if assertion is disabled */\r
945     q->tot_len = p->tot_len - p->len;\r
946     /* decouple pbuf from remainder */\r
947     p->next = NULL;\r
948     /* total length of pbuf p is its own length only */\r
949     p->tot_len = p->len;\r
950     /* q is no longer referenced by p, free it */\r
951     LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));\r
952     tail_gone = pbuf_free(q);\r
953     if (tail_gone > 0) {\r
954       LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,\r
955                   ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));\r
956     }\r
957     /* return remaining tail or NULL if deallocated */\r
958   }\r
959   /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */\r
960   LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);\r
961   return (tail_gone > 0? NULL: q);\r
962 }\r