The first set of changes to incorporate Jason Jiangs TCP write buffering logic

This commit is contained in:
Gregory Nutt
2014-01-13 17:11:01 -06:00
parent 486314ad05
commit a9e44cdfe0
14 changed files with 1488 additions and 629 deletions
+6
View File
@@ -6422,3 +6422,9 @@
the changes does not seem to do any harm (2014-1-13).
* net/connect.c and net/uip/uip_callback.c: prevent tcp_connect
callback from being double freed. From Max Holtzberg (2014-1-13).
* net/Kconfig and include/nuttx/net/uip/uipopt.h: Add configuration
support for forthcoming TCP write buffering (2014-1-13).
* net/net_send_buffered.c, net_send_unbuffered.c, and
uip/uip_tcpwrbuffer.c: First set of changes to bring in Jason
Jiang's TCP write buffering logic. Still not complete but
apparently harmless if not selected. (2014-1-13).
+8 -2
View File
@@ -51,7 +51,7 @@
#include <nuttx/net/uip/uip.h>
/****************************************************************************
* Definitions
* Pre-processor Definitions
****************************************************************************/
/* Socket descriptors are the index into the TCB sockets list, offset by the
@@ -101,6 +101,12 @@ struct socket
#endif
#endif
FAR void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */
#ifdef CONFIG_NET_TCP_WRBUFFER
/* Callback instance for TCP send */
FAR struct uip_callback_s *s_sndcb;
#endif
};
/* This defines a list of sockets indexed by the socket descriptor */
@@ -108,7 +114,7 @@ struct socket
#if CONFIG_NSOCKET_DESCRIPTORS > 0
struct socketlist
{
sem_t sl_sem; /* Manage access to the socket list */
sem_t sl_sem; /* Manage access to the socket list */
struct socket sl_sockets[CONFIG_NSOCKET_DESCRIPTORS];
};
#endif
+60 -24
View File
@@ -144,15 +144,9 @@ struct uip_conn
{
dq_entry_t node; /* Implements a doubly linked list */
uip_ipaddr_t ripaddr; /* The IP address of the remote host */
uint16_t lport; /* The local TCP port, in network byte order */
uint16_t rport; /* The remoteTCP port, in network byte order */
uint8_t rcvseq[4]; /* The sequence number that we expect to
* receive next */
uint8_t sndseq[4]; /* The sequence number that was last sent by us */
uint16_t unacked; /* Number bytes sent but not yet ACKed */
uint16_t mss; /* Current maximum segment size for the
* connection */
uint16_t winsize; /* Current window size of the connection */
uint8_t crefs; /* Reference counts on this instance */
uint8_t sa; /* Retransmission time-out calculation state
* variable */
@@ -163,6 +157,16 @@ struct uip_conn
uint8_t timer; /* The retransmission timer (units: half-seconds) */
uint8_t nrtx; /* The number of retransmissions for the last
* segment sent */
uint16_t lport; /* The local TCP port, in network byte order */
uint16_t rport; /* The remoteTCP port, in network byte order */
uint16_t mss; /* Current maximum segment size for the
* connection */
uint16_t winsize; /* Current window size of the connection */
#ifdef CONFIG_NET_TCP_WRBUFFER
uint32_t unacked; /* Number bytes sent but not yet ACKed */
#else
uint16_t unacked; /* Number bytes sent but not yet ACKed */
#endif
/* Read-ahead buffering.
*
@@ -174,6 +178,17 @@ struct uip_conn
sq_queue_t readahead; /* Read-ahead buffering */
#endif
/* Write buffering */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
sq_queue_t write_q; /* Write buffering for segments */
sq_queue_t unacked_q; /* Write buffering for un-ACKed segments */
size_t expired; /* Number segments retransmitted but not yet ACKed,
* it can only be updated at UIP_ESTABLISHED state */
size_t sent; /* The number of bytes sent */
uint32_t isn; /* Initial sequence number */
#endif
/* Listen backlog support
*
* blparent - The backlog parent. If this connection is backlogged,
@@ -238,8 +253,22 @@ struct uip_conn
struct uip_readahead_s
{
sq_entry_t rh_node; /* Supports a singly linked list */
uint16_t rh_nbytes; /* Number of bytes available in this buffer */
uint8_t rh_buffer[CONFIG_NET_TCP_READAHEAD_BUFSIZE];
uint16_t rh_nbytes; /* Number of bytes available in this buffer */
uint8_t rh_buffer[CONFIG_NET_TCP_READAHEAD_BUFSIZE];
};
#endif
/* This structure supports TCP write buffering */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
struct uip_wrbuffer_s
{
sq_entry_t wb_node; /* Supports a singly linked list */
uint32_t wb_seqno; /* Sequence number of the write segment */
uint16_t wb_nbytes; /* Number of bytes available in this buffer */
uint8_t wb_nrtx; /* The number of retransmissions for the last
* segment sent */
uint8_t wb_buffer[CONFIG_NET_TCP_WRITE_BUFSIZE];
};
#endif
@@ -350,7 +379,7 @@ struct uip_tcpip_hdr
* normally something done by the implementation of the socket() API
*/
extern struct uip_conn *uip_tcpalloc(void);
struct uip_conn *uip_tcpalloc(void);
/* Allocate a new TCP data callback */
@@ -361,14 +390,14 @@ extern struct uip_conn *uip_tcpalloc(void);
* be done by the implementation of close()
*/
extern void uip_tcpfree(struct uip_conn *conn);
void uip_tcpfree(struct uip_conn *conn);
/* Bind a TCP connection to a local address */
#ifdef CONFIG_NET_IPv6
extern int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr);
int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr);
#else
extern int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr);
int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr);
#endif
/* This function implements the UIP specific parts of the standard
@@ -386,44 +415,51 @@ extern int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr);
*/
#ifdef CONFIG_NET_IPv6
extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr);
int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in6 *addr);
#else
extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr);
int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr);
#endif
/* Start listening to the port bound to the specified TCP connection */
extern int uip_listen(struct uip_conn *conn);
int uip_listen(struct uip_conn *conn);
/* Stop listening to the port bound to the specified TCP connection */
extern int uip_unlisten(struct uip_conn *conn);
int uip_unlisten(struct uip_conn *conn);
/* Access to TCP read-ahead buffers */
#ifdef CONFIG_NET_TCP_READAHEAD
extern struct uip_readahead_s *uip_tcpreadaheadalloc(void);
extern void uip_tcpreadaheadrelease(struct uip_readahead_s *buf);
struct uip_readahead_s *uip_tcpreadaheadalloc(void);
void uip_tcpreadaheadrelease(struct uip_readahead_s *buf);
#endif /* CONFIG_NET_TCP_READAHEAD */
/* Access to TCP write buffers */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
FAR struct uip_wrbuffer_s *uip_tcpwrbuffer_alloc(FAR const struct timespec *abstime);
void uip_tcpwrbuffer_release(FAR struct uip_wrbuffer_s *buf);
#endif /* CONFIG_NET_NTCP_READAHEAD_BUFFERS */
/* Backlog support */
#ifdef CONFIG_NET_TCPBACKLOG
/* APIs to create and terminate TCP backlog support */
extern int uip_backlogcreate(FAR struct uip_conn *conn, int nblg);
extern int uip_backlogdestroy(FAR struct uip_conn *conn);
int uip_backlogcreate(FAR struct uip_conn *conn, int nblg);
int uip_backlogdestroy(FAR struct uip_conn *conn);
/* APIs to manage individual backlog actions */
extern int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn);
int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn);
#ifndef CONFIG_DISABLE_POLL
extern bool uip_backlogavailable(FAR struct uip_conn *conn);
bool uip_backlogavailable(FAR struct uip_conn *conn);
#else
# define uip_backlogavailable(conn) (false);
#endif
extern FAR struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn);
extern int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn);
FAR struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn);
int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn);
#else
# define uip_backlogcreate(conn,nblg) (-ENOSYS)
+1 -1
View File
@@ -16,7 +16,7 @@
* Note: Most of the configuration options in the uipopt.h should not
* be changed, but rather the per-project defconfig file.
*
* Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was leveraged from uIP which also has a BSD-style license:
+2 -1
View File
@@ -75,7 +75,7 @@ config NET_SOCKOPTS
config NET_SOLINGER
bool "SO_LINGER socket option"
default n
depends on NET_SOCKOPTS && !DISABLE_CLOCK
depends on NET_SOCKOPTS && NET_TCP_WRITE_BUFFERS && !DISABLE_CLOCK
---help---
Enable or disable support for the SO_LINGER socket option.
@@ -210,6 +210,7 @@ config NET_TCPBACKLOG
config NET_TCP_SPLIT
bool "Enable packet splitting"
default n
depends on !NET_TCP_WRITE_BUFFERS
---help---
send() will not return until the transfer has been ACKed by the
recipient. But under RFC 1122, the host need not ACK each packet
+8 -2
View File
@@ -1,7 +1,7 @@
############################################################################
# net/Makefile
#
# Copyright (C) 2007, 2008, 2011-2013 Gregory Nutt. All rights reserved.
# Copyright (C) 2007, 2008, 2011-2014 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -41,13 +41,19 @@ ifeq ($(CONFIG_NET),y)
SOCK_ASRCS =
SOCK_CSRCS = bind.c connect.c getsockname.c recv.c recvfrom.c socket.c
SOCK_CSRCS += sendto.c net_sockets.c net_close.c net_dup.c net_dup2.c
SOCK_CSRCS += sendto.c net_sockets.c net_close.c net_dup.c net_dup2.c
SOCK_CSRCS += net_clone.c net_vfcntl.c
# TCP/IP support
ifeq ($(CONFIG_NET_TCP),y)
SOCK_CSRCS += send.c listen.c accept.c net_monitor.c
ifeq ($(CONFIG_NET_TCP_WRBUFFER),y)
SOCK_CSRCS += net_send_buffered.c
else
SOCK_CSRCS += net_send_unbuffered.c
endif
endif
# Socket options
+5 -4
View File
@@ -196,8 +196,7 @@ static uint16_t netclose_interrupt(FAR struct uip_driver_s *dev,
}
}
#ifdef CONFIG_NET_SOLINGER
#ifndef CONFIG_DISABLE_CLOCK
#if defined(CONFIG_NET_SOLINGER) && !defined(CONFIG_DISABLE_CLOCK)
/* Check for a timeout. */
else if (pstate && close_timeout(pstate))
@@ -208,8 +207,10 @@ static uint16_t netclose_interrupt(FAR struct uip_driver_s *dev,
pstate->cl_result = -ETIMEDOUT;
goto end_wait;
}
#endif /* CONFIG_DISABLE_CLOCK */
#endif /* CONFIG_NET_SOLINGER && !CONFIG_DISABLE_CLOCK */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
/* Check if all outstanding bytes have been ACKed */
else if (pstate && conn->unacked != 0)
@@ -222,7 +223,7 @@ static uint16_t netclose_interrupt(FAR struct uip_driver_s *dev,
flags = (flags & ~UIP_NEWDATA);
}
#endif /* CONFIG_NET_SOLINGER */
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS */
else
{
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -575
View File
File diff suppressed because it is too large Load Diff
+9 -5
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket.c
*
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -128,6 +128,9 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
psock->s_type = type;
psock->s_conn = NULL;
#ifdef CONFIG_NET_TCP_WRBUFFER
psock->s_sndcb = NULL;
#endif
/* Allocate the appropriate connection structure. This reserves the
* the connection structure is is unallocated at this point. It will
@@ -153,8 +156,11 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
*/
DEBUGASSERT(conn->crefs == 0);
psock->s_conn = conn;
conn->crefs = 1;
psock->s_conn = conn;
conn->crefs = 1;
#ifdef CONFIG_NET_TCP_WRBUFFER
psock->s_sndcb = NULL;
#endif
}
}
break;
@@ -282,5 +288,3 @@ errout:
}
#endif /* CONFIG_NET */
+22 -14
View File
@@ -1,7 +1,7 @@
############################################################################
# Make.defs
# net/uip/Make.defs
#
# Copyright (C) 2007, 2009-20010 Gregory Nutt. All rights reserved.
# Copyright (C) 2007, 2009-2010, 2014 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -40,8 +40,8 @@ ifeq ($(CONFIG_NET),y)
# Common IP source files
UIP_CSRCS += uip_initialize.c uip_setipid.c uip_input.c uip_send.c \
uip_poll.c uip_chksum.c uip_callback.c
UIP_CSRCS += uip_initialize.c uip_setipid.c uip_input.c uip_send.c
UIP_CSRCS += uip_poll.c uip_chksum.c uip_callback.c
# Non-interrupt level support required?
@@ -65,18 +65,28 @@ endif
ifeq ($(CONFIG_NET_TCP),y)
UIP_CSRCS += uip_tcpconn.c uip_tcpseqno.c uip_tcppoll.c uip_tcptimer.c uip_tcpsend.c \
uip_tcpinput.c uip_tcpappsend.c uip_listen.c uip_tcpcallback.c \
uip_tcpreadahead.c uip_tcpbacklog.c
UIP_CSRCS += uip_tcpconn.c uip_tcpseqno.c uip_tcppoll.c uip_tcptimer.c
UIP_CSRCS += uip_tcpsend.c uip_tcpinput.c uip_tcpappsend.c uip_listen.c
UIP_CSRCS += uip_tcpcallback.c uip_tcpbacklog.c
endif
# Buffering
ifeq ($(CONFIG_NET_TCP_READAHEAD),y)
UIP_CSRCS += uip_tcpreadahead.c
endif
ifeq ($(CONFIG_NET_TCP_WRBUFFER),y)
UIP_CSRCS += uip_tcpwrbuffer.c
endif
# UDP source files
ifeq ($(CONFIG_NET_UDP),y)
UIP_CSRCS += uip_udpconn.c uip_udppoll.c uip_udpsend.c uip_udpinput.c \
uip_udpcallback.c
UIP_CSRCS += uip_udpconn.c uip_udppoll.c uip_udpsend.c uip_udpinput.c
UIP_CSRCS += uip_udpcallback.c
endif
@@ -95,12 +105,10 @@ endif
# IGMP source files
ifeq ($(CONFIG_NET_IGMP),y)
UIP_CSRCS += uip_igmpgroup.c uip_igmpinit.c uip_igmpinput.c uip_igmpjoin.c \
uip_igmpleave.c uip_igmpmsg.c uip_igmpsend.c uip_igmptimer.c \
uip_mcastmac.c
UIP_CSRCS += uip_igmpgroup.c uip_igmpinit.c uip_igmpinput.c uip_igmpjoin.c
UIP_CSRCS += uip_igmpleave.c uip_igmpmsg.c uip_igmpsend.c uip_igmptimer.c
UIP_CSRCS += uip_mcastmac.c
endif
endif
endif
+6 -1
View File
@@ -139,6 +139,12 @@ void uip_initialize(void)
#endif
#endif /* CONFIG_NET_TCP */
/* Initialize the TCP/IP write buffering */
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
uip_tcpwrbuffer_init();
#endif
/* Initialize the UDP connection structures */
#ifdef CONFIG_NET_UDP
@@ -152,4 +158,3 @@ void uip_initialize(void)
#endif
}
#endif /* CONFIG_NET */
+165
View File
@@ -0,0 +1,165 @@
/****************************************************************************
* net/uip/uip_tcpwrbuffer.c
*
* Copyright (C) 2007-2009, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Jason Jiang <jasonj@live.cn>
*
* 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/net/uip/uipopt.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) && defined(CONFIG_NET_TCP_WRITE_BUFFERS)
#include <queue.h>
#include <semaphore.h>
#include <debug.h>
#include "uip_internal.h"
/****************************************************************************
* Private Types
****************************************************************************/
/* Package all globals used by this logic into a structure */
struct wrbuffer_s
{
/* The semaphore to protect the buffers */
sem_t sem;
/* This is the list of available write buffers */
sq_queue_t freebuffers;
/* These are the pre-allocated write buffers */
struct uip_wrbuffer_s buffers[CONFIG_NET_NTCP_WRITE_BUFFERS];
};
/****************************************************************************
* Private Data
****************************************************************************/
/* This is the state of the global write buffer resource */
static struct wrbuffer_s g_wrbuffer;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: uip_tcpwrbuffer_init
*
* Description:
* Initialize the list of free write buffers
*
* Assumptions:
* Called once early initialization.
*
****************************************************************************/
void uip_tcpwrbuffer_init(void)
{
int i;
sq_init(&g_wrbuffer.freebuffers);
for (i = 0; i < CONFIG_NET_NTCP_WRITE_BUFFERS; i++)
{
sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers);
}
sem_init(&g_wrbuffer.sem, 0, CONFIG_NET_NTCP_WRITE_BUFFERS);
}
/****************************************************************************
* Function: uip_tcpwrbuffer_alloc
*
* Description:
* Allocate a TCP write buffer by taking a pre-allocated buffer from
* the free list. This function is called from TCP logic when a buffer
* of TCP data is about to sent
*
* Assumptions:
* Called from user logic with interrupts enabled.
*
****************************************************************************/
FAR struct uip_wrbuffer_s *uip_tcpwrbuffer_alloc(FAR const struct timespec *abstime)
{
int ret;
if (abstime)
{
ret = sem_timedwait(&g_wrbuffer.sem, abstime);
}
else
{
ret = sem_wait(&g_wrbuffer.sem);
}
if (ret != 0)
{
return NULL;
}
return (FAR struct uip_wrbuffer_s*)sq_remfirst(&g_wrbuffer.freebuffers);
}
/****************************************************************************
* Function: uip_tcpwrbuffer_release
*
* Description:
* Release a TCP write buffer by returning the buffer to the free list.
* This function is called from user logic after it is consumed the buffered
* data.
*
* Assumptions:
* Called from interrupt level with interrupts disabled.
*
****************************************************************************/
void uip_tcpwrbuffer_release(FAR struct uip_wrbuffer_s *wrbuffer)
{
sq_addlast(&wrbuffer->wb_node, &g_wrbuffer.freebuffers);
sem_post(&g_wrbuffer.sem);
}
#endif /* CONFIG_NET && CONFIG_NET_TCP && CONFIG_NET_NTCP_WRITE_BUFFERS*/