summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-12-06 23:10:31 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-12-06 23:10:31 +0000
commitc9c4a58af6383cc524f4ebdbfaea3a117ebaf8c3 (patch)
tree952a99a56375ea4591f2d44aee065e7f02601b83
parentbedbe4f4b09fc925b7c204cc358bc32d5b48064c (diff)
downloadnuttx-c9c4a58af6383cc524f4ebdbfaea3a117ebaf8c3.tar.gz
nuttx-c9c4a58af6383cc524f4ebdbfaea3a117ebaf8c3.tar.bz2
nuttx-c9c4a58af6383cc524f4ebdbfaea3a117ebaf8c3.zip
Improved read-ahead buffer management
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@430 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog1
-rw-r--r--nuttx/Documentation/NuttX.html1
-rw-r--r--nuttx/net/uip/uip-tcpcallback.c100
3 files changed, 78 insertions, 24 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index e944fc6b2..77b2207f6 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -268,3 +268,4 @@
* Implemented send() timeout logic
* Add a skeleton Ethernet device driver (drivers/net/skeleton.c)
* Added C5471 Ethernet device driver (arch/arm/src/c5471/c5471_ethernet.c)
+ * Improved utilization of read-ahead buffers
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 45064cf89..b5996a81f 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -964,6 +964,7 @@ Other memory:
* Add TELNETD front end to NSH (examples/nsh)
* Add a skeleton Ethernet device driver (drivers/net/skeleton.c)
* Added C5471 Ethernet device driver (arch/arm/src/c5471/c5471_ethernet.c)
+ * Improved utilization of read-ahead buffers
</pre></ul>
<table width ="100%">
diff --git a/nuttx/net/uip/uip-tcpcallback.c b/nuttx/net/uip/uip-tcpcallback.c
index d96e97981..7c7fb2209 100644
--- a/nuttx/net/uip/uip-tcpcallback.c
+++ b/nuttx/net/uip/uip-tcpcallback.c
@@ -60,6 +60,45 @@
****************************************************************************/
/****************************************************************************
+ * Function: uip_readahead
+ *
+ * Description:
+ * Copy as much received data as possible into the readahead buffer
+ *
+ * Assumptions:
+ * This function is called at the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+static int uip_readahead(struct uip_readahead_s *readahead, uint8 *buf, int len)
+{
+ int available = CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead->rh_nbytes;
+ int recvlen = 0;
+
+ if (len > 0 && available > 0)
+ {
+ /* Get the length of the data to buffer. */
+
+ if (len > available)
+ {
+ recvlen = available;
+ }
+ else
+ {
+ recvlen = len;
+ }
+
+ /* Copy the new appdata into the read-ahead buffer */
+
+ memcpy(&readahead->rh_buffer[readahead->rh_nbytes], buf, recvlen);
+ readahead->rh_nbytes += recvlen;
+ }
+ return recvlen;
+}
+#endif
+
+/****************************************************************************
* Function: uip_dataevent
*
* Description:
@@ -74,10 +113,6 @@
static inline uint8
uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
{
-#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
- struct uip_readahead_s *readahead;
- uint16 recvlen;
-#endif
uint8 ret = flags;
/* Is there new data? With non-zero length? (Certain connection events
@@ -87,39 +122,56 @@ uip_dataevent(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
if ((flags & UIP_NEWDATA) != 0 && dev->d_len > 0)
{
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
- /* Allocate a read-ahead buffer to hold the newly received data */
+ struct uip_readahead_s *readahead1;
+ struct uip_readahead_s *readahead2 = NULL;
+ uint16 recvlen = 0;
+ uint8 *buf = dev->d_appdata;
+ int buflen = dev->d_len;
+
+ /* First, we need to determine if we have space to buffer the data. This
+ * needs to be verified before we actually begin buffering the data. We
+ * will use any remaining space in the last allocated readahead buffer
+ * plus as much one additional buffer. It is expected that the size of
+ * readahead buffers are tuned so that one full packet will always fit
+ * into one readahead buffer (for example if the buffer size is 420, then
+ * a readahead buffer of 366 will hold a full packet of TCP data).
+ */
- readahead = uip_tcpreadaheadalloc();
- if (readahead)
+ readahead1 = (struct uip_readahead_s*)conn->readahead.tail;
+ if ((readahead1 &&
+ (CONFIG_NET_TCP_READAHEAD_BUFSIZE - readahead1->rh_nbytes) > buflen) ||
+ (readahead2 = uip_tcpreadaheadalloc()) != NULL)
{
- /* Get the length of the data to buffer. If the sizes of the
- * read-ahead buffers are picked correct, they should always
- * hold the full received packet.\
+ /* We have buffer space. Now try to append add as much data as possible
+ * to the last readahead buffer attached to this connection.
*/
- if (dev->d_len > CONFIG_NET_TCP_READAHEAD_BUFSIZE)
- {
- recvlen = CONFIG_NET_TCP_READAHEAD_BUFSIZE;
- }
- else
+ if (readahead1)
{
- recvlen = dev->d_len;
+ recvlen = uip_readahead(readahead1, buf, buflen);
+ if (recvlen > 0)
+ {
+ buf += recvlen;
+ buflen -= recvlen;
+ }
}
- /* Copy the new appdata into the read-ahead buffer */
+ /* Do we need to buffer into the newly allocated buffer as well? */
- memcpy(readahead->rh_buffer, dev->d_appdata, recvlen);
- readahead->rh_nbytes = recvlen;
- nvdbg("Buffered %d bytes (of %d)\n", recvlen, dev->d_len);
+ if (readahead2)
+ {
+ (void)uip_readahead(readahead2, buf, buflen);
- /* Save the readahead buffer in the connection structure where
- * it can be found with recv() is called.
- */
+ /* Save the readahead buffer in the connection structure where
+ * it can be found with recv() is called.
+ */
- sq_addlast(&readahead->rh_node, &conn->readahead);
+ sq_addlast(&readahead2->rh_node, &conn->readahead);
+ }
/* Indicate that all of the data in the buffer has been consumed */
+ nvdbg("Buffered %d bytes\n", dev->d_len);
dev->d_len = 0;
}
else