NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
Diff: lwip/core/ipv4/ip_frag.c
- Revision:
- 5:dd63a1e02b1b
- Parent:
- 0:632c9925f013
--- a/lwip/core/ipv4/ip_frag.c Fri Jul 09 14:46:47 2010 +0000 +++ b/lwip/core/ipv4/ip_frag.c Tue Jul 27 15:59:42 2010 +0000 @@ -80,7 +80,10 @@ /** This is a helper struct which holds the starting * offset and the ending offset of this fragment to * easily chain the fragments. - * It has to be packed since it has to fit inside the IP header. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) */ #ifdef PACK_STRUCT_USE_INCLUDES # include "arch/bpstruct.h" @@ -267,11 +270,11 @@ { struct ip_reassdata* ipr; /* No matching previous fragment found, allocate a new reassdata struct */ - ipr = (struct ip_reassdata*) memp_malloc(MEMP_REASSDATA); + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); if (ipr == NULL) { #if IP_REASS_FREE_OLDEST if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { - ipr = (struct ip_reassdata*) memp_malloc(MEMP_REASSDATA); + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); } if (ipr == NULL) #endif /* IP_REASS_FREE_OLDEST */ @@ -552,7 +555,7 @@ * to an existing one */ /* check for 'no more fragments', and update queue entry*/ - if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) { + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { ipr->flags |= IP_REASS_FLAG_LASTFRAG; ipr->datagram_len = offset + len; LWIP_DEBUGF(IP_REASS_DEBUG, @@ -613,6 +616,38 @@ #if IP_FRAG #if IP_FRAG_USES_STATIC_BUF static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ #endif /* IP_FRAG_USES_STATIC_BUF */ /** @@ -635,7 +670,9 @@ #if IP_FRAG_USES_STATIC_BUF struct pbuf *header; #else +#if !LWIP_NETIF_TX_SINGLE_PBUF struct pbuf *newpbuf; +#endif struct ip_hdr *original_iphdr; #endif struct ip_hdr *iphdr; @@ -646,7 +683,7 @@ u16_t last; u16_t poff = IP_HLEN; u16_t tmp; -#if !IP_FRAG_USES_STATIC_BUF +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF u16_t newpbuflen = 0; u16_t left_to_copy; #endif @@ -666,10 +703,10 @@ rambuf->payload = LWIP_MEM_ALIGN((void *)buf); /* Copy the IP header in it */ - iphdr = (struct ip_hdr*) rambuf->payload; + iphdr = (struct ip_hdr *)rambuf->payload; SMEMCPY(iphdr, p->payload, IP_HLEN); #else /* IP_FRAG_USES_STATIC_BUF */ - original_iphdr = (struct ip_hdr*) p->payload; + original_iphdr = (struct ip_hdr *)p->payload; iphdr = original_iphdr; #endif /* IP_FRAG_USES_STATIC_BUF */ @@ -697,6 +734,23 @@ #if IP_FRAG_USES_STATIC_BUF poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); #else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if(pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ /* When not using a static buffer, create a chain of pbufs. * The first will be a PBUF_RAM holding the link and IP header. * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, @@ -709,7 +763,7 @@ LWIP_ASSERT("this needs a pbuf in one piece!", (p->len >= (IP_HLEN))); SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr*) rambuf->payload; + iphdr = (struct ip_hdr *)rambuf->payload; /* Can just adjust p directly for needed offset. */ p->payload = (u8_t *)p->payload + poff; @@ -717,20 +771,29 @@ left_to_copy = cop; while (left_to_copy) { + struct pbuf_custom_ref *pcr; newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; /* Is this pbuf already empty? */ if (!newpbuflen) { p = p->next; continue; } - newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); - if (newpbuf == NULL) { + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { pbuf_free(rambuf); return ERR_MEM; } /* Mirror this pbuf, although we might not need all of it. */ - newpbuf->payload = p->payload; - newpbuf->len = newpbuf->tot_len = newpbuflen; + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain * so that it is removed when pbuf_dechain is later called on rambuf. */ @@ -741,6 +804,7 @@ } } poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ #endif /* IP_FRAG_USES_STATIC_BUF */ /* Correct header */