diff --git a/ChangeLog b/ChangeLog
index bdd2ad17eb5029e776544b61c0d74cb10e112098..2e69d72f504c7c3fae80747d79687f4e33d7eaf4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -254,3 +254,7 @@
 	* Added vsnprintf
 	* Integrated uIP telnetd
 	* Add missing logic to readahead buffer logic
+	* examples/nettest uses larger buffers
+	* Improved ACK handling in send() to better hander deferred acknowledgements
+	  and polling intervals.  Greatly improves send performance.
+
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index fe6c5d560933a2ff722b256a41a2453cf72c655e..8247fa14c8997348904e342eef3e533f5f9f5733 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -734,6 +734,9 @@ Other memory:
 	* Added vsnprintf
 	* Integrated uIP telnetd
 	* Add missing logic to readahead buffer logic
+	* examples/nettest uses larger buffers
+	* Improved ACK handling in send() to better hander deferred acknowledgements
+	  and polling intervals.  Greatly improves send performance.
 </pre></ul>
 
 <table width ="100%">
diff --git a/TODO b/TODO
index 4484be424cf87d0e42d2608b79f7241706b4ed15..c0aff5318e78e3c60d6a14e777efb4f5d95924f0 100644
--- a/TODO
+++ b/TODO
@@ -33,10 +33,6 @@ o Network
   but is not implemented.
 - uIP's netutils/smtp, dpcpc, resolv, webclient -- untested
 - Should implement SOCK_RAW
-- Performance Improvements (uIP is not very fast):
-  Need to extend logic so that uIP can have more than on packet in flight and to
-  handle deferred acknowledgements.  This is supposed to improve send performance by
-  an order of magnitude.
 - uIP polling issues:
   (1) Current logic will not support multiple ethernet drivers.  Each driver should
       poll on TCP connections connect on the network supported by the driver; UDP
@@ -78,8 +74,8 @@ o C5471
 
 o DM320
 - It seems that when a lot of debug statements are added, the system no
-  longer boots.  There could be some issue with the bootloader or with
-  the programming of the SDRAM MMU regions.
+  longer boots.  This has been diagnosed as a stack problem.. making the stack
+  bigger or removing arrays on the stack fixes the problem.
 
 o LPC214x
 - Finish bringup
diff --git a/examples/nettest/nettest-client.c b/examples/nettest/nettest-client.c
index 2e5991a86b3f167b22463931e39c0d551759d394..371f4d4f8a88ea3c8346d4ca2f1b223c6e10b617 100644
--- a/examples/nettest/nettest-client.c
+++ b/examples/nettest/nettest-client.c
@@ -56,9 +56,9 @@
 void send_client(void)
 {
   struct sockaddr_in myaddr;
-  char outbuf[SENDSIZE];
+  char *outbuf;
 #ifndef CONFIG_EXAMPLE_NETTEST_PERFORMANCE
-  char inbuf[SENDSIZE];
+  char *inbuf;
 #endif
   int sockfd;
   int nbytessent;
@@ -69,13 +69,28 @@ void send_client(void)
   int ch;
   int i;
 
+  /* Allocate buffers */
+
+  outbuf = (char*)malloc(SENDSIZE);
+#ifndef CONFIG_EXAMPLE_NETTEST_PERFORMANCE
+  inbuf  = (char*)malloc(SENDSIZE);
+  if (!outbuf || !inbuf)
+#else
+  if (!outbuf)
+#endif
+    {
+      message("client: failed to allocate buffers\n");
+      exit(1);
+    }
+
+
   /* Create a new TCP socket */
 
   sockfd = socket(PF_INET, SOCK_STREAM, 0);
   if (sockfd < 0)
     {
       message("client socket failure %d\n", errno);
-      exit(1);
+      goto errout_with_buffers;
     }
 
   /* Connect the socket to the server */
@@ -92,7 +107,7 @@ void send_client(void)
   if (connect( sockfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
     {
       message("client: connect failure: %d\n", errno);
-      exit(1);
+      goto errout_with_socket;
     }
   message("client: Connected\n");
 
@@ -117,14 +132,12 @@ void send_client(void)
       if (nbytessent < 0)
         {
           message("client: send failed: %d\n", errno);
-          close(sockfd);
-          exit(-1);
+          goto errout_with_socket;
         }
       else if (nbytessent != 512)
         {
           message("client: Bad send length=%d: %d\n", nbytessent);
-          close(sockfd);
-          exit(-1);
+          goto errout_with_socket;
         }
     }
 #else
@@ -137,14 +150,12 @@ void send_client(void)
   if (nbytessent < 0)
     {
       message("client: send failed: %d\n", errno);
-      close(sockfd);
-      exit(-1);
+      goto errout_with_socket;
     }
   else if (nbytessent != SENDSIZE)
     {
       message("client: Bad send length: %d Expected: %d\n", nbytessent, SENDSIZE);
-      close(sockfd);
-      exit(-1);
+      goto errout_with_socket;
     }
 
   totalbytesrecvd = 0;
@@ -156,8 +167,7 @@ void send_client(void)
       if (nbytesrecvd < 0)
         {
           message("client: recv failed: %d\n", errno);
-          close(sockfd);
-          exit(-1);
+          goto errout_with_socket;
         }
       totalbytesrecvd += nbytesrecvd;
       message("client: Received %d of %d bytes\n", totalbytesrecvd, SENDSIZE);
@@ -167,16 +177,29 @@ void send_client(void)
   if (totalbytesrecvd != SENDSIZE)
     {
       message("client: Bad recv length: %d Expected: %d\n", totalbytesrecvd, SENDSIZE);
-      close(sockfd);
-      exit(-1);
+      goto errout_with_socket;
     }
   else if (memcmp(inbuf, outbuf, SENDSIZE) != 0)
     {
       message("client: Received buffer does not match sent buffer\n");
-      close(sockfd);
-      exit(-1);
+      goto errout_with_socket;
     }
 
   close(sockfd);
+  free(outbuf);
+#ifndef CONFIG_EXAMPLE_NETTEST_PERFORMANCE
+  free(inbuf);
+#endif
+  return;
+#endif
+
+errout_with_socket:
+  close(sockfd);
+
+errout_with_buffers:
+  free(outbuf);
+#ifndef CONFIG_EXAMPLE_NETTEST_PERFORMANCE
+  free(inbuf);
 #endif
+  exit(1);
 }
diff --git a/examples/nettest/nettest-server.c b/examples/nettest/nettest-server.c
index 6dbede997835b4676011c56ff26e99ec95687bff..6d9ccaeba7fb836d962623702a10fb66ac12984d 100644
--- a/examples/nettest/nettest-server.c
+++ b/examples/nettest/nettest-server.c
@@ -58,7 +58,7 @@ void recv_server(void)
 #ifdef NETTEST_HAVE_SOLINGER
   struct linger ling;
 #endif
-  char buffer[1024];
+  char *buffer;
   int listensd;
   int acceptsd;
   socklen_t addrlen;
@@ -71,13 +71,23 @@ void recv_server(void)
 #endif
   int optval;
 
+  /* Allocate a BIG buffer */
+
+  buffer = (char*)malloc(2*SENDSIZE);
+  if (!buffer)
+    {
+      message("server: failed to allocate buffer\n");
+      exit(1);
+    }
+
+
   /* Create a new TCP socket */
 
   listensd = socket(PF_INET, SOCK_STREAM, 0);
   if (listensd < 0)
     {
       message("server: socket failure: %d\n", errno);
-      exit(1);
+      goto errout_with_buffer;
     }
 
   /* Set socket to reuse address */
@@ -86,7 +96,7 @@ void recv_server(void)
   if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
     {
       message("server: setsockopt SO_REUSEADDR failure: %d\n", errno);
-      exit(1);
+      goto errout_with_listensd;
     }
 
   /* Bind the socket to a local address */
@@ -98,7 +108,7 @@ void recv_server(void)
   if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
     {
       message("server: bind failure: %d\n", errno);
-      exit(1);
+      goto errout_with_listensd;
     }
 
   /* Listen for connections on the bound TCP socket */
@@ -106,7 +116,7 @@ void recv_server(void)
   if (listen(listensd, 5) < 0)
     {
       message("server: listen failure %d\n", errno);
-      exit(1);
+      goto errout_with_listensd;
     }
 
   /* Accept only one connection */
@@ -117,7 +127,7 @@ void recv_server(void)
   if (acceptsd < 0)
     {
       message("server: accept failure: %d\n", errno);
-      exit(1);
+      goto errout_with_listensd;
     }
   message("server: Connection accepted -- receiving\n");
 
@@ -129,7 +139,7 @@ void recv_server(void)
     if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0)
       {
       message("server: setsockopt SO_LINGER failure: %d\n", errno);
-      exit(1);
+      goto errout_with_acceptsd;
     }
 #endif
 
@@ -138,13 +148,11 @@ void recv_server(void)
 
   for (;;)
     {
-      nbytesread = recv(acceptsd, buffer, 1024, 0);
+      nbytesread = recv(acceptsd, buffer, 2*SENDSIZE, 0);
       if (nbytesread <= 0)
         {
           message("server: recv failed: %d\n", errno);
-          close(listensd);
-          close(acceptsd);
-          exit(-1);
+          goto errout_with_acceptsd;
         }
     }
 #else
@@ -154,13 +162,11 @@ void recv_server(void)
   while (totalbytesread < SENDSIZE)
     {
       message("server: Reading...\n");
-      nbytesread = recv(acceptsd, &buffer[totalbytesread], 1024 - totalbytesread, 0);
+      nbytesread = recv(acceptsd, &buffer[totalbytesread], 2*SENDSIZE - totalbytesread, 0);
       if (nbytesread <= 0)
         {
           message("server: recv failed: %d\n", errno);
-          close(listensd);
-          close(acceptsd);
-          exit(-1);
+          goto errout_with_acceptsd;
         }
 
       totalbytesread += nbytesread;
@@ -172,9 +178,7 @@ void recv_server(void)
   if (totalbytesread != SENDSIZE)
     {
       message("server: Received %d / Expected %d bytes\n", totalbytesread, SENDSIZE);
-      close(listensd);
-      close(acceptsd);
-      exit(-1);
+      goto errout_with_acceptsd;
     }
 
   ch = 0x20;
@@ -183,9 +187,7 @@ void recv_server(void)
       if (buffer[i] != ch)
         {
           message("server: Byte %d is %02x / Expected %02x\n", i, buffer[i], ch);
-          close(listensd);
-          close(acceptsd);
-          exit(-1);
+          goto errout_with_acceptsd;
         }
 
       if (++ch > 0x7e)
@@ -201,9 +203,7 @@ void recv_server(void)
   if (nbytessent <= 0)
     {
       message("server: send failed: %d\n", errno);
-      close(listensd);
-      close(acceptsd);
-      exit(-1);
+      goto errout_with_acceptsd;
     }
   message("server: Sent %d bytes\n", nbytessent);
 
@@ -218,5 +218,17 @@ void recv_server(void)
 
   close(listensd);
   close(acceptsd);
+  free(buffer);
+  return;
 #endif
+
+errout_with_acceptsd:
+  close(acceptsd);
+
+errout_with_listensd:
+  close(listensd);
+
+errout_with_buffer:
+  free(buffer);
+  exit(1);
 }
diff --git a/examples/nettest/nettest.h b/examples/nettest/nettest.h
index eb7c83c8425e92ece2ba6986384e732bac3719da..318211e795fe3208a52775ccaf056b430163b4e9 100644
--- a/examples/nettest/nettest.h
+++ b/examples/nettest/nettest.h
@@ -85,7 +85,7 @@
 #endif
 
 #define PORTNO     5471
-#define SENDSIZE   512
+#define SENDSIZE   4096
 
 /****************************************************************************
  * Public Function Prototypes
diff --git a/net/net-close.c b/net/net-close.c
index f64d70de70c2bf762b31f430d93626ad1b8eceb5..8d1be9099670202618e3c5ded84bdad7bff4653f 100644
--- a/net/net-close.c
+++ b/net/net-close.c
@@ -165,6 +165,10 @@ static inline void netclose_disconnect(FAR struct socket *psock)
        conn->data_private = (void*)&state;
        conn->data_event   = netclose_interrupt;
 
+       /* Notify the device driver of the availaibilty of TX data */
+
+       netdev_txnotify(&conn->ripaddr);
+
        /* Wait for the disconnect event */
 
        (void)sem_wait(&state.cl_sem);
diff --git a/net/send.c b/net/send.c
index 69cf883ac572ef19c23f0eafdb2027a081f62d48..67acc62856bcd1d862c161237b0bbbd661035969 100644
--- a/net/send.c
+++ b/net/send.c
@@ -48,6 +48,7 @@
 #include <debug.h>
 
 #include <arch/irq.h>
+#include <net/uip/uip-arch.h>
 
 #include "net-internal.h"
 
@@ -55,8 +56,7 @@
  * Definitions
  ****************************************************************************/
 
-#define STATE_POLLWAIT   1
-#define STATE_DATA_SENT  2
+#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
 
 /****************************************************************************
  * Private Types
@@ -69,17 +69,66 @@
 struct send_s
 {
   FAR struct socket *snd_sock;    /* Points to the parent socket structure */
-  sem_t                snd_sem;     /* Used to wake up the waiting thread */
-  FAR const uint8     *snd_buffer;  /* Points to the buffer of data to send */
-  size_t               snd_buflen;  /* Number of bytes in the buffer to send */
-  ssize_t              snd_sent;    /* The number of bytes sent */
-  uint8                snd_state;   /* The state of the send operation. */
+  sem_t              snd_sem;     /* Used to wake up the waiting thread */
+  FAR const uint8   *snd_buffer;  /* Points to the buffer of data to send */
+  size_t             snd_buflen;  /* Number of bytes in the buffer to send */
+  ssize_t            snd_sent;    /* The number of bytes sent */
+  uint32             snd_isn;     /* Initial sequence number */
+  uint32             snd_acked;   /* The number of bytes acked */
 };
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Function: send_getisn
+ *
+ * Description:
+ *   Get the next initial sequence number from the connection stucture
+ *
+ * Parameters:
+ *   conn     The connection structure associated with the socket
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Running at the interrupt level
+ *
+ ****************************************************************************/
+
+static uint32 send_getisn(struct uip_conn *conn)
+{
+   uint32 tmp;
+   memcpy(&tmp, conn->snd_nxt, 4);
+   return ntohl(tmp);
+}
+
+/****************************************************************************
+ * Function: send_getackno
+ *
+ * Description:
+ *   Extract the current acknowledgement sequence number from the incoming packet
+ *
+ * Parameters:
+ *   dev - The sructure of the network driver that caused the interrupt
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Running at the interrupt level
+ *
+ ****************************************************************************/
+
+static uint32 send_getackno(struct uip_driver_s *dev)
+{
+   uint32 tmp;
+   memcpy(&tmp, TCPBUF->ackno, 4);
+   return ntohl(tmp);
+}
+
 /****************************************************************************
  * Function: send_interrupt
  *
@@ -106,51 +155,31 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
 
   nvdbg("flags: %02x state: %d\n", flags, pstate->snd_state);
 
-  /* If the data has not been sent OR if it needs to be retransmitted,
-   * then send it now.
+  /* If this packet contains an acknowledgement, then update the count of
+   * acknowldged bytes.
    */
 
-  if (pstate->snd_state != STATE_DATA_SENT || (flags & UIP_REXMIT) != 0)
+  if ((flags & UIP_ACKDATA) != 0)
     {
-      if (pstate->snd_buflen > uip_mss(conn))
-        {
-          uip_send(dev, pstate->snd_buffer, uip_mss(conn));
-        }
-      else
-        {
-          uip_send(dev, pstate->snd_buffer, pstate->snd_buflen);
-        }
-
-      pstate->snd_state = STATE_DATA_SENT;
-    }
-
-  /* Check if all data has been sent and acknowledged */
-
-  else if (pstate->snd_state == STATE_DATA_SENT && (flags & UIP_ACKDATA) != 0)
-    {
-      /* Yes.. the data has been sent AND acknowledged */
-
-      if (pstate->snd_buflen > uip_mss(conn))
-        {
-          /* Not all data has been sent */
+      /* The current acknowledgement number number is the (relative) offset of
+       * the of the next byte needed by the receiver.  The snd_isn is the offset
+       * of the first byte to send to the receiver.  The difference is the number
+       * of bytes to be acknowledged.
+       */
 
-          pstate->snd_sent   += uip_mss(conn);
-          pstate->snd_buflen -= uip_mss(conn);
-          pstate->snd_buffer += uip_mss(conn);
+      pstate->snd_acked = send_getackno(dev) - pstate->snd_isn;
+      nvdbg("ACK: acked=%d sent=%d buflen=%d\n",
+            pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
 
-          /* Send again on the next poll */
+      /* Have all of the bytes in the buffer been sent and ACKed? */
 
-          pstate->snd_state = STATE_POLLWAIT;
-        }
-      else
+      if ( pstate->snd_acked >= pstate->snd_buflen)
         {
-          /* All data has been sent */
-
-          pstate->snd_sent   += pstate->snd_buflen;
-          pstate->snd_buffer += pstate->snd_buflen;
-          pstate->snd_buflen  = 0;
-
-          /* Don't allow any further call backs. */
+          /* Yes.  Then pstate->snd_len should hold the number of bytes actually
+           * sent.
+           *
+           * Don't allow any further call backs.
+           */
 
           conn->data_flags   = 0;
           conn->data_private = NULL;
@@ -161,9 +190,21 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
            */
 
           sem_post(&pstate->snd_sem);
+          return flags;
         }
     }
 
+  /* Check if we are being asked to retransmit data */
+
+  else if ((flags & UIP_REXMIT) != 0)
+    {
+      /* Yes.. in this case, reset the number of bytes that have been sent
+       * to the number of bytes that have been ACKed.
+       */
+
+      pstate->snd_sent = pstate->snd_acked;
+    }
+
  /* Check for a loss of connection */
 
   else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
@@ -183,6 +224,32 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
       sem_post(&pstate->snd_sem);
     }
 
+  /* We get here if (1) not all of the data has been ACKed, (2) we have been
+   * asked to retransmit data, and (3) the connection is still healthy.
+   * We are now free to send more data to receiver.
+   */
+
+  if (pstate->snd_sent < pstate->snd_buflen)
+    {
+      /* Get the amount of data that we can send in the next packet */
+
+      uint32 sndlen = pstate->snd_buflen - pstate->snd_sent;
+      if (sndlen > uip_mss(conn))
+        {
+          sndlen = uip_mss(conn);
+        }
+
+      /* Then send that amount of data */
+
+      uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen);
+
+      /* And update the amount of data sent (but not necessarily ACKed) */
+
+      pstate->snd_sent += sndlen;
+      nvdbg("SEND: acked=%d sent=%d buflen=%d\n",
+            pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);
+    }
+
   return flags;
 }
 
@@ -293,16 +360,19 @@ ssize_t send(int sockfd, const void *buf, size_t len, int flags)
   save                = irqsave();
   memset(&state, 0, sizeof(struct send_s));
   (void)sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */
-  state.snd_sock      = psock;
-  state.snd_buflen    = len;
-  state.snd_buffer    = buf;
-  state.snd_state     = STATE_POLLWAIT;
+  state.snd_sock      = psock;             /* Socket descriptor to use */
+  state.snd_buflen    = len;               /* Number of bytes to send */
+  state.snd_buffer    = buf;               /* Buffer to send from */
 
   if (len > 0)
     {
-      /* Set up the callback in the connection */
+     /* Get the initial sequence number that will be used */
 
       conn               = (struct uip_conn *)psock->s_conn;
+      state.snd_isn      = send_getisn(conn); /* Initial sequence number */
+
+      /* Set up the callback in the connection */
+
       conn->data_flags   = UIP_REXMIT|UIP_ACKDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
       conn->data_private = (void*)&state;
       conn->data_event   = send_interrupt;
diff --git a/netutils/webserver/httpd.c b/netutils/webserver/httpd.c
index 755d118926373a0e39fe30b168dd75559f7196ff..9e37e46aad522ba6ed67d0aa262b3f47b87ca985 100644
--- a/netutils/webserver/httpd.c
+++ b/netutils/webserver/httpd.c
@@ -78,8 +78,8 @@
 
 #define errno *get_errno_ptr()
 
-#define CONFIG_NETUTILS_HTTPD_DUMPBUFFER 1
-#undef  CONFIG_NETUTILS_HTTPD_DUMPPSTATE
+#undef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
+#undef CONFIG_NETUTILS_HTTPD_DUMPPSTATE
 
 /****************************************************************************
  * Private Data