PF_IEEE802154: On input, there may be a list of frames provided, not just one. When closed() and connection is freed, also need to free any frames remaining in the RX queue.

This commit is contained in:
Gregory Nutt 2017-08-21 07:13:34 -06:00
parent 969d7c5814
commit 0eac90f775
2 changed files with 126 additions and 61 deletions

View File

@ -44,6 +44,7 @@
#include <arch/irq.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
@ -150,6 +151,9 @@ FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void)
void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn)
{
FAR struct ieee802154_container_s *container;
FAR struct ieee802154_container_s *next;
/* The free list is only accessed from user, non-interrupt level and
* is protected by a semaphore (that behaves like a mutex).
*/
@ -161,6 +165,29 @@ void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn)
net_lock();
dq_rem(&conn->node, &g_active_ieee802154_connections);
/* Check if there any any frames attached to the container */
for (container = conn->rxhead;
container != NULL;
container = container->ic_flink)
{
/* Remove the frame from the list */
next = container->ic_flink;
container->ic_flink = NULL;
/* Free the contained frame data (should be only one in chain) */
if (container->ic_iob)
{
iob_free(container->ic_iob);
}
/* And free the container itself */
ieee802154_container_free(container);
}
/* Free the connection */
dq_addlast(&conn->node, &g_free_ieee802154_connections);

View File

@ -51,6 +51,77 @@
#ifdef CONFIG_NET_IEEE802154
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ieee802154_queue_frame
*
* Description:
* Add one frame to the connection's RX queue.
*
* Parameters:
* conn - The socket connection structure.
* framel - A single frame to add to the RX queue.
* meta - Meta data characterizing the received frane.
*
* Return:
* Zero (OK) is returned on success; A negated errno value is returned on
* any failure.
*
****************************************************************************/
int ieee802154_queue_frame(FAR struct ieee802154_conn_s *conn,
FAR struct iob_s *frame,
FAR struct ieee802154_data_ind_s *meta)
{
FAR struct ieee802154_container_s *container;
/* Allocate a container for the frame */
container = ieee802154_container_allocate();
if (container == NULL)
{
nerr("ERROR: Failed to allocate a container\n");
return -ENOMEM;
}
/* Initialize the container */
memset(&container->ic_src, 0, sizeof(struct ieee802154_saddr_s));
DEBUGASSERT(meta->src.mode != IEEE802154_ADDRMODE_NONE);
container->ic_src.s_mode = meta->src.mode;
IEEE802154_PANIDCOPY(container->ic_src.s_panid, meta->src.panid);
if (meta->src.mode == IEEE802154_ADDRMODE_SHORT)
{
IEEE802154_SADDRCOPY(container->ic_src.s_saddr, meta->src.saddr);
}
else if (meta->src.mode == IEEE802154_ADDRMODE_EXTENDED)
{
IEEE802154_EADDRCOPY(container->ic_src.s_eaddr, meta->src.eaddr);
}
DEBUGASSERT(frame != NULL);
container->ic_iob = frame;
/* Add the container to the tail of the list of incoming frames */
container->ic_flink = NULL;
if (conn->rxtail == NULL)
{
conn->rxhead = container;
}
else
{
conn->rxtail->ic_flink = container;
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -101,8 +172,9 @@ int ieee802154_input(FAR struct radio_driver_s *radio,
FAR struct iob_s *framelist,
FAR struct ieee802154_data_ind_s *meta)
{
FAR struct ieee802154_container_s *container;
FAR struct ieee802154_conn_s *conn;
FAR struct iob_s *frame;
FAR struct iob_s *next;
int ret = OK;
/* Check if there is a connection that will accept this packet */
@ -110,8 +182,6 @@ int ieee802154_input(FAR struct radio_driver_s *radio,
conn = ieee802154_conn_active(meta);
if (conn != NULL)
{
uint16_t flags;
/* Setup for the application callback (NOTE: These should not be
* used by PF_IEEE802154 sockets).
*/
@ -120,72 +190,40 @@ int ieee802154_input(FAR struct radio_driver_s *radio,
radio->r_dev.d_len = 0;
radio->r_dev.d_sndlen = 0;
/* Allocate a container for the IOB */
container = ieee802154_container_allocate();
if (container == NULL)
{
nerr("ERROR: Failed to allocate a container\n");
return -ENOMEM;
}
/* Initialize the container */
memset(&container->ic_src, 0, sizeof(struct ieee802154_saddr_s));
DEBUGASSERT(meta->src.mode != IEEE802154_ADDRMODE_NONE);
container->ic_src.s_mode = meta->src.mode;
IEEE802154_PANIDCOPY(container->ic_src.s_panid, meta->src.panid);
if (meta->src.mode == IEEE802154_ADDRMODE_SHORT)
{
IEEE802154_SADDRCOPY(container->ic_src.s_saddr, meta->src.saddr);
}
else if (meta->src.mode == IEEE802154_ADDRMODE_EXTENDED)
{
IEEE802154_EADDRCOPY(container->ic_src.s_eaddr, meta->src.eaddr);
}
DEBUGASSERT(framelist != NULL);
container->ic_iob = framelist;
/* Add the container to the tail of the list of incoming frames */
container->ic_flink = NULL;
if (conn->rxtail == NULL)
{
conn->rxhead = container;
}
else
{
conn->rxtail->ic_flink = container;
}
conn->rxtail = container;
/* Perform the application callback */
flags = ieee802154_callback(radio, conn, IEEE802154_NEWDATA);
/* If the operation was successful, the IEEE802154_NEWDATA flag is
* removed and thus the frame can be deleted (OK will be returned).
/* The framelist probably contains only a single frame, but we will
* process it as a list of frames.
*/
if ((flags & IEEE802154_NEWDATA) != 0)
for (frame = framelist; frame != NULL; frame = next)
{
/* No.. the frame was not processed now. Return ERROR so
* that the driver may retry again later. We still need to
* set d_len to zero so that the driver is aware that there
* is nothing to be sent.
*/
/* Remove the frame from the list */
nwarn("WARNING: Frame not processed\n");
ret = ERROR;
next = frame->io_flink;
frame->io_flink = NULL;
/* Add the frame to the RX queue */
ret = ieee802154_queue_frame(conn, frame, meta);
if (ret < 0)
{
nerr("ERROR: Failed to queue frame: %d\n", ret);
iob_free(frame);
}
}
/* Perform the application callback. The frame may be processed now
* if there is a user wait for an incoming frame. Or it may pend in
* the RX queue until some user process reads the frame. NOTE: The
* return value from ieee802154_callback would distinguish these
* cases: IEEE802154_NEWDATA will still be processed if the frame
* was not consumed.
*/
(void)ieee802154_callback(radio, conn, IEEE802154_NEWDATA);
}
else
{
nerr("ERROR: No listener\n");
nwarn("WARNING: No listener\n");
}
return ret;