diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index 9feed6e2cc..0f4ddc0ecf 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/mm/iob.h * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -183,6 +183,16 @@ FAR struct iob_s *iob_alloc(bool throttled); FAR struct iob_s *iob_tryalloc(bool throttled); +/**************************************************************************** + * Name: iob_navail + * + * Description: + * Return the number of of available IOBs. + * + ****************************************************************************/ + +int iob_navail(void); + /**************************************************************************** * Name: iob_free * diff --git a/mm/iob/Make.defs b/mm/iob/Make.defs index bdfd11d7c1..87d3b4614f 100644 --- a/mm/iob/Make.defs +++ b/mm/iob/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # mm/iob/Make.defs # -# Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved. +# Copyright (C) 2014, 2017-2018 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -42,6 +42,7 @@ CSRCS += iob_concat.c iob_copyin.c iob_copyout.c iob_contig.c iob_free.c CSRCS += iob_free_chain.c iob_free_qentry.c iob_free_queue.c CSRCS += iob_initialize.c iob_pack.c iob_peek_queue.c iob_remove_queue.c CSRCS += iob_trimhead.c iob_trimhead_queue.c iob_trimtail.c +CSRCS += iob_navail.c ifeq ($(CONFIG_DEBUG_FEATURES),y) CSRCS += iob_dump.c diff --git a/mm/iob/iob_navail.c b/mm/iob/iob_navail.c new file mode 100644 index 0000000000..81b8cad3ac --- /dev/null +++ b/mm/iob/iob_navail.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * mm/iob/iob_navail.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "iob.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: iob_navail + * + * Description: + * Return the number of of available IOBs. + * + ****************************************************************************/ + +int iob_navail(void) +{ + int navail = 0; + int ret; + + ret = nxsem_getvalue(&g_qentry_sem, &navail); + if (ret >= 0) + { + ret = navail; + } + + return ret; +} diff --git a/net/Kconfig b/net/Kconfig index 3acaaf63a0..339b33e0a3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -61,12 +61,17 @@ config NET_ETH_TCP_RECVWNDO default 1220 if NET_IPv6 default 536 if !NET_IPv6 depends on NET_ETHERNET && NET_TCP + range 536 65535 ---help--- The size of the advertised receiver's window. Should be set low (i.e., to the size of the MSS) if the application is slow to process - incoming data, or high (32768 bytes) if the application processes + incoming data, or high (65,535 bytes) if the application processes data quickly. + This value does not account for buffering provided for read-ahead + buffering via IOBs. To include IOB aware windowing logic also + enable CONFIG_NET_TCP_RWND_CONTROL. + config NET_SLIP_MTU int # "SLIP packet buffer size (MTU)" default 296 diff --git a/net/tcp/Kconfig b/net/tcp/Kconfig index 4b7b7059f5..c11192e81f 100644 --- a/net/tcp/Kconfig +++ b/net/tcp/Kconfig @@ -178,9 +178,12 @@ endif # NET_TCP && !NET_TCP_NO_STACK config NET_TCP_RWND_CONTROL bool "Receive window control based on IOBuffer" default n - depends on MM_IOB + depends on NET_READAHEAD ---help--- Support receive window control based on I/O buffer. This feature is still experimental. + This feature, if enabled, will assume that the every IOB is + available for read-ahead storage of TCP packets. + endmenu # TCP/IP Networking diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c index 2cb206ed26..005e64d9c7 100644 --- a/net/tcp/tcp_send.c +++ b/net/tcp/tcp_send.c @@ -1,7 +1,8 @@ /**************************************************************************** * net/tcp/tcp_send.c * - * Copyright (C) 2007-2010, 2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2010, 2012, 2015, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Adapted for NuttX from logic in uIP which also has a BSD-like license: @@ -314,9 +315,10 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp) { #ifdef CONFIG_NET_TCP_RWND_CONTROL - extern sem_t g_qentry_sem; - int qentry_sem_count; uint32_t rwnd; + uint16_t iplen; + uint16_t overhead; + int navail; #endif /* Copy the IP address into the IPv6 header */ @@ -327,8 +329,13 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, #endif { FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; + net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); net_ipv6addr_hdrcopy(ipv6->destipaddr, conn->u.ipv6.raddr); + +#ifdef CONFIG_NET_TCP_RWND_CONTROL + iplen = IPv6_HDRLEN; +#endif } #endif /* CONFIG_NET_IPv6 */ @@ -338,8 +345,13 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, #endif { FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; + net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr); + +#ifdef CONFIG_NET_TCP_RWND_CONTROL + iplen = IPv4_HDRLEN; +#endif } #endif /* CONFIG_NET_IPv4 */ @@ -352,16 +364,64 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, tcp->destport = conn->rport; #ifdef CONFIG_NET_TCP_RWND_CONTROL - /* Update the TCP received window based on I/O buffer */ + /* Update the TCP received window based on I/O buffer availability */ /* NOTE: This algorithm is still experimental */ - if (OK == nxsem_getvalue(&g_qentry_sem, &qentry_sem_count)) + overhead = NET_LL_HDRLEN(dev) + iplen + TCP_HDRLEN; + navail = iob_navail(); + if (navail > 0) { - rwnd = (qentry_sem_count * CONFIG_NET_ETH_TCP_RECVWNDO) - / CONFIG_IOB_NCHAINS; + /* The optimal TCP window size is the amount of TCP data that we can + * currently buffer via TCP read-ahead buffering minus overhead for the + * link-layer, IP, and TCP headers. This logic here assumes that + * all IOBs are available for TCP buffering. + * + * REVISIT: In an environment with mutliple, active read-ahead TCP + * sockets (and perhaps multiple network devices) or if there are + * other consumers of IOBs (such as for TCP write buffering) then the + * total number of IOBs will all not be available for read-ahead + * buffering for this connection. + */ + +#if 0 + /* REVISIT: (1)CONFIG_NET_ETH_TCP_RECVWNDO will typically be larger + * than the IOB payload size. (2) Why divide by CONFIG_IOB_NCHAINS? + * (3) CONFIG_NET_ETH_TCP_RECVWNDO includes the header overhead + * penalty. But we only have to pay the header overhead penalty + * once. (4) This logic needs to work even if Ethernet is not + * enabled (and hence CONFIG_NET_ETH_TCP_RECVWNDO is not defined). + */ + + rwnd = (navail * CONFIG_NET_ETH_TCP_RECVWNDO) / CONFIG_IOB_NCHAINS; +#else + /* Assume that all of the available IOBs are can be used for buffering + * on this connection. + */ + + rwnd = (navail * CONFIG_IOB_BUFSIZE) - overhead; +#endif + + /* Save the new receive window size */ + + if (rwnd > UINT16_MAX) + { + rwnd = UINT16_MAX; + } NET_DEV_RCVWNDO(dev) = (uint16_t)rwnd; } + else /* (navail == 0) */ + { + /* No IOBs are available... fall back to the configured default + * which assumes no write buffering. The only buffering available + * is the packet itself. + * + * NOTE: If no IOBs are available, then the next packet will be + * lost will be be lost if there is no listener on the connection. + */ + + NET_DEV_RCVWNDO(dev) = dev->d_mtu - overhead; + } #endif /* Set the TCP window */