Index: core/pbuf.c =================================================================== RCS file: /sources/lwip/lwip/src/core/pbuf.c,v retrieving revision 1.118 diff -u -5 -p -r1.118 pbuf.c --- core/pbuf.c 27 Jul 2007 15:06:03 -0000 1.118 +++ core/pbuf.c 30 Jul 2007 19:16:37 -0000 @@ -89,10 +89,13 @@ * @param 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_RAM_NOCOPY: As for PBUF_RAM, but used when payload does not + * require copying should the pbuf be queued anywhere. The + * stack frees this sort of pbuf, not the application. * - 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 @@ -202,21 +205,23 @@ pbuf_alloc(pbuf_layer l, u16_t length, p } /* end of chain */ /*r->next = NULL;*/ break; + case PBUF_RAM_NOCOPY: + /* pbuf is like a RAM one, but with indication that the payload does not need copying */ case PBUF_RAM: /* If pbuf is to be allocated in RAM, allocate memory for it. */ p = mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); if (p == NULL) { return NULL; } /* Set up internal structure of the pbuf. */ p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); p->len = p->tot_len = length; p->next = NULL; - p->flags = PBUF_FLAG_RAM; + p->flags = (flag == PBUF_RAM) ? PBUF_FLAG_RAM : (PBUF_FLAG_RAM|PBUF_FLAG_NOCOPY); LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); break; /* pbuf references existing (non-volatile static constant) ROM payload? */ @@ -232,11 +237,11 @@ pbuf_alloc(pbuf_layer l, u16_t length, p } /* caller must set this field properly, afterwards */ p->payload = NULL; p->len = p->tot_len = length; p->next = NULL; - p->flags = ((flag == PBUF_ROM) ? PBUF_FLAG_ROM : PBUF_FLAG_REF); + p->flags = ((flag == PBUF_ROM) ? (PBUF_FLAG_ROM|PBUF_FLAG_NOCOPY) : PBUF_FLAG_REF); break; default: LWIP_ASSERT("pbuf_alloc: erroneous flag", 0); return NULL; } @@ -267,14 +272,14 @@ pbuf_realloc(struct pbuf *p, u16_t new_l { struct pbuf *q; u16_t rem_len; /* remaining length */ s32_t grow; - LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL || - p->flags == PBUF_FLAG_ROM || - p->flags == PBUF_FLAG_RAM || - p->flags == PBUF_FLAG_REF); + LWIP_ASSERT("pbuf_realloc: sane p->flags", IS_POOL_PBUF(p) || + IS_ROM_PBUF(p) || + IS_RAM_PBUF(p) || + IS_REF_PBUF(p)); /* desired length larger than current length? */ if (new_len >= p->tot_len) { /* enlarging not yet supported */ return; @@ -300,11 +305,11 @@ pbuf_realloc(struct pbuf *p, u16_t new_l /* we have now reached the new last pbuf (in q) */ /* rem_len == desired length for pbuf q */ /* shrink allocated memory for PBUF_RAM */ /* (other types merely adjust their length fields */ - if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) { + if (IS_RAM_PBUF(q) && (rem_len != q->len)) { /* reallocate and adjust the length of the pbuf that will be split */ mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len); } /* adjust length fields for new last pbuf */ q->len = rem_len; @@ -341,11 +346,10 @@ pbuf_realloc(struct pbuf *p, u16_t new_l * */ u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment) { - u16_t flags; void *payload; u16_t increment_magnitude; LWIP_ASSERT("p != NULL", p != NULL); if ((header_size_increment == 0) || (p == NULL)) @@ -359,24 +363,23 @@ pbuf_header(struct pbuf *p, s16_t header increment_magnitude = header_size_increment; #if 0 /* Can't assert these as some callers speculatively call pbuf_header() to see if it's OK. Will return 1 below instead. */ /* Check that we've got the correct type of pbuf to work with */ - LWIP_ASSERT("p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL", - p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL); + LWIP_ASSERT("IS_RAM_PBUF(p) || IS_POOL_PBUF(p)", + IS_RAM_PBUF(p) || IS_POOL_PBUF(p)); /* Check that we aren't going to move off the beginning of the pbuf */ LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); #endif } - flags = p->flags; /* remember current payload pointer */ payload = p->payload; /* pbuf types containing payloads? */ - if (flags == PBUF_FLAG_RAM || flags == PBUF_FLAG_POOL) { + if (IS_RAM_PBUF(p) || IS_POOL_PBUF(p)) { /* set new payload pointer */ p->payload = (u8_t *)p->payload - header_size_increment; /* boundary check fails? */ if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", @@ -386,11 +389,11 @@ pbuf_header(struct pbuf *p, s16_t header p->payload = payload; /* bail out unsuccesfully */ return 1; } /* pbuf types refering to external payloads? */ - } else if (flags == PBUF_FLAG_REF || flags == PBUF_FLAG_ROM) { + } else if (IS_REF_PBUF(p) || IS_ROM_PBUF(p)) { /* hide a header in the payload? */ if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { /* increase payload pointer */ p->payload = (u8_t *)p->payload - header_size_increment; } else { @@ -448,11 +451,10 @@ pbuf_header(struct pbuf *p, s16_t header * */ u8_t pbuf_free(struct pbuf *p) { - u16_t flags; struct pbuf *q; u8_t count; if (p == NULL) { LWIP_ASSERT("p != NULL", p != NULL); @@ -463,12 +465,11 @@ pbuf_free(struct pbuf *p) LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p)); PERF_START; LWIP_ASSERT("pbuf_free: sane flags", - p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM || - p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL); + IS_RAM_PBUF(p) || IS_ROM_PBUF(p) || IS_REF_PBUF(p) || IS_POOL_PBUF(p)); count = 0; /* de-allocate all consecutive pbufs from the head of the chain that * obtain a zero reference count after decrementing*/ while (p != NULL) { @@ -486,18 +487,17 @@ pbuf_free(struct pbuf *p) /* this pbuf is no longer referenced to? */ if (ref == 0) { /* remember next pbuf in chain for next iteration */ q = p->next; LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p)); - flags = p->flags; /* is this a pbuf from the pool? */ - if (flags == PBUF_FLAG_POOL) { + if (IS_POOL_PBUF(p)) { memp_free(MEMP_PBUF_POOL, p); /* is this a ROM or RAM referencing pbuf? */ - } else if (flags == PBUF_FLAG_ROM || flags == PBUF_FLAG_REF) { + } else if (IS_ROM_PBUF(p) || IS_REF_PBUF(p)) { memp_free(MEMP_PBUF, p); - /* flags == PBUF_FLAG_RAM */ + /* IS_RAM_PBUF(p) */ } else { mem_free(p); } count++; /* proceed to next pbuf */ Index: core/ipv4/ip_frag.c =================================================================== RCS file: /sources/lwip/lwip/src/core/ipv4/ip_frag.c,v retrieving revision 1.33 diff -u -5 -p -r1.33 ip_frag.c --- core/ipv4/ip_frag.c 25 Jul 2007 18:53:46 -0000 1.33 +++ core/ipv4/ip_frag.c 30 Jul 2007 19:16:37 -0000 @@ -452,9 +452,12 @@ ip_frag(struct pbuf *p, struct netif *ne ofo += nfb; } #if IP_FRAG_USES_STATIC_BUF pbuf_free(rambuf); #endif /* IP_FRAG_USES_STATIC_BUF */ + if (STACK_FREES_PBUF(p) { + pbuf_free(p); + } snmp_inc_ipfragoks(); return ERR_OK; } #endif /* IP_FRAG */ Index: include/lwip/pbuf.h =================================================================== RCS file: /sources/lwip/lwip/src/include/lwip/pbuf.h,v retrieving revision 1.26 diff -u -5 -p -r1.26 pbuf.h --- include/lwip/pbuf.h 29 Jul 2007 08:23:57 -0000 1.26 +++ include/lwip/pbuf.h 30 Jul 2007 19:16:37 -0000 @@ -50,21 +50,33 @@ typedef enum { PBUF_RAW } pbuf_layer; typedef enum { PBUF_RAM, + PBUF_RAM_NOCOPY, PBUF_ROM, PBUF_REF, PBUF_POOL } pbuf_flag; /* Definitions for the pbuf flag field. These are NOT the flags that * are passed to pbuf_alloc(). */ -#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */ -#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */ -#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */ -#define PBUF_FLAG_REF 0x04U /* Flags thet the pbuf payload refers to RAM */ +#define PBUF_FLAG_RAM 0x01U /* Flags that pbuf data is stored in RAM */ +#define PBUF_FLAG_ROM 0x02U /* Flags that pbuf data is stored in ROM */ +#define PBUF_FLAG_POOL 0x04U /* Flags that the pbuf comes from the pbuf pool */ +#define PBUF_FLAG_REF 0x08U /* Flags that the pbuf payload refers to RAM */ +#define PBUF_FLAG_NOCOPY 0x10U /* Flags that pbuf payload does not need copying when queuing */ + + +#define IS_RAM_PBUF(_p) ((_p)->flags & PBUF_FLAG_RAM) +#define IS_ROM_PBUF(_p) ((_p)->flags & PBUF_FLAG_ROM) +#define IS_REF_PBUF(_p) ((_p)->flags & PBUF_FLAG_REF) +#define IS_POOL_PBUF(_p) ((_p)->flags & PBUF_FLAG_POOL) +#define PBUF_NEEDS_COPY(_p) (0 == ((_p)->flags & PBUF_FLAG_NOCOPY)) +/* The stack is responsible for freeing a pbuf if the copy flag is + * set, unless it's a ROM pbuf */ +#define STACK_FREES_PBUF(_p) (((_p)->flags & (PBUF_FLAG_NOCOPY|PBUF_FLAG_ROM)) == PBUF_FLAG_NOCOPY) /** indicates this packet was broadcast on the link */ #define PBUF_FLAG_LINK_BROADCAST 0x80U struct pbuf { Index: netif/etharp.c =================================================================== RCS file: /sources/lwip/lwip/src/netif/etharp.c,v retrieving revision 1.131 diff -u -5 -p -r1.131 etharp.c --- netif/etharp.c 29 Jul 2007 08:11:33 -0000 1.131 +++ netif/etharp.c 30 Jul 2007 19:16:37 -0000 @@ -934,11 +934,11 @@ etharp_query(struct netif *netif, struct * to copy the whole queue into a new PBUF_RAM (see bug #11400) * PBUF_ROMs can be left as they are, since ROM must not get changed. */ p = q; while (p) { LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if(p->flags != PBUF_FLAG_ROM) { + if(PBUF_NEEDS_COPY(p)) { copy_needed = 1; break; } p = p->next; }