net/udp: Resolves final design issues with UDP write buffering. 100% code complete but also 100% untested.
This commit is contained in:
parent
fa3ad46897
commit
2d4fa19a54
@ -105,9 +105,6 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void sendto_netdev_down(FAR struct socket *psock,
|
|
||||||
FAR struct udp_conn_s *conn);
|
|
||||||
|
|
||||||
#ifdef NEED_IPDOMAIN_SUPPORT
|
#ifdef NEED_IPDOMAIN_SUPPORT
|
||||||
static inline void sendto_ipselect(FAR struct net_driver_s *dev,
|
static inline void sendto_ipselect(FAR struct net_driver_s *dev,
|
||||||
FAR struct udp_conn_s *conn);
|
FAR struct udp_conn_s *conn);
|
||||||
@ -135,47 +132,64 @@ static inline void sendto_txnotify(FAR struct socket *psock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sendto_netdev_down
|
* Name: sendto_writebuffer_release
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* The network device is down. Free all write buffers.
|
* Release the write buffer at the head of the write buffer queue.
|
||||||
* REVISIT: Should only free write buffers associated with the device
|
|
||||||
* that went down.
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* psock The socket structure
|
* dev - The structure of the network driver that caused the event
|
||||||
* conn The connection structure associated with the socket
|
* psock - Socket state structure
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The network is locked
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void sendto_netdev_down(FAR struct socket *psock,
|
static void sendto_writebuffer_release(FAR struct socket *psock,
|
||||||
FAR struct udp_conn_s *conn)
|
FAR struct udp_conn_s *conn)
|
||||||
{
|
{
|
||||||
FAR sq_entry_t *entry;
|
FAR struct udp_wrbuffer_s *wrb;
|
||||||
FAR sq_entry_t *next;
|
int ret = OK;
|
||||||
|
|
||||||
/* Do not allow any further callbacks */
|
do
|
||||||
|
|
||||||
if (psock->s_sndcb != NULL)
|
|
||||||
{
|
{
|
||||||
psock->s_sndcb->flags = 0;
|
/* Check if the write queue became empty */
|
||||||
psock->s_sndcb->event = NULL;
|
|
||||||
|
if (sq_empty(&conn->write_q))
|
||||||
|
{
|
||||||
|
/* Yes.. stifle any further callbacks until more write data is
|
||||||
|
* enqueued.
|
||||||
|
*/
|
||||||
|
|
||||||
|
psock->s_sndcb->flags = 0;
|
||||||
|
psock->s_sndcb->priv = NULL;
|
||||||
|
psock->s_sndcb->event = NULL;
|
||||||
|
wrb = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove the write buffer from the head of the write buffer queue
|
||||||
|
* and release it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
||||||
|
DEBUGASSERT(wrb != NULL);
|
||||||
|
|
||||||
|
udp_wrbuffer_release(wrb);
|
||||||
|
|
||||||
|
/* Set up for the next packet transfer by setting the connection
|
||||||
|
* address to the address of the next packet now at the header of
|
||||||
|
* the write buffer queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = sendto_next_transfer(psock, conn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while (wrb != NULL && ret < 0);
|
||||||
/* Free all queued write buffers */
|
|
||||||
|
|
||||||
for (entry = sq_peek(&conn->write_q); entry; entry = next)
|
|
||||||
{
|
|
||||||
next = sq_next(entry);
|
|
||||||
udp_wrbuffer_release((FAR struct udp_wrbuffer_s *)entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset write buffering variables */
|
|
||||||
|
|
||||||
sq_init(&conn->write_q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -254,7 +268,7 @@ static inline void sendto_ipselect(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
#ifdef CONFIG_NET_ETHERNET
|
#ifdef CONFIG_NET_ETHERNET
|
||||||
static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn,
|
static inline bool sendto_addrcheck(FAR struct udp_conn_s *conn,
|
||||||
FAR struct net_driver_s *dev)
|
FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
/* REVISIT: Could the MAC address not also be in a routing table? */
|
/* REVISIT: Could the MAC address not also be in a routing table? */
|
||||||
|
|
||||||
@ -458,7 +472,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
{
|
{
|
||||||
FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)pvconn;
|
FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)pvconn;
|
||||||
FAR struct socket *psock = (FAR struct socket *)pvpriv;
|
FAR struct socket *psock = (FAR struct socket *)pvpriv;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ninfo("flags: %04x\n", flags);
|
ninfo("flags: %04x\n", flags);
|
||||||
|
|
||||||
@ -468,9 +481,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
{
|
{
|
||||||
ninfo("Device down: %04x\n", flags);
|
ninfo("Device down: %04x\n", flags);
|
||||||
|
|
||||||
/* Free write buffers and terminate polling */
|
/* Free the write buffer at the head of the queue and attempt to setup
|
||||||
|
* the next transfer.
|
||||||
|
*/
|
||||||
|
|
||||||
sendto_netdev_down(psock, conn);
|
sendto_writebuffer_release(psock, conn);
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +510,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
if (sendto_addrcheck(conn, dev))
|
if (sendto_addrcheck(conn, dev))
|
||||||
{
|
{
|
||||||
FAR struct udp_wrbuffer_s *wrb;
|
FAR struct udp_wrbuffer_s *wrb;
|
||||||
FAR struct udp_wrbuffer_s *tmp;
|
|
||||||
size_t sndlen;
|
size_t sndlen;
|
||||||
|
|
||||||
/* Peek at the head of the write queue (but don't remove anything
|
/* Peek at the head of the write queue (but don't remove anything
|
||||||
@ -530,41 +544,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
devif_iob_send(dev, wrb->wb_iob, sndlen, 0);
|
devif_iob_send(dev, wrb->wb_iob, sndlen, 0);
|
||||||
|
|
||||||
/* Remove and free the write buffer from the head of the write
|
/* Free the write buffer at the head of the queue and attempt to
|
||||||
* buffer queue.
|
* setup the next transfer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
do
|
sendto_writebuffer_release(psock, conn);
|
||||||
{
|
|
||||||
tmp = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
|
||||||
DEBUGASSERT(tmp == wrb);
|
|
||||||
|
|
||||||
udp_wrbuffer_release(tmp);
|
|
||||||
|
|
||||||
/* Check if the write queue became empty */
|
|
||||||
|
|
||||||
if (sq_empty(&conn->write_q))
|
|
||||||
{
|
|
||||||
/* Yes.. stifle any further callbacks until more write
|
|
||||||
* data is enqueued.
|
|
||||||
*/
|
|
||||||
|
|
||||||
psock->s_sndcb->flags = 0;
|
|
||||||
psock->s_sndcb->priv = NULL;
|
|
||||||
psock->s_sndcb->event = NULL;
|
|
||||||
ret = OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set up for the next packet transfer by setting the
|
|
||||||
* connection address to the address of the next packet
|
|
||||||
* now at the header of of the write buffer queue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = sendto_next_transfer(psock, conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (ret < 0);
|
|
||||||
|
|
||||||
/* Only one data can be sent by low level driver at once,
|
/* Only one data can be sent by low level driver at once,
|
||||||
* tell the caller stop polling the other connections.
|
* tell the caller stop polling the other connections.
|
||||||
@ -579,28 +563,11 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
else if (sendto_timeout(psock, conn))
|
else if (sendto_timeout(psock, conn))
|
||||||
{
|
{
|
||||||
FAR struct udp_wrbuffer_s *wrb;
|
/* Free the write buffer at the head of the queue and attempt to setup
|
||||||
|
* the next transfer.
|
||||||
|
*/
|
||||||
|
|
||||||
do
|
sendto_writebuffer_release(psock, conn);
|
||||||
{
|
|
||||||
/* Remove and free the write buffer from the head of the write
|
|
||||||
* buffer queue. Here we know that the write queue is not empty
|
|
||||||
* because the entry at the head of the queue just timed out!
|
|
||||||
*/
|
|
||||||
|
|
||||||
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
|
||||||
DEBUGASSERT(wrb != NULL);
|
|
||||||
|
|
||||||
udp_wrbuffer_release(wrb);
|
|
||||||
|
|
||||||
/* Set up for the next packet transfer by setting the connection
|
|
||||||
* address to the address of the next packet now at the header of the
|
|
||||||
* write buffer queue.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = sendto_next_transfer(psock, conn);
|
|
||||||
}
|
|
||||||
while (ret < 0);
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_SOCKOPTS */
|
#endif /* CONFIG_NET_SOCKOPTS */
|
||||||
|
|
||||||
@ -799,9 +766,8 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
|||||||
ret = sendto_next_transfer(psock, conn);
|
ret = sendto_next_transfer(psock, conn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* REVISIT: An error here is not recoverable */
|
(void)sq_remlast(&conn->write_q);
|
||||||
|
goto errout_with_wrb;
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify the device driver of the availability of TX data */
|
/* Notify the device driver of the availability of TX data */
|
||||||
|
Loading…
Reference in New Issue
Block a user