NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

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 */