* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). * * 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). * * @param layer flag to define header size * @param length size of the pbuf's payload * @param type this parameter decides how and where the pbuf * should be
| 204 | * is the first pbuf of a pbuf chain. |
| 205 | */ |
| 206 | struct pbuf * |
| 207 | pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) |
| 208 | { |
| 209 | struct pbuf *p, *q, *r; |
| 210 | u16_t offset; |
| 211 | s32_t rem_len; /* remaining length */ |
| 212 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); |
| 213 | |
| 214 | /* determine header offset */ |
| 215 | switch (layer) { |
| 216 | case PBUF_TRANSPORT: |
| 217 | /* add room for transport (often TCP) layer header */ |
| 218 | offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; |
| 219 | break; |
| 220 | case PBUF_IP: |
| 221 | /* add room for IP layer header */ |
| 222 | offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; |
| 223 | break; |
| 224 | case PBUF_LINK: |
| 225 | /* add room for link layer header */ |
| 226 | offset = PBUF_LINK_HLEN; |
| 227 | break; |
| 228 | case PBUF_RAW: |
| 229 | offset = 0; |
| 230 | break; |
| 231 | default: |
| 232 | LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); |
| 233 | return NULL; |
| 234 | } |
| 235 | |
| 236 | switch (type) { |
| 237 | case PBUF_POOL: |
| 238 | /* allocate head of pbuf chain into p */ |
| 239 | p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); |
| 240 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); |
| 241 | if (p == NULL) { |
| 242 | PBUF_POOL_IS_EMPTY(); |
| 243 | return NULL; |
| 244 | } |
| 245 | p->type = type; |
| 246 | p->next = NULL; |
| 247 | |
| 248 | /* make the payload pointer point 'offset' bytes into pbuf data memory */ |
| 249 | p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); |
| 250 | LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
| 251 | ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); |
| 252 | /* the total length of the pbuf chain is the requested size */ |
| 253 | p->tot_len = length; |
| 254 | /* set the length of the first pbuf in the chain */ |
| 255 | p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); |
| 256 | LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", |
| 257 | ((u8_t*)p->payload + p->len <= |
| 258 | (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); |
| 259 | LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", |
| 260 | (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); |
| 261 | /* set reference count (needed here in case we fail) */ |
| 262 | p->ref = 1; |
| 263 |