mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
This commit adds an as-of-yet untested implemented of UDP write buffering.
Squashed commit of the following:
net/udp: Address most of the issues with UDP write buffering. There is a remaining issue with handling one network going down in a multi-network environment. None of this has been test but it is certainly ready for test. Hence, the feature is marked EXPERIMENTAL.
net/udp: Some baby steps toward a corrected write buffering design.
net/udp: Remove pesky write buffer macros.
Eliminate trailing space at the end of lines.
net/udp: A little more UDP write buffering logic. Still at least on big gaping hole in the design.
net/udp: Undefined CONFIG_NET_SENDTO_TIMEOUT.
net/udp: Crude, naive port of the TCP write buffering logic into UDP. This commit is certainly non-functional and is simply a starting point for the implementatin of UDP write buffering.
net/udp: Rename udp/udp_psock_sendto.c udp/udp_psock_sendto_unbuffered.c.
This commit is contained in:
committed by
Matt Thompson
parent
055a3ef844
commit
880176e1cb
@@ -208,8 +208,8 @@ struct socket
|
||||
|
||||
FAR const struct sock_intf_s *s_sockif;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Callback instance for TCP send */
|
||||
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS)
|
||||
/* Callback instance for TCP send() or UDP sendto() */
|
||||
|
||||
FAR struct devif_callback_s *s_sndcb;
|
||||
#endif
|
||||
|
||||
+7
-7
@@ -16,9 +16,9 @@ if MM_IOB
|
||||
|
||||
config IOB_NBUFFERS
|
||||
int "Number of pre-allocated I/O buffers"
|
||||
default 24 if (NET_TCP_WRITE_BUFFERS && !NET_TCP_READAHEAD) || (!NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD)
|
||||
default 36 if NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD
|
||||
default 8 if !NET_TCP_WRITE_BUFFERS && !NET_TCP_READAHEAD
|
||||
default 24 if (NET_WRITE_BUFFERS && !NET_READAHEAD) || (!NET_WRITE_BUFFERS && NET_READAHEAD)
|
||||
default 36 if NET_WRITE_BUFFERS && NET_READAHEAD
|
||||
default 8 if !NET_WRITE_BUFFERS && !NET_READAHEAD
|
||||
---help---
|
||||
Each packet is represented by a series of small I/O buffers in a
|
||||
chain. This setting determines the number of preallocated I/O
|
||||
@@ -34,8 +34,8 @@ config IOB_BUFSIZE
|
||||
|
||||
config IOB_NCHAINS
|
||||
int "Number of pre-allocated I/O buffer chain heads"
|
||||
default 0 if !NET_TCP_READAHEAD && !NET_UDP_READAHEAD
|
||||
default 8 if NET_TCP_READAHEAD || NET_UDP_READAHEAD
|
||||
default 0 if !NET_READAHEAD && !NET_UDP_READAHEAD
|
||||
default 8 if NET_READAHEAD || NET_UDP_READAHEAD
|
||||
---help---
|
||||
These tiny nodes are used as "containers" to support queueing of
|
||||
I/O buffer chains. This will limit the number of I/O transactions
|
||||
@@ -49,8 +49,8 @@ config IOB_NCHAINS
|
||||
|
||||
config IOB_THROTTLE
|
||||
int "I/O buffer throttle value"
|
||||
default 0 if !NET_TCP_WRITE_BUFFERS || !NET_TCP_READAHEAD
|
||||
default 8 if NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD
|
||||
default 0 if !NET_WRITE_BUFFERS || !NET_READAHEAD
|
||||
default 8 if NET_WRITE_BUFFERS && NET_READAHEAD
|
||||
---help---
|
||||
TCP write buffering and read-ahead buffer use the same pool of free
|
||||
I/O buffers. In order to prevent uncontrolled incoming TCP packets
|
||||
|
||||
@@ -11,6 +11,14 @@ config ARCH_HAVE_PHY
|
||||
bool
|
||||
default n
|
||||
|
||||
config NET_WRITE_BUFFERS
|
||||
bool
|
||||
default n
|
||||
|
||||
config NET_READAHEAD
|
||||
bool
|
||||
default n
|
||||
|
||||
config NET
|
||||
bool "Networking support"
|
||||
default n
|
||||
|
||||
@@ -1146,7 +1146,7 @@ static ssize_t inet_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
#if defined(CONFIG_NET_6LOWPAN)
|
||||
/* Try 6LoWPAN UDP packet sendto() */
|
||||
|
||||
nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, tolen);
|
||||
nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, minlen);
|
||||
|
||||
#ifdef NET_UDP_HAVE_STACK
|
||||
if (nsent < 0)
|
||||
|
||||
@@ -172,6 +172,10 @@ void net_setup(void)
|
||||
/* Initialize the UDP connection structures */
|
||||
|
||||
udp_initialize();
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
udp_wrbuffer_initialize();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IGMP
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
|
||||
psock->s_domain = domain;
|
||||
psock->s_type = type;
|
||||
psock->s_conn = NULL;
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS)
|
||||
psock->s_sndcb = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
+3
-1
@@ -70,6 +70,7 @@ config NET_MAX_LISTENPORTS
|
||||
config NET_TCP_READAHEAD
|
||||
bool "Enable TCP/IP read-ahead buffering"
|
||||
default y
|
||||
select NET_READAHEAD
|
||||
select MM_IOB
|
||||
---help---
|
||||
Read-ahead buffers allows buffering of TCP/IP packets when there is no
|
||||
@@ -91,6 +92,7 @@ endif # NET_TCP_READAHEAD
|
||||
config NET_TCP_WRITE_BUFFERS
|
||||
bool "Enable TCP/IP write buffering"
|
||||
default n
|
||||
select NET_WRITE_BUFFERS
|
||||
select MM_IOB
|
||||
---help---
|
||||
Write buffers allows buffering of ongoing TCP/IP packets, providing
|
||||
@@ -105,7 +107,7 @@ config NET_TCP_NWRBCHAINS
|
||||
int "Number of pre-allocated I/O buffer chain heads"
|
||||
default 8
|
||||
---help---
|
||||
These tiny nodes are used as "containers" to support queueing of
|
||||
These tiny nodes are used as "containers" to support queuing of
|
||||
TCP write buffers. This setting will limit the number of TCP write
|
||||
operations that can be "in-flight" at any give time. So a good
|
||||
choice for this value would be the same as the maximum number of
|
||||
|
||||
@@ -44,7 +44,57 @@ config NET_BROADCAST
|
||||
config NET_UDP_READAHEAD
|
||||
bool "Enable UDP/IP read-ahead buffering"
|
||||
default y
|
||||
select NET_READAHEAD
|
||||
select MM_IOB
|
||||
|
||||
config NET_UDP_WRITE_BUFFERS
|
||||
bool "Enable UDP/IP write buffering"
|
||||
default n
|
||||
select NET_WRITE_BUFFERS
|
||||
select MM_IOB
|
||||
depends on EXPERIMENTAL
|
||||
---help---
|
||||
Write buffers allows buffering of ongoing UDP/IP packets, providing
|
||||
for higher performance, streamed output.
|
||||
|
||||
You might want to disable UDP/IP write buffering on a highly memory
|
||||
memory constrained system where there are no performance issues.
|
||||
|
||||
if NET_UDP_WRITE_BUFFERS
|
||||
|
||||
config NET_UDP_NWRBCHAINS
|
||||
int "Number of pre-allocated I/O buffer chain heads"
|
||||
default 8
|
||||
---help---
|
||||
These tiny nodes are used as "containers" to support queuing of
|
||||
UDP write buffers. This setting will limit the number of UDP write
|
||||
operations that can be "in-flight" at any give time. So a good
|
||||
choice for this value would be the same as the maximum number of
|
||||
UDP connections.
|
||||
|
||||
config NET_UDP_WRBUFFER_DEBUG
|
||||
bool "Force write buffer debug"
|
||||
default n
|
||||
depends on DEBUG_FEATURES
|
||||
select IOB_DEBUG
|
||||
---help---
|
||||
This option will force debug output from UDP write buffer logic,
|
||||
even without network debug output. This is not normally something
|
||||
that would want to do but is convenient if you are debugging the
|
||||
write buffer logic and do not want to get overloaded with other
|
||||
network-related debug output.
|
||||
|
||||
config NET_UDP_WRBUFFER_DUMP
|
||||
bool "Force write buffer dump"
|
||||
default n
|
||||
depends on DEBUG_NET || NET_UDP_WRBUFFER_DEBUG
|
||||
select IOB_DEBUG
|
||||
---help---
|
||||
Dump the contents of the write buffers. You do not want to do this
|
||||
unless you really want to analyze the write buffer transfers in
|
||||
detail.
|
||||
|
||||
endif # NET_UDP_WRITE_BUFFERS
|
||||
|
||||
endif # NET_UDP && !NET_UDP_NO_STACK
|
||||
endmenu # UDP Networking
|
||||
|
||||
+17
-2
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# net/udp/Make.defs
|
||||
#
|
||||
# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2014-2015, 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,7 +40,13 @@ ifneq ($(CONFIG_NET_UDP_NO_STACK),y)
|
||||
|
||||
# Socket layer
|
||||
|
||||
NET_CSRCS += udp_psock_send.c udp_psock_sendto.c
|
||||
NET_CSRCS += udp_psock_send.c
|
||||
|
||||
ifeq ($(CONFIG_NET_UDP_WRITE_BUFFERS),y)
|
||||
SOCK_CSRCS += udp_psock_sendto_buffered.c
|
||||
else
|
||||
SOCK_CSRCS += udp_psock_sendto_unbuffered.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_POLL),y)
|
||||
ifeq ($(CONFIG_NET_UDP_READAHEAD),y)
|
||||
@@ -53,6 +59,15 @@ endif
|
||||
NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c
|
||||
NET_CSRCS += udp_callback.c udp_ipselect.c
|
||||
|
||||
# UDP write buffering
|
||||
|
||||
ifeq ($(CONFIG_NET_UDP_WRITE_BUFFERS),y)
|
||||
NET_CSRCS += udp_wrbuffer.c
|
||||
ifeq ($(CONFIG_DEBUG_FEATURES),y)
|
||||
NET_CSRCS += udp_wrbuffer_dump.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Include UDP build support
|
||||
|
||||
DEPPATH += --dep-path udp
|
||||
|
||||
+127
-2
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/udp/udp.h
|
||||
*
|
||||
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2014-2015, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/net/ip.h>
|
||||
|
||||
#ifdef CONFIG_NET_UDP_READAHEAD
|
||||
@@ -66,6 +67,17 @@
|
||||
# define HAVE_UDP_POLL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* UDP write buffer dump macros */
|
||||
|
||||
# ifdef CONFIG_DEBUG_FEATURES
|
||||
# define UDPWB_DUMP(msg,wrb,len,offset) \
|
||||
udp_wrbuffer_dump(msg,wrb,len,offset)
|
||||
# else
|
||||
# define UDPWB_DUMP(msg,wrb,len,offset)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Allocate a new UDP data callback */
|
||||
|
||||
#define udp_callback_alloc(dev,conn) \
|
||||
@@ -102,11 +114,38 @@ struct udp_conn_s
|
||||
struct iob_queue_s readahead; /* Read-ahead buffering */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Write buffering
|
||||
*
|
||||
* write_q - The queue of unsent I/O buffers. The head of this
|
||||
* list may be partially sent. FIFO ordering.
|
||||
*/
|
||||
|
||||
sq_queue_t write_q; /* Write buffering for UDP packets */
|
||||
FAR struct net_driver_s *dev; /* Last device */
|
||||
#endif
|
||||
|
||||
/* Defines the list of UDP callbacks */
|
||||
|
||||
FAR struct devif_callback_s *list;
|
||||
};
|
||||
|
||||
/* This structure supports UDP write buffering. It is simply a container
|
||||
* for a IOB list and associated destination address.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
struct udp_wrbuffer_s
|
||||
{
|
||||
sq_entry_t wb_node; /* Supports a singly linked list */
|
||||
union ip_addr_u wb_dest; /* Destination address */
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
systime_t wb_start; /* Start time for timeout calculation */
|
||||
#endif
|
||||
struct iob_s *wb_iob; /* Head of the I/O buffer chain */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@@ -291,6 +330,92 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn);
|
||||
|
||||
void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the list of free write buffers
|
||||
*
|
||||
* Assumptions:
|
||||
* Called once early initialization.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
void udp_wrbuffer_initialize(void);
|
||||
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate a UDP write buffer by taking a pre-allocated buffer from
|
||||
* the free list. This function is called from UDP logic when a buffer
|
||||
* of UDP data is about to sent
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from user logic with the network locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
struct udp_wrbuffer_s;
|
||||
|
||||
FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void);
|
||||
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_release
|
||||
*
|
||||
* Description:
|
||||
* Release a UDP 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 network stack logic with the network stack locked
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb);
|
||||
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_test
|
||||
*
|
||||
* Description:
|
||||
* Check if there is room in the write buffer. Does not reserve any space.
|
||||
*
|
||||
* Assumptions:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
int udp_wrbuffer_test(void);
|
||||
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_dump
|
||||
*
|
||||
* Description:
|
||||
* Dump the contents of a write buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
void udp_wrbuffer_dump(FAR const char *msg, FAR struct udp_wrbuffer_s *wrb,
|
||||
unsigned int len, unsigned int offset);
|
||||
#else
|
||||
# define udp_wrbuffer_dump(msg,wrb)
|
||||
#endif
|
||||
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_ipv4_input
|
||||
*
|
||||
@@ -495,7 +620,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds);
|
||||
* Teardown monitoring of events on an UDP/IP socket
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock - The TCP/IP socket of interest
|
||||
* psock - The UDP/IP socket of interest
|
||||
* fds - The structure describing the events to be monitored, OR NULL if
|
||||
* this is a request to stop monitoring events.
|
||||
*
|
||||
|
||||
+20
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* net/udp/udp_conn.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011-2012, 2016, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Large parts of this file were leveraged from uIP logic:
|
||||
@@ -485,6 +486,11 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
|
||||
conn->lport = 0;
|
||||
conn->ttl = IP_TTL;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Initialize the write buffer lists */
|
||||
|
||||
sq_init(&conn->write_q);
|
||||
#endif
|
||||
/* Enqueue the connection into the active list */
|
||||
|
||||
dq_addlast(&conn->node, &g_active_udp_connections);
|
||||
@@ -505,6 +511,10 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
|
||||
|
||||
void udp_free(FAR struct udp_conn_s *conn)
|
||||
{
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
FAR struct udp_wrbuffer_s *wrbuffer;
|
||||
#endif
|
||||
|
||||
/* The free list is protected by a semaphore (that behaves like a mutex). */
|
||||
|
||||
DEBUGASSERT(conn->crefs == 0);
|
||||
@@ -522,6 +532,15 @@ void udp_free(FAR struct udp_conn_s *conn)
|
||||
iob_free_queue(&conn->readahead);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* Release any write buffers attached to the connection */
|
||||
|
||||
while ((wrbuffer = (struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q)) != NULL)
|
||||
{
|
||||
udp_wrbuffer_release(wrbuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free the connection */
|
||||
|
||||
dq_addlast(&conn->node, &g_free_udp_connections);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* net/udp/udp_psock_sendto.c
|
||||
* net/udp/udp_psock_sendto_unbuffered.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011-2016, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -94,7 +95,7 @@ struct sendto_s
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: send_timeout
|
||||
* Name: sendto_timeout
|
||||
*
|
||||
* Description:
|
||||
* Check for send timeout.
|
||||
@@ -111,7 +112,7 @@ struct sendto_s
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
static inline int send_timeout(FAR struct sendto_s *pstate)
|
||||
static inline int sendto_timeout(FAR struct sendto_s *pstate)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
|
||||
@@ -235,7 +236,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
if (send_timeout(pstate))
|
||||
if (sendto_timeout(pstate))
|
||||
{
|
||||
/* Yes.. report the timeout */
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/****************************************************************************
|
||||
* net/udp/udp_wrbuffer.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/net/netconfig.h>
|
||||
#if defined(CONFIG_NET) && defined(CONFIG_NET_UDP) && defined(CONFIG_NET_UDP_WRITE_BUFFERS)
|
||||
|
||||
#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_NET_UDP_WRBUFFER_DEBUG)
|
||||
/* Force debug output (from this file only) */
|
||||
|
||||
# undef CONFIG_DEBUG_NET
|
||||
# define CONFIG_DEBUG_NET 1
|
||||
#endif
|
||||
|
||||
#include <queue.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/mm/iob.h>
|
||||
|
||||
#include "udp/udp.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 udp_wrbuffer_s buffers[CONFIG_NET_UDP_NWRBCHAINS];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the state of the global write buffer resource */
|
||||
|
||||
static struct wrbuffer_s g_wrbuffer;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the list of free write buffers
|
||||
*
|
||||
* Assumptions:
|
||||
* Called once early initialization.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_wrbuffer_initialize(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
sq_init(&g_wrbuffer.freebuffers);
|
||||
|
||||
for (i = 0; i < CONFIG_NET_UDP_NWRBCHAINS; i++)
|
||||
{
|
||||
sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers);
|
||||
}
|
||||
|
||||
nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_UDP_NWRBCHAINS);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate a UDP write buffer by taking a pre-allocated buffer from
|
||||
* the free list. This function is called from UDP logic when a buffer
|
||||
* of UDP data is about to sent
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from user logic with the network locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void)
|
||||
{
|
||||
FAR struct udp_wrbuffer_s *wrb;
|
||||
|
||||
/* We need to allocate two things: (1) A write buffer structure and (2)
|
||||
* at least one I/O buffer to start the chain.
|
||||
*
|
||||
* Allocate the write buffer structure first then the IOBG. In order to
|
||||
* avoid deadlocks, we will need to free the IOB first, then the write
|
||||
* buffer
|
||||
*/
|
||||
|
||||
DEBUGVERIFY(net_lockedwait(&g_wrbuffer.sem)); /* TODO: Handle EINTR. */
|
||||
|
||||
/* Now, we are guaranteed to have a write buffer structure reserved
|
||||
* for us in the free list.
|
||||
*/
|
||||
|
||||
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers);
|
||||
DEBUGASSERT(wrb);
|
||||
memset(wrb, 0, sizeof(struct udp_wrbuffer_s));
|
||||
|
||||
/* Now get the first I/O buffer for the write buffer structure */
|
||||
|
||||
wrb->wb_iob = iob_alloc(false);
|
||||
if (!wrb->wb_iob)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate I/O buffer\n");
|
||||
udp_wrbuffer_release(wrb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wrb;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_release
|
||||
*
|
||||
* Description:
|
||||
* Release a UDP 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:
|
||||
* This function must be called with the network locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb)
|
||||
{
|
||||
DEBUGASSERT(wrb && wrb->wb_iob);
|
||||
|
||||
/* To avoid deadlocks, we must following this ordering: Release the I/O
|
||||
* buffer chain first, then the write buffer structure.
|
||||
*/
|
||||
|
||||
iob_free_chain(wrb->wb_iob);
|
||||
|
||||
/* Then free the write buffer structure */
|
||||
|
||||
sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers);
|
||||
nxsem_post(&g_wrbuffer.sem);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_test
|
||||
*
|
||||
* Description:
|
||||
* Check if there is room in the write buffer. Does not reserve any space.
|
||||
*
|
||||
* Assumptions:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int udp_wrbuffer_test(void)
|
||||
{
|
||||
int val = 0;
|
||||
nxsem_getvalue(&g_wrbuffer.sem, &val);
|
||||
return val > 0 ? OK : ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_UDP && CONFIG_NET_UDP_WRITE_BUFFERS */
|
||||
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
* net/udp/udp_wrbuffer_dump.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 <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mm/iob.h>
|
||||
|
||||
#include "udp/udp.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_wrbuffer_dump
|
||||
*
|
||||
* Description:
|
||||
* Dump the contents of a write buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_wrbuffer_dump(FAR const char *msg, FAR struct udp_wrbuffer_s *wrb,
|
||||
unsigned int len, unsigned int offset)
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s: wrb=%p pktlen=%d\n", msg, wrb, wrb->wb_iob->io_pktlen);
|
||||
iob_dump("I/O Buffer Chain", wrb->wb_iob, len, offset);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FEATURES */
|
||||
Reference in New Issue
Block a user