diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-19 16:40:43 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-01-19 16:40:43 +0000 |
commit | 070651221f4f60c2074e7641affa10e2b8714f07 (patch) | |
tree | 38615943a732fd25e20509600f99745f2cee68ec /nuttx | |
parent | 53e8b454bf671e2b7e2cfe1898468543ab231984 (diff) | |
download | px4-firmware-070651221f4f60c2074e7641affa10e2b8714f07.tar.gz px4-firmware-070651221f4f60c2074e7641affa10e2b8714f07.tar.bz2 px4-firmware-070651221f4f60c2074e7641affa10e2b8714f07.zip |
Add split package logic to improve TCP send performance with delayed ACKs
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5538 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 2 | ||||
-rwxr-xr-x | nuttx/configs/olimex-lpc1766stk/nsh/defconfig | 14 | ||||
-rw-r--r-- | nuttx/net/Kconfig | 35 | ||||
-rw-r--r-- | nuttx/net/send.c | 99 |
4 files changed, 147 insertions, 3 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index a5bcaf1bc..122187410 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3987,3 +3987,5 @@ * configs/open1788: Board configuration for the Wave Share Open1788 board. Still fragmentary (contribnuted by Rommel Marcelo, adapted to use kconfig-frontends. + * net/send(): Add logic to work around delayed ACKs by splitting + packets (contributed by Yan T.). diff --git a/nuttx/configs/olimex-lpc1766stk/nsh/defconfig b/nuttx/configs/olimex-lpc1766stk/nsh/defconfig index 0f16933b8..c77f3f0c2 100755 --- a/nuttx/configs/olimex-lpc1766stk/nsh/defconfig +++ b/nuttx/configs/olimex-lpc1766stk/nsh/defconfig @@ -194,6 +194,10 @@ CONFIG_NET_PRIORITY=0 # # +# External Memory Configuration +# + +# # Architecture Options # # CONFIG_ARCH_NOINTC is not set @@ -396,6 +400,10 @@ CONFIG_NET_NACTIVESOCKETS=16 CONFIG_NET_SOCKOPTS=y CONFIG_NET_BUFSIZE=562 # CONFIG_NET_TCPURGDATA is not set + +# +# TCP/IP Networking +# CONFIG_NET_TCP=y CONFIG_NET_TCP_CONNS=8 CONFIG_NET_MAX_LISTENPORTS=8 @@ -403,6 +411,12 @@ CONFIG_NET_TCP_READAHEAD_BUFSIZE=562 CONFIG_NET_NTCP_READAHEAD_BUFFERS=16 CONFIG_NET_TCP_RECVDELAY=0 # CONFIG_NET_TCPBACKLOG is not set +CONFIG_NET_TCP_SPLIT=y +CONFIG_NET_TCP_SPLIT_SIZE=40 + +# +# UDP Networking +# CONFIG_NET_UDP=y CONFIG_NET_UDP_CHECKSUMS=y CONFIG_NET_UDP_CONNS=8 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); |