net/udp: UDP write buffering is basically functional but needs a lot more verification.

This commit is contained in:
Gregory Nutt 2018-01-23 07:32:17 -06:00
parent 289e4dde06
commit f2017bded8
3 changed files with 24 additions and 61 deletions

View File

@ -52,7 +52,6 @@ config NET_UDP_WRITE_BUFFERS
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.

View File

@ -43,6 +43,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <queue.h>
#include <nuttx/clock.h>
@ -137,12 +138,12 @@ struct udp_conn_s
#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 */
sq_entry_t wb_node; /* Supports a singly linked list */
struct sockaddr_storage wb_dest; /* Destination address */
#ifdef CONFIG_NET_SOCKOPTS
systime_t wb_start; /* Start time for timeout calculation */
systime_t wb_start; /* Start time for timeout calculation */
#endif
struct iob_s *wb_iob; /* Head of the I/O buffer chain */
struct iob_s *wb_iob; /* Head of the I/O buffer chain */
};
#endif

View File

@ -124,8 +124,6 @@ static int sendto_next_transfer(FAR struct socket *psock,
static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags);
static inline void sendto_txnotify(FAR struct socket *psock,
FAR struct udp_conn_s *conn);
/****************************************************************************
* Private Functions
@ -378,9 +376,13 @@ static int sendto_next_transfer(FAR struct socket *psock,
*/
wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q);
DEBUGASSERT(wrb != NULL);
if (wrb == NULL)
{
ninfo("Write buffer queue is empty\n");
return -ENOENT;
}
ret = udp_connect(conn, (FAR const struct sockaddr *)wrb->wb_iob->io_data);
ret = udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest);
if (ret < 0)
{
nerr("ERROR: udp_connect failed: %d\n", ret);
@ -443,6 +445,10 @@ static int sendto_next_transfer(FAR struct socket *psock,
psock->s_sndcb->flags = (UDP_POLL | NETDEV_DOWN);
psock->s_sndcb->priv = (FAR void *)psock;
psock->s_sndcb->event = sendto_eventhandler;
/* Notify the device driver of the availability of TX data */
netdev_txnotify_dev(dev);
return OK;
}
@ -499,7 +505,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
* buffers to send.
*/
if (dev->d_sndlen <= 0 && (flags & UDP_NEWDATA) != 0 &&
if (dev->d_sndlen <= 0 && (flags & UDP_NEWDATA) == 0 &&
(flags & UDP_POLL) != 0 && !sq_empty(&conn->write_q))
{
/* Check if the destination IP address is in the ARP or Neighbor
@ -576,53 +582,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
return flags;
}
/****************************************************************************
* Name: sendto_txnotify
*
* Description:
* Notify the appropriate device driver that we are have data ready to
* be send (UDP)
*
* Parameters:
* psock - Socket state structure
* conn - The UDP connection structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void sendto_txnotify(FAR struct socket *psock,
FAR struct udp_conn_s *conn)
{
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
/* If both IPv4 and IPv6 support are enabled, then we will need to select
* the device driver using the appropriate IP domain.
*/
if (psock->s_domain == PF_INET)
#endif
{
/* Notify the device driver that send data is available */
netdev_ipv4_txnotify(conn->u.ipv4.laddr, conn->u.ipv4.raddr);
}
#endif /* CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */
{
/* Notify the device driver that send data is available */
DEBUGASSERT(psock->s_domain == PF_INET6);
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_IPv6 */
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -750,7 +709,14 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
UDP_WBDUMP("I/O buffer chain", wrb, wrb->wb_iob->io_pktlen, 0);
/* sendto_eventhandler() will send data in FIFO order from the
* conn->write_q
* conn->write_q.
*
* REVISIT: Why FIFO order? Because it is easy. In a real world
* environment where there are multiple network devices this might
* be inefficient because we could be sending data to different
* device out-of-queued-order to optimize performance. Sending
* data to different networks from a single UDP socket is probably
* not a very common use case, however.
*/
sq_addlast(&wrb->wb_node, &conn->write_q);
@ -770,9 +736,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
goto errout_with_wrb;
}
/* Notify the device driver of the availability of TX data */
sendto_txnotify(psock, conn);
net_unlock();
}