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/net | |
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/net')
-rw-r--r-- | nuttx/net/Kconfig | 35 | ||||
-rw-r--r-- | nuttx/net/send.c | 99 |
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); |