net/tcp: Re-think CONFIG_NET_TCP_RWND_CONTROL TCP windowing controls.

This commit is contained in:
Gregory Nutt 2018-06-24 14:46:12 -06:00
parent 433f29eea2
commit 0786b5d053
6 changed files with 161 additions and 11 deletions

View File

@ -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 <gnutt@nuttx.org>
*
* 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
*

View File

@ -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 <gnutt@nuttx.org>
#
# 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

71
mm/iob/iob_navail.c Normal file
View File

@ -0,0 +1,71 @@
/****************************************************************************
* mm/iob/iob_navail.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <nuttx/semaphore.h>
#include <nuttx/mm/iob.h>
#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;
}

View File

@ -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

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
* 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 */