net/TCP: Extend the TCP notification logic logic so that it will also report loss of connection events.

This commit is contained in:
Gregory Nutt 2018-09-09 17:32:10 -06:00
parent 9d3148406c
commit 09d5d05b95
6 changed files with 190 additions and 42 deletions

View File

@ -47,6 +47,17 @@ config NET_MAX_LISTENPORTS
---help---
Maximum number of listening TCP/IP ports (all tasks). Default: 20
config TCP_NOTIFIER
bool "Support TCP notifications"
default n
depends on SCHED_HPWORK
---help---
Enable building of TCP notifier logic that will execute a worker
function on the high priority work queue when read-ahead data
is available or when a TCP connection is lost. This is is a general
purpose notifier, but was developed specifically to support poll()
logic where the poll must wait for these events.
config NET_TCP_READAHEAD
bool "Enable TCP/IP read-ahead buffering"
default y
@ -66,17 +77,6 @@ config NET_TCP_READAHEAD
These settings are critical to the reasonable operation of read-
ahead buffering.
config TCP_READAHEAD_NOTIFIER
bool "Support TCP read-ahead notifications"
default n
depends on NET_TCP_READAHEAD && SCHED_HPWORK
---help---
Enable building of TCP read-ahead notifier logic that will execute a
worker function on the high priority work queue when read-ahead data
is available. This is is a general purpose notifier, but was
developed specifically to support poll() logic where the poll must
wait for read-ahead data to become available.
config NET_TCP_WRITE_BUFFERS
bool "Enable TCP/IP write buffering"
default n

View File

@ -55,7 +55,7 @@ endif
ifneq ($(CONFIG_DISABLE_POLL),y)
ifeq ($(CONFIG_NET_TCP_READAHEAD),y)
SOCK_CSRCS += tcp_netpoll.c
ifeq ($(CONFIG_TCP_READAHEAD_NOTIFIER),y)
ifeq ($(CONFIG_TCP_NOTIFIER),y)
SOCK_CSRCS += tcp_notifier.c
endif
endif

View File

@ -49,7 +49,7 @@
#include <nuttx/mm/iob.h>
#include <nuttx/net/ip.h>
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
#ifdef CONFIG_TCP_NOTIFIER
# include <nuttx/wqueue.h>
#endif
@ -1547,7 +1547,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
#endif
/****************************************************************************
* Name: tcp_notifier_setup
* Name: tcp_readahead_notifier_setup
*
* Description:
* Set up to perform a callback to the worker function when an TCP data
@ -1556,7 +1556,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
*
* Input Parameters:
* worker - The worker function to execute on the high priority work
* queue when data is available in the TCP readahead buffer.
* queue when data is available in the TCP read-ahead buffer.
* conn - The TCP connection where read-ahead data is needed.
* arg - A user-defined argument that will be available to the worker
* function when it runs.
@ -1573,9 +1573,42 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
*
****************************************************************************/
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
int tcp_notifier_setup(worker_t worker, FAR struct tcp_conn_s *conn,
FAR void *arg);
#ifdef CONFIG_TCP_NOTIFIER
int tcp_readahead_notifier_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg);
#endif
/****************************************************************************
* Name: tcp_readahead_disconnect_setup
*
* Description:
* Set up to perform a callback to the worker function if the TCP
* connection is lost.
*
* Input Parameters:
* worker - The worker function to execute on the high priority work
* queue when data is available in the TCP read-ahead buffer.
* conn - The TCP connection where read-ahead data is needed.
* arg - A user-defined argument that will be available to the worker
* function when it runs.
*
* Returned Value:
* > 0 - The signal notification is in place. The returned value is a
* key that may be used later in a call to
* tcp_notifier_teardown().
* == 0 - There is already buffered read-ahead data. No signal
* notification will be provided.
* < 0 - An unexpected error occurred and no signal will be sent. The
* returned value is a negated errno value that indicates the
* nature of the failure.
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
int tcp_readahead_disconnect_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg);
#endif
/****************************************************************************
@ -1583,13 +1616,13 @@ int tcp_notifier_setup(worker_t worker, FAR struct tcp_conn_s *conn,
*
* Description:
* Eliminate a TCP read-ahead notification previously setup by
* tcp_notifier_setup(). This function should only be called if the
* notification should be aborted prior to the notification. The
* tcp_readahead_notifier_setup(). This function should only be called
* if the notification should be aborted prior to the notification. The
* notification will automatically be torn down after the signal is sent.
*
* Input Parameters:
* key - The key value returned from a previous call to
* tcp_notifier_setup().
* tcp_readahead_notifier_setup().
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
@ -1597,12 +1630,12 @@ int tcp_notifier_setup(worker_t worker, FAR struct tcp_conn_s *conn,
*
****************************************************************************/
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
#ifdef CONFIG_TCP_NOTIFIER
int tcp_notifier_teardown(int key);
#endif
/****************************************************************************
* Name: tcp_notifier_signal
* Name: tcp_readahead_signal
*
* Description:
* Read-ahead data has been buffered. Signal all threads waiting for
@ -1611,7 +1644,8 @@ int tcp_notifier_teardown(int key);
* When read-ahead data becomes available, *all* of the workers waiting
* for read-ahead data will be executed. If there are multiple workers
* waiting for read-ahead data then only the first to execute will get the
* data. Others will need to call tcp_notifier_setup() once again.
* data. Others will need to call tcp_readahead_notifier_setup() once
* again.
*
* Input Parameters:
* conn - The TCP connection where read-ahead data was just buffered.
@ -1621,8 +1655,27 @@ int tcp_notifier_teardown(int key);
*
****************************************************************************/
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
void tcp_notifier_signal(FAR struct tcp_conn_s *conn);
#ifdef CONFIG_TCP_NOTIFIER
void tcp_readahead_signal(FAR struct tcp_conn_s *conn);
#endif
/****************************************************************************
* Name: tcp_disconnect_signal
*
* Description:
* The TCP connection has been lost. Signal all threads monitoring TCP
* state events.
*
* Input Parameters:
* conn - The TCP connection where read-ahead data was just buffered.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
void tcp_disconnect_signal(FAR struct tcp_conn_s *conn);
#endif
#undef EXTERN

View File

@ -145,6 +145,10 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint16_t tcp_callback(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn, uint16_t flags)
{
#ifdef CONFIG_TCP_NOTIFIER
uint16_t orig = flags;
#endif
/* Preserve the TCP_ACKDATA, TCP_CLOSE, and TCP_ABORT in the response.
* These is needed by the network to handle responses and buffer state. The
* TCP_NEWDATA indication will trigger the ACK response, but must be
@ -199,6 +203,15 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
flags = devif_conn_event(dev, conn, flags, conn->connevents);
}
#ifdef CONFIG_TCP_NOTIFIER
/* Provide notification(s) if the TCP connection has been lost. */
if ((orig & TCP_DISCONN_EVENTS) != 0)
{
tcp_disconnect_signal(conn);
}
#endif
return flags;
}
@ -273,12 +286,12 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
return 0;
}
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
/* Provided notification(s) that additional TCP read-ahead data is
#ifdef CONFIG_TCP_NOTIFIER
/* Provide notification(s) that additional TCP read-ahead data is
* available.
*/
tcp_notifier_signal(conn);
tcp_readahead_signal(conn);
#endif
ninfo("Buffered %d bytes\n", buflen);

View File

@ -44,17 +44,18 @@
#include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/tcp.h>
#include "tcp/tcp.h"
#ifdef CONFIG_TCP_READAHEAD_NOTIFIER
#ifdef CONFIG_TCP_NOTIFIER
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: tcp_notifier_setup
* Name: tcp_readahead_notifier_setup
*
* Description:
* Set up to perform a callback to the worker function when an TCP data
@ -63,7 +64,7 @@
*
* Input Parameters:
* worker - The worker function to execute on the high priority work
* queue when data is available in the TCP readahead buffer.
* queue when data is available in the TCP read-ahead buffer.
* conn - The TCP connection where read-ahead data is needed.
* arg - A user-defined argument that will be available to the worker
* function when it runs.
@ -80,8 +81,9 @@
*
****************************************************************************/
int tcp_notifier_setup(worker_t worker, FAR struct tcp_conn_s *conn,
FAR void *arg)
int tcp_readahead_notifier_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg)
{
struct work_notifier_s info;
@ -106,18 +108,69 @@ int tcp_notifier_setup(worker_t worker, FAR struct tcp_conn_s *conn,
return work_notifier_setup(&info);
}
/****************************************************************************
* Name: tcp_readahead_disconnect_setup
*
* Description:
* Set up to perform a callback to the worker function if the TCP
* connection is lost.
*
* Input Parameters:
* worker - The worker function to execute on the high priority work
* queue when data is available in the TCP read-ahead buffer.
* conn - The TCP connection where read-ahead data is needed.
* arg - A user-defined argument that will be available to the worker
* function when it runs.
*
* Returned Value:
* > 0 - The signal notification is in place. The returned value is a
* key that may be used later in a call to
* tcp_notifier_teardown().
* == 0 - There is already buffered read-ahead data. No signal
* notification will be provided.
* < 0 - An unexpected error occurred and no signal will be sent. The
* returned value is a negated errno value that indicates the
* nature of the failure.
*
****************************************************************************/
int tcp_readahead_disconnect_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg)
{
struct work_notifier_s info;
DEBUGASSERT(worker != NULL);
/* If connection has not been established, then return 0. */
if (conn->tcpstateflags != TCP_ESTABLISHED)
{
return 0;
}
/* Otherwise, this is just a simple wrapper around work_notifer_setup(). */
info.evtype = WORK_TCP_DISCONNECT;
info.qualifier = conn;
info.arg = arg;
info.worker = worker;
return work_notifier_setup(&info);
}
/****************************************************************************
* Name: tcp_notifier_teardown
*
* Description:
* Eliminate a TCP read-ahead notification previously setup by
* tcp_notifier_setup(). This function should only be called if the
* notification should be aborted prior to the notification. The
* tcp_readahead_notifier_setup(). This function should only be called
* if the notification should be aborted prior to the notification. The
* notification will automatically be torn down after the signal is sent.
*
* Input Parameters:
* key - The key value returned from a previous call to
* tcp_notifier_setup().
* tcp_readahead_notifier_setup().
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
@ -133,7 +186,7 @@ int tcp_notifier_teardown(int key)
}
/****************************************************************************
* Name: tcp_notifier_signal
* Name: tcp_readahead_signal
*
* Description:
* Read-ahead data has been buffered. Signal all threads waiting for
@ -142,7 +195,8 @@ int tcp_notifier_teardown(int key)
* When read-ahead data becomes available, *all* of the workers waiting
* for read-ahead data will be executed. If there are multiple workers
* waiting for read-ahead data then only the first to execute will get the
* data. Others will need to call tcp_notifier_setup() once again.
* data. Others will need to call tcp_readahead_notifier_setup() once
* again.
*
* Input Parameters:
* conn - The TCP connection where read-ahead data was just buffered.
@ -152,11 +206,33 @@ int tcp_notifier_teardown(int key)
*
****************************************************************************/
void tcp_notifier_signal(FAR struct tcp_conn_s *conn)
void tcp_readahead_signal(FAR struct tcp_conn_s *conn)
{
/* This is just a simple wrapper around work_notifier_signal(). */
return work_notifier_signal(WORK_TCP_READAHEAD, conn);
}
#endif /* CONFIG_TCP_READAHEAD_NOTIFIER */
/****************************************************************************
* Name: tcp_disconnect_signal
*
* Description:
* The TCP connection has been lost. Signal all threads monitoring TCP
* state events.
*
* Input Parameters:
* conn - The TCP connection where read-ahead data was just buffered.
*
* Returned Value:
* None.
*
****************************************************************************/
void tcp_disconnect_signal(FAR struct tcp_conn_s *conn)
{
/* This is just a simple wrapper around work_notifier_signal(). */
return work_notifier_signal(WORK_TCP_DISCONNECT, conn);
}
#endif /* CONFIG_TCP_NOTIFIER */

View File

@ -314,7 +314,13 @@ int work_notifier_setup(FAR struct work_notifier_s *info)
key = work_notifier_key();
/* Add the notification to the head of the pending list */
/* Add the notification to the head of the pending list
*
* REVISIT: Work will be processed in LIFO order. Perhaps
* we should should consider saving the notification is the
* order of the caller's execution priority so that the
* notifications executed in a saner order?
*/
notifier->flink = g_notifier_pending;
notifier->alloc = alloc;