summaryrefslogtreecommitdiff
path: root/nuttx/net
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-19 16:40:43 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-19 16:40:43 +0000
commit0aad9ccecb8d4fbb8712cbf050fe7654168e0c13 (patch)
tree38615943a732fd25e20509600f99745f2cee68ec /nuttx/net
parent153ab5ddf5454d559da0d30751a7acb49e2c8d68 (diff)
downloadpx4-nuttx-0aad9ccecb8d4fbb8712cbf050fe7654168e0c13.tar.gz
px4-nuttx-0aad9ccecb8d4fbb8712cbf050fe7654168e0c13.tar.bz2
px4-nuttx-0aad9ccecb8d4fbb8712cbf050fe7654168e0c13.zip
Add split package logic to improve TCP send performance with delayed ACKs
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5538 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net')
-rw-r--r--nuttx/net/Kconfig35
-rw-r--r--nuttx/net/send.c99
2 files changed, 131 insertions, 3 deletions
diff --git a/nuttx/net/Kconfig b/nuttx/net/Kconfig
index d4ea8befb..6a084914f 100644
--- a/nuttx/net/Kconfig
+++ b/nuttx/net/Kconfig
@@ -97,14 +97,14 @@ config NET_TCPURGDATA
compiled in. Urgent data (out-of-band data) is a rarely used TCP feature
that is very seldom would be required.
+menu "TCP/IP Networking"
+
config NET_TCP
bool "TCP/IP Networking"
default n
---help---
TCP support on or off
-endif
-
if NET_TCP
config NET_TCP_CONNS
int "Number of TCP/IP connections"
@@ -164,7 +164,36 @@ config NET_TCPBACKLOG
Incoming connections pend in a backlog until accept() is called.
The size of the backlog is selected when listen() is called.
+config NET_TCP_SPLIT
+ bool "Enable packet splitting"
+ default n
+ ---help---
+ send() will not return until the the transfer has been ACKed by the
+ recipient. But under RFC 1122, the host need not ACK each packet
+ immediately; the host may wait for 500 MS before ACKing. This
+ combination can cause very slow performance with small transfers are
+ made to an RFC 1122 client. However, the RFC 1122 must ACK at least
+ every second (odd) packet.
+
+ This option enables logic to trick the RFC 1122 host be exploiting
+ this last RFC 1122 requirement: If an odd number of packets were to
+ be sent, then send() will split the last even packet to guarantee
+ that an even number of packets will be sent and the RFC 1122 host
+ will ACK the final packet immediately.
+
+if NET_TCP_SPLIT
+
+config NET_TCP_SPLIT_SIZE
+ int "Split size threshold"
+ default 40
+ ---help---
+ Packets of this size or smaller than this will not be split.
+
endif
+endif
+endmenu
+
+menu "UDP Networking"
config NET_UDP
bool "UDP Networking"
@@ -193,6 +222,7 @@ config NET_BROADCAST
Incoming UDP broadcast support
endif
+endmenu
config NET_ICMP
bool "ICMP networking support"
@@ -321,3 +351,4 @@ config SLIP_DEFPRIO
The priority of the SLIP RX and TX tasks. Default: 128
endif
+endif
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 8a5154191..b75a864e3 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/send.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,9 @@
#include <sys/types.h>
#include <sys/socket.h>
+
#include <stdint.h>
+#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
@@ -62,6 +64,10 @@
* Definitions
****************************************************************************/
+#if defined(CONFIG_NET_TCP_SPLIT) && !defined(CONFIG_NET_TCP_SPLIT_SIZE)
+# define CONFIG_NET_TCP_SPLIT_SIZE 40
+#endif
+
#define TCPBUF ((struct uip_tcpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
/****************************************************************************
@@ -85,6 +91,9 @@ struct send_s
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
uint32_t snd_time; /* last send time for determining timeout */
#endif
+#if defined(CONFIG_NET_TCP_SPLIT)
+ bool snd_odd; /* True: Odd packet in pair transaction */
+#endif
};
/****************************************************************************
@@ -200,6 +209,14 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
pstate->snd_sent = pstate->snd_acked;
+#if defined(CONFIG_NET_TCP_SPLIT)
+ /* Reset the the even/odd indicator to even since we need to
+ * retransmit.
+ */
+
+ pstate->snd_odd = false;
+#endif
+
/* Fall through to re-send data from the last that was ACKed */
}
@@ -242,6 +259,86 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
/* Get the amount of data that we can send in the next packet */
uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;
+
+
+#if defined(CONFIG_NET_TCP_SPLIT)
+
+ /* RFC 1122 states that a host may delay ACKing for up to 500ms but
+ * must respond to every second segment). This logic here will trick
+ * the RFC 1122 recipient into responding sooner. This logic will be
+ * activated if:
+ *
+ * 1. An even number of packets has been send (where zero is an even
+ * number),
+ * 2. There is more data be sent (more than or equal to
+ * CONFIG_NET_TCP_SPLIT_SIZE), but
+ * 3. Not enough data for two packets.
+ *
+ * Then we will split the remaining, single packet into two partial
+ * packets. This will stimulate the RFC 1122 not into ACKing sooner.
+ *
+ * Check if there is more data to be sent (more than or equal to
+ * CONFIG_NET_TCP_SPLIT_SIZE):
+ */
+
+ if (sndlen >= CONFIG_NET_TCP_SPLIT_SIZE)
+ {
+ /* sndlen is the number of bytes remaining to be sent.
+ * uip_mss(conn) will return the number of bytes that can sent
+ * in one packet. The difference, then, is the number of bytes
+ * that would be sent in the next packet after this one.
+ */
+
+ int32_t next_sndlen = sndlen - uip_mss(conn);
+
+ /* Is this the even packet in the packet pair transaction? */
+
+ if (!pstate->snd_odd)
+ {
+ /* next_sndlen <= 0 means that the entire remaining data
+ * could fit into this single packet. This is condition
+ * in which we must do the split.
+ */
+
+ if (next_sndlen <= 0)
+ {
+ /* Split so that there will be an odd packet. Here
+ * we know that 0 < sndlen <= MSS
+ */
+
+ sndlen = (sndlen / 2) + 1;
+ }
+ }
+
+ /* No... this is the odd packet in the packet pair transaction */
+
+ else
+ {
+ /* Will there be another (even) packet afer this one?
+ * (next_sndlen > 0) Will the split conidition occur on that
+ * next, even packet? ((next_sndlen - uip_mss(conn)) < 0) If
+ * so, then perform the split now to avoid the case where the
+ * byte count is less than CONFIG_NET_TCP_SPLIT_SIZE on the
+ * next pair.
+ */
+
+ if (next_sndlen > 0 && (next_sndlen - uip_mss(conn)) < 0)
+ {
+ /* Here, we know that sndlen must be MSS <= sndlen <= 2*MSS
+ * and so (sndlen / 2) is <= MSS.
+ */
+
+ sndlen /= 2;
+ }
+ }
+ }
+
+ /* Toggle the even/odd indicator */
+
+ pstate->snd_odd ^= true;
+
+#endif /* CONFIG_NET_TCP_SPLIT */
+
if (sndlen > uip_mss(conn))
{
sndlen = uip_mss(conn);