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:
parent
969d7c5814
commit
0eac90f775
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user