From b52034ffd236f5c312e0e3f0e5104d053e2009fa Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 19 Aug 2017 18:50:50 -0600 Subject: [PATCH] PF_IEEE802154: With this commit PF_IEEE802154 address family is basically functional. More testing is needed, of course. --- configs/same70-xplained/README.txt | 2 +- configs/sim/README.txt | 5 + include/nuttx/net/ieee802154.h | 4 +- net/devif/devif_poll.c | 2 +- net/ieee802154/Kconfig | 9 +- net/ieee802154/Make.defs | 17 +- net/ieee802154/ieee802154.h | 140 ++++++++- net/ieee802154/ieee802154_conn.c | 70 ++--- net/ieee802154/ieee802154_container.c | 221 +++++++++++++++ net/ieee802154/ieee802154_initialize.c | 71 +++++ net/ieee802154/ieee802154_input.c | 64 ++++- net/ieee802154/ieee802154_recvfrom.c | 377 +++++++++---------------- net/ieee802154/ieee802154_sockif.c | 7 +- net/pkt/pkt_recvfrom.c | 21 +- wireless/pktradio/pktradio_metadata.c | 4 +- 15 files changed, 670 insertions(+), 344 deletions(-) create mode 100644 net/ieee802154/ieee802154_container.c create mode 100644 net/ieee802154/ieee802154_initialize.c diff --git a/configs/same70-xplained/README.txt b/configs/same70-xplained/README.txt index b718e1b410..7dd0677363 100644 --- a/configs/same70-xplained/README.txt +++ b/configs/same70-xplained/README.txt @@ -1304,7 +1304,7 @@ Configuration sub-directories Then, on subsequent testing, it "magically" started behaving properaly and seems quite stable now.. although I did nothing to - the the problem. Perhaps the radio was in a bad state for awhile; + solve the problem. Perhaps the radio was in a bad state for awhile; perhaps something I did masked the problem. However, all is well for the time being. diff --git a/configs/sim/README.txt b/configs/sim/README.txt index c47b9e60b2..4e133d822d 100644 --- a/configs/sim/README.txt +++ b/configs/sim/README.txt @@ -836,6 +836,11 @@ pf_ieee802154 the IEEE 802.15.4 loopback network driver and the test at apps/examples/pf_ieee802154. + Basic usage example: + + nsh> pfserver ab:cd & + nsh> pfclient ab:cd + pktradio This configuration is identical to the 'sixlowpan configuration diff --git a/include/nuttx/net/ieee802154.h b/include/nuttx/net/ieee802154.h index 18843e833b..20ff457593 100644 --- a/include/nuttx/net/ieee802154.h +++ b/include/nuttx/net/ieee802154.h @@ -87,7 +87,7 @@ struct ieee802154_data_ind_s; /* Forward reference */ struct iob_s; /* Forward reference */ int ieee802154_input(FAR struct radio_driver_s *radio, - FAR struct iob_s *framelist, - FAR const struct ieee802154_data_ind_s *meta); + FAR struct iob_s *framelist, + FAR struct ieee802154_data_ind_s *meta); #endif /* __INCLUDE_NUTTX_NET_IEEE802154_H */ diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 52632515fc..0d28f642a3 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -259,7 +259,7 @@ static int devif_poll_ieee802154_connections(FAR struct net_driver_s *dev, /* Traverse all of the allocated packet connections and perform the poll action */ - while (!bstop && (ieee802154_conn = ieee802154_nextconn(ieee802154_conn))) + while (!bstop && (ieee802154_conn = ieee802154_conn_next(ieee802154_conn))) { /* Perform the packet TX poll */ diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 97093bf9d0..f32844ccfe 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig @@ -24,7 +24,14 @@ if NET_IEEE802154 config NET_IEEE802154_NCONNS int "Max IEEE 802.15.4 sockets" - default 1 + default 4 + +config NET_IEEE802154_NCONTAINERS + int "Number of pre-allocated frame containers" + default 20 + ---help--- + This specifies the total number of preallocated frame containers. + One must be allocated with each incoming frame. endif # NET_IEEE802154 endmenu # IEEE 802.15.4 Socket Support diff --git a/net/ieee802154/Make.defs b/net/ieee802154/Make.defs index cc33e07d56..e666b298fa 100644 --- a/net/ieee802154/Make.defs +++ b/net/ieee802154/Make.defs @@ -37,19 +37,24 @@ ifeq ($(CONFIG_NET_IEEE802154),y) +# Initialization / resource managment + +NET_CSRCS += ieee802154_initialize.c +NET_CSRCS += ieee802154_conn.c +NET_CSRCS += ieee802154_container.c + # Socket layer SOCK_CSRCS += ieee802154_sockif.c SOCK_CSRCS += ieee802154_sendto.c SOCK_CSRCS += ieee802154_recvfrom.c -# Transport layer +# Device interface -NET_CSRCS += ieee802154_conn.c -NET_CSRCS += ieee802154_input.c -NET_CSRCS += ieee802154_callback.c -NET_CSRCS += ieee802154_poll.c -NET_CSRCS += ieee802154_finddev.c +NET_CSRCS += ieee802154_input.c +NET_CSRCS += ieee802154_callback.c +NET_CSRCS += ieee802154_poll.c +NET_CSRCS += ieee802154_finddev.c # Include packet socket build support diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h index d00b80fc08..35641acdc6 100644 --- a/net/ieee802154/ieee802154.h +++ b/net/ieee802154/ieee802154.h @@ -59,20 +59,44 @@ #define ieee802154_callback_free(dev,conn,cb) \ devif_conn_callback_free(dev, cb, &conn->list) +/* Memory Pools */ + +#define IEEE802154_POOL_PREALLOCATED 0 +#define IEEE802154_POOL_DYNAMIC 1 + /**************************************************************************** * Public Type Definitions ****************************************************************************/ +/* Used for containing and queuing IOBs along with information about the + * source of the frame. + */ + +struct iob_s; /* Forward reference */ + +struct ieee802154_container_s +{ + FAR struct ieee802154_container_s *ic_flink; /* Supports a singly linked list */ + struct ieee802154_saddr_s ic_src; /* Source of the packet */ + FAR struct iob_s *ic_iob; /* Contained IOB */ + uint8_t ic_pool; /* See IEEE802154_POOL_* definitions */ +}; + /* Representation of a IEEE 802.15.4 socket connection */ -struct devif_callback_s; /* Forward reference */ +struct devif_callback_s; /* Forward reference */ struct ieee802154_conn_s { - dq_entry_t node; /* Supports a double linked list */ - struct ieee802154_saddr_s laddr; /* Locally bound / source address */ - struct ieee802154_saddr_s raddr; /* Connected remote address */ - uint8_t crefs; /* Reference counts on this instance */ + dq_entry_t node; /* Supports a double linked list */ + struct ieee802154_saddr_s laddr; /* Locally bound / source address */ + struct ieee802154_saddr_s raddr; /* Connected remote address */ + uint8_t crefs; /* Reference counts on this instance */ + + /* List of incoming packets */ + + FAR struct ieee802154_container_s *rxhead; + FAR struct ieee802154_container_s *rxtail; /* This is a list of IEEE 802.15.4 callbacks. Each callback represents * a thread that is stalled, waiting for a device-specific event. @@ -112,15 +136,32 @@ struct sockaddr; /* Forward reference */ * Name: ieee802154_initialize() * * Description: - * Initialize the IEEE 802.15.4 socket connection structures. Called - * once and only from the network initialization logic. + * Initialize the IEEE 802.15.4 socket support. Called once and only + * from the network initialization logic. + * + * Assumptions: + * Called early in the initialization sequence * ****************************************************************************/ void ieee802154_initialize(void); /**************************************************************************** - * Name: ieee802154_alloc() + * Name: ieee802154_conn_initialize + * + * Description: + * Initialize the IEEE 802.15.5 connection structure allocator. Called + * once and only from ieee802154_initialize(). + * + * Assumptions: + * Called early in the initialization sequence + * + ****************************************************************************/ + +void ieee802154_conn_initialize(void); + +/**************************************************************************** + * Name: ieee802154_conn_alloc() * * Description: * Allocate a new, uninitialized IEEE 802.15.4 socket connection @@ -129,10 +170,10 @@ void ieee802154_initialize(void); * ****************************************************************************/ -FAR struct ieee802154_conn_s *ieee802154_alloc(void); +FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void); /**************************************************************************** - * Name: ieee802154_free() + * Name: ieee802154_conn_free() * * Description: * Free a IEEE 802.15.4 socket connection structure that is no longer in @@ -140,10 +181,10 @@ FAR struct ieee802154_conn_s *ieee802154_alloc(void); * ****************************************************************************/ -void ieee802154_free(FAR struct ieee802154_conn_s *conn); +void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn); /**************************************************************************** - * Name: ieee802154_active() + * Name: ieee802154_conn_active() * * Description: * Find a connection structure that is the appropriate @@ -155,10 +196,10 @@ void ieee802154_free(FAR struct ieee802154_conn_s *conn); ****************************************************************************/ FAR struct ieee802154_conn_s * - ieee802154_active(FAR const struct ieee802154_data_ind_s *meta); + ieee802154_conn_active(FAR const struct ieee802154_data_ind_s *meta); /**************************************************************************** - * Name: ieee802154_nextconn() + * Name: ieee802154_conn_next() * * Description: * Traverse the list of allocated IEEE 802.15.4 connections @@ -169,7 +210,7 @@ FAR struct ieee802154_conn_s * ****************************************************************************/ FAR struct ieee802154_conn_s * - ieee802154_nextconn(FAR struct ieee802154_conn_s *conn); + ieee802154_conn_next(FAR struct ieee802154_conn_s *conn); /**************************************************************************** * Name: ieee802154_input @@ -339,6 +380,75 @@ ssize_t psock_ieee802154_sendto(FAR struct socket *psock, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen); +/**************************************************************************** + * Name: ieee802154_container_initialize + * + * Description: + * This function initializes the container allocator. This function must + * be called early in the initialization sequence before any socket + * activity. + * + * Inputs: + * None + * + * Return Value: + * None + * + * Assumptions: + * Called early in the initialization sequence + * + ****************************************************************************/ + +void ieee802154_container_initialize(void); + +/**************************************************************************** + * Name: ieee802154_container_allocate + * + * Description: + * The ieee802154_container_allocate function will get a free continer + * for use by the recvfrom() logic. + * + * This function will first attempt to allocate from the g_free_container + * list. If that the list is empty, then the meta-data structure will be + * allocated from the dynamic memory pool. + * + * Inputs: + * None + * + * Return Value: + * A reference to the allocated container structure. All user fields in this + * structure have been zeroed. On a failure to allocate, NULL is + * returned. + * + * Assumptions: + * The caller has locked the network. + * + ****************************************************************************/ + +FAR struct ieee802154_container_s *ieee802154_container_allocate(void); + +/**************************************************************************** + * Name: ieee802154_container_free + * + * Description: + * The ieee802154_container_free function will return a container structure + * to the free list of containers if it was a pre-allocated container + * structure. If the container structure was allocated dynamically it will + * be deallocated. + * + * Inputs: + * container - container structure to free + * + * Return Value: + * None + * + * Assumptions: + * The caller has locked the network. + * + ****************************************************************************/ + +void ieee802154_container_free(FAR struct ieee802154_container_s *container); + #undef EXTERN #ifdef __cplusplus } diff --git a/net/ieee802154/ieee802154_conn.c b/net/ieee802154/ieee802154_conn.c index acf8070174..b1cac1c3f5 100644 --- a/net/ieee802154/ieee802154_conn.c +++ b/net/ieee802154/ieee802154_conn.c @@ -58,7 +58,9 @@ * Private Data ****************************************************************************/ -/* The array containing all packet socket connections */ +/* The array containing all packet socket connections. Protected via the + * network lock. + */ static struct ieee802154_conn_s g_ieee802154_connections[CONFIG_NET_IEEE802154_NCONNS]; @@ -66,54 +68,28 @@ static struct ieee802154_conn_s /* A list of all free packet socket connections */ static dq_queue_t g_free_ieee802154_connections; -static sem_t g_free_sem; /* A list of all allocated packet socket connections */ static dq_queue_t g_active_ieee802154_connections; -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: _ieee802154_semtake() and _ieee802154_semgive() - * - * Description: - * Take/give semaphore - * - ****************************************************************************/ - -static inline void _ieee802154_semtake(sem_t *sem) -{ - /* Take the semaphore (perhaps waiting) */ - - while (net_lockedwait(sem) != 0) - { - /* The only case that an error should occur here is if - * the wait was awakened by a signal. - */ - - DEBUGASSERT(get_errno() == EINTR); - } -} - -#define _ieee802154_semgive(sem) sem_post(sem) - /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: ieee802154_initialize() + * Name: ieee802154_conn_initialize * * Description: - * Initialize the packet socket connection structures. Called once and - * only from the network logic early in initialization. + * Initialize the IEEE 802.15.5 connection structure allocator. Called + * once and only from ieee802154_initialize(). + * + * Assumptions: + * Called early in the initialization sequence * ****************************************************************************/ -void ieee802154_initialize(void) +void ieee802154_conn_initialize(void) { int i; @@ -121,7 +97,6 @@ void ieee802154_initialize(void) dq_init(&g_free_ieee802154_connections); dq_init(&g_active_ieee802154_connections); - sem_init(&g_free_sem, 0, 1); for (i = 0; i < CONFIG_NET_IEEE802154_NCONNS; i++) { @@ -133,7 +108,7 @@ void ieee802154_initialize(void) } /**************************************************************************** - * Name: ieee802154_alloc() + * Name: ieee802154_conn_alloc() * * Description: * Allocate a new, uninitialized packet socket connection structure. This @@ -141,7 +116,7 @@ void ieee802154_initialize(void) * ****************************************************************************/ -FAR struct ieee802154_conn_s *ieee802154_alloc(void) +FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void) { FAR struct ieee802154_conn_s *conn; @@ -149,7 +124,7 @@ FAR struct ieee802154_conn_s *ieee802154_alloc(void) * is protected by a semaphore (that behaves like a mutex). */ - _ieee802154_semtake(&g_free_sem); + net_lock(); conn = (FAR struct ieee802154_conn_s *) dq_remfirst(&g_free_ieee802154_connections); @@ -160,12 +135,12 @@ FAR struct ieee802154_conn_s *ieee802154_alloc(void) dq_addlast(&conn->node, &g_active_ieee802154_connections); } - _ieee802154_semgive(&g_free_sem); + net_unlock(); return conn; } /**************************************************************************** - * Name: ieee802154_free() + * Name: ieee802154_conn_free() * * Description: * Free a packet socket connection structure that is no longer in use. @@ -173,7 +148,7 @@ FAR struct ieee802154_conn_s *ieee802154_alloc(void) * ****************************************************************************/ -void ieee802154_free(FAR struct ieee802154_conn_s *conn) +void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn) { /* The free list is only accessed from user, non-interrupt level and * is protected by a semaphore (that behaves like a mutex). @@ -181,20 +156,19 @@ void ieee802154_free(FAR struct ieee802154_conn_s *conn) DEBUGASSERT(conn->crefs == 0); - _ieee802154_semtake(&g_free_sem); - /* Remove the connection from the active list */ + net_lock(); dq_rem(&conn->node, &g_active_ieee802154_connections); /* Free the connection */ dq_addlast(&conn->node, &g_free_ieee802154_connections); - _ieee802154_semgive(&g_free_sem); + net_unlock(); } /**************************************************************************** - * Name: ieee802154_active() + * Name: ieee802154_conn_active() * * Description: * Find a connection structure that is the appropriate @@ -206,7 +180,7 @@ void ieee802154_free(FAR struct ieee802154_conn_s *conn) ****************************************************************************/ FAR struct ieee802154_conn_s * - ieee802154_active(FAR const struct ieee802154_data_ind_s *meta) + ieee802154_conn_active(FAR const struct ieee802154_data_ind_s *meta) { FAR struct ieee802154_conn_s *conn; @@ -271,7 +245,7 @@ FAR struct ieee802154_conn_s * } /**************************************************************************** - * Name: ieee802154_nextconn() + * Name: ieee802154_conn_next() * * Description: * Traverse the list of allocated packet connections @@ -282,7 +256,7 @@ FAR struct ieee802154_conn_s * ****************************************************************************/ FAR struct ieee802154_conn_s * - ieee802154_nextconn(FAR struct ieee802154_conn_s *conn) + ieee802154_conn_next(FAR struct ieee802154_conn_s *conn) { if (!conn) { diff --git a/net/ieee802154/ieee802154_container.c b/net/ieee802154/ieee802154_container.c new file mode 100644 index 0000000000..af70fe645d --- /dev/null +++ b/net/ieee802154/ieee802154_container.c @@ -0,0 +1,221 @@ +/**************************************************************************** + * wireless/pktradio/ieee802154_container.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ieee802154/ieee802154.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The g_free_container is a list of IOB container structures that are + * available for general use. The number of messages in this list is a + * system configuration item. + * + * Mutually exclusive access to this list is managed via the network lock: + * i.e., the network must be locked beffore accessing this free list. + */ + +static FAR struct ieee802154_container_s *g_free_container; + +/* Pool of pre-allocated meta-data stuctures */ + +static struct ieee802154_container_s + g_container_pool[CONFIG_NET_IEEE802154_NCONTAINERS]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ieee802154_container_initialize + * + * Description: + * This function initializes the container allocator. This function must + * be called early in the initialization sequence before any socket + * activity. + * + * Inputs: + * None + * + * Return Value: + * None + * + * Assumptions: + * Called early in the initialization sequence + * + ****************************************************************************/ + +void ieee802154_container_initialize(void) +{ + FAR struct ieee802154_container_s *container; + int i; + + /* Initialize g_free_container, the list of meta-data structures that + * are available for allocation. + */ + + g_free_container = NULL; + for (i = 0, container = g_container_pool; + i < CONFIG_NET_IEEE802154_NCONTAINERS; + i++, container++) + { + /* Add the next meta data structure from the pool to the list of + * general structures. + */ + + container->ic_flink = g_free_container; + g_free_container = container; + } +} + +/**************************************************************************** + * Name: ieee802154_container_allocate + * + * Description: + * The ieee802154_container_allocate function will get a free continer + * for use by the recvfrom() logic. + * + * This function will first attempt to allocate from the g_free_container + * list. If that the list is empty, then the meta-data structure will be + * allocated from the dynamic memory pool. + * + * Inputs: + * None + * + * Return Value: + * A reference to the allocated container structure. All user fields in this + * structure have been zeroed. On a failure to allocate, NULL is + * returned. + * + * Assumptions: + * The caller has locked the network. + * + ****************************************************************************/ + +FAR struct ieee802154_container_s *ieee802154_container_allocate(void) +{ + FAR struct ieee802154_container_s *container; + uint8_t pool; + + /* Try the free list first */ + + net_lock(); + if (g_free_container != NULL) + { + container = g_free_container; + g_free_container = container->ic_flink; + pool = IEEE802154_POOL_PREALLOCATED; + net_unlock(); + } + else + { + net_unlock(); + container = (FAR struct ieee802154_container_s *) + kmm_malloc((sizeof (struct ieee802154_container_s))); + pool = IEEE802154_POOL_DYNAMIC; + } + + /* We have successfully allocated memory from some source? */ + + if (container != NULL) + { + /* Zero and tag the allocated meta-data structure. */ + + memset(container, 0, sizeof(struct ieee802154_container_s)); + container->ic_pool = pool; + } + + return container; +} + +/**************************************************************************** + * Name: ieee802154_container_free + * + * Description: + * The ieee802154_container_free function will return a container structure + * to the free list of containers if it was a pre-allocated container + * structure. If the container structure was allocated dynamically it will + * be deallocated. + * + * Inputs: + * container - container structure to free + * + * Return Value: + * None + * + * Assumptions: + * The caller has locked the network. + * + ****************************************************************************/ + +void ieee802154_container_free(FAR struct ieee802154_container_s *container) +{ + /* If this is a pre-allocated meta-data structure, then just put it back + * in the free list. + */ + + net_lock(); + if (container->ic_pool == IEEE802154_POOL_PREALLOCATED) + { + container->ic_flink = g_free_container; + g_free_container = container; + net_unlock(); + } + else + { + DEBUGASSERT(container->ic_pool == IEEE802154_POOL_DYNAMIC); + + /* Otherwise, deallocate it. */ + + net_unlock(); + sched_kfree(container); + } +} diff --git a/net/ieee802154/ieee802154_initialize.c b/net/ieee802154/ieee802154_initialize.c new file mode 100644 index 0000000000..e28f90a0e3 --- /dev/null +++ b/net/ieee802154/ieee802154_initialize.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * net/ieee802154/ieee802154_initialize.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "ieee802154/ieee802154.h" + +#ifdef CONFIG_NET_IEEE802154 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ieee802154_initialize() + * + * Description: + * Initialize the IEEE 802.15.4 socket support. Called once and only + * from the network initialization logic. + * + * Assumptions: + * Called early in the initialization sequence + * + ****************************************************************************/ + +void ieee802154_initialize(void) +{ + /* Initialize connection structions */ + + ieee802154_conn_initialize(); + + /* Initialize the container allocator */ + + ieee802154_container_initialize(); +} + +#endif /* CONFIG_NET_IEEE802154 */ diff --git a/net/ieee802154/ieee802154_input.c b/net/ieee802154/ieee802154_input.c index c776632151..c17ed82c86 100644 --- a/net/ieee802154/ieee802154_input.c +++ b/net/ieee802154/ieee802154_input.c @@ -38,6 +38,8 @@ #include +#include +#include #include #include @@ -97,15 +99,16 @@ int ieee802154_input(FAR struct radio_driver_s *radio, FAR struct iob_s *framelist, - FAR const struct ieee802154_data_ind_s *meta) + FAR struct ieee802154_data_ind_s *meta) { + FAR struct ieee802154_container_s *container; FAR struct ieee802154_conn_s *conn; int ret = OK; /* Check if there is a connection that will accept this packet */ - conn = ieee802154_active(meta); - if (conn) + conn = ieee802154_conn_active(meta); + if (conn != NULL) { uint16_t flags; @@ -117,25 +120,66 @@ 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 */ - /* REVISIT: Need to pass the meta data and the IOB through the callback */ -#warning Missing logic flags = ieee802154_callback(radio, conn, IEEE802154_NEWDATA); - /* If the operation was successful, the PKT_NEWDATA flag is removed - * and thus the packet can be deleted (OK will be returned). + /* If the operation was successful, the IEEE802154_NEWDATA flag is + * removed and thus the frame can be deleted (OK will be returned). */ - if ((flags & PKT_NEWDATA) != 0) + if ((flags & IEEE802154_NEWDATA) != 0) { - /* No.. the packet was not processed now. Return ERROR so + /* 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. */ - nwarn("WARNING: Packet not processed\n"); + nwarn("WARNING: Frame not processed\n"); ret = ERROR; } } diff --git a/net/ieee802154/ieee802154_recvfrom.c b/net/ieee802154/ieee802154_recvfrom.c index 46d63fb6a1..9d06700afc 100644 --- a/net/ieee802154/ieee802154_recvfrom.c +++ b/net/ieee802154/ieee802154_recvfrom.c @@ -68,108 +68,99 @@ struct ieee802154_recvfrom_s { + FAR struct socket *ir_sock; /* Points to the parent socket structure */ FAR struct devif_callback_s *ir_cb; /* Reference to callback instance */ - sem_t ir_sem; /* Semaphore signals recv completion */ - size_t ir_buflen; /* Length of receive buffer */ - uint8_t *ir_buffer; /* Pointer to receive buffer */ - ssize_t ir_recvlen; /* The received length */ - int ir_result; /* Success:OK, failure:negated errno */ + FAR struct sockaddr *ir_from; /* Location to return the from address */ + FAR uint8_t *ir_buffer; /* Pointer to receive buffer */ + size_t ir_buflen; /* Length of receive buffer */ + sem_t ir_sem; /* Semaphore signals recv completion */ + ssize_t ir_result; /* Success:size, failure:negated errno */ }; /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: ieee802154_add_recvlen - * - * Description: - * Update information about space available for new data and update size - * of data in buffer, This logic accounts for the case where - * recvfrom_udpreadahead() sets state.ir_recvlen == -1 . - * - * Parameters: - * pstate recvfrom state structure - * recvlen size of new data appended to buffer - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void - ieee802154_add_recvlen(FAR struct ieee802154_recvfrom_s *pstate, - size_t recvlen) -{ - if (pstate->ir_recvlen < 0) - { - pstate->ir_recvlen = 0; - } - - pstate->ir_recvlen += recvlen; - pstate->ir_buffer += recvlen; - pstate->ir_buflen -= recvlen; -} - -/**************************************************************************** - * Name: ieee802154_recvfrom_newdata - * - * Description: - * Copy the read data from the packet - * - * Parameters: - * radio The structure of the network driver that caused the interrupt - * pstate recvfrom state structure - * - * Returned Value: - * None. - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -static void ieee802154_recvfrom_newdata(FAR struct radio_driver_s *radio, - FAR struct ieee802154_recvfrom_s *pstate) -{ - size_t recvlen; - - if (radio->r_dev.d_len > pstate->ir_buflen) - { - recvlen = pstate->ir_buflen; - } - else - { - recvlen = radio->r_dev.d_len; - } - - /* Copy the new packet data into the user buffer */ - - memcpy(pstate->ir_buffer, radio->r_dev.d_buf, recvlen); - ninfo("Received %d bytes (of %d)\n", (int)recvlen, (int)radio->r_dev.d_len); - - /* Update the accumulated size of the data read */ - - ieee802154_add_recvlen(pstate, recvlen); -} - /**************************************************************************** * Name: ieee802154_recvfrom_sender * * Description: + * Perform the reception operation if there are any queued frames in the + * RX frame queue. * * Parameters: * * Returned Values: * * Assumptions: + * The network is lockec * ****************************************************************************/ -static inline void - ieee802154_recvfrom_sender(FAR struct radio_driver_s *radio, - FAR struct ieee802154_recvfrom_s *pstate) +static ssize_t ieee802154_recvfrom_rxqueue(FAR struct radio_driver_s *radio, + FAR struct ieee802154_recvfrom_s *pstate) { + FAR struct ieee802154_container_s *container; + FAR struct sockaddr_ieee802154_s *iaddr; + FAR struct ieee802154_conn_s *conn; + FAR struct iob_s *iob; + size_t copylen; + int ret = -EAGAIN; + + /* Check if there is anyting in in the RX input queue */ + + DEBUGASSERT(pstate != NULL && pstate->ir_sock != NULL); + conn = (FAR struct ieee802154_conn_s *)pstate->ir_sock->s_conn; + DEBUGASSERT(conn != NULL); + + if (conn->rxhead != NULL) + { + /* Remove the container from the RX input queue. */ + + container = conn->rxhead; + DEBUGASSERT(container != NULL); + conn->rxhead = container->ic_flink; + container->ic_flink = NULL; + + /* Did the RX queue become empty? */ + + if (conn->rxhead == NULL) + { + conn->rxtail = NULL; + } + + /* Extract the IOB containing the frame from the container */ + + iob = container->ic_iob; + container->ic_iob = NULL; + DEBUGASSERT(iob != NULL); + + /* Copy the new packet data into the user buffer */ + + copylen = iob->io_len - iob->io_offset; + memcpy(pstate->ir_buffer, &iob->io_data[iob->io_offset], copylen); + + ninfo("Received %d bytes\n", (int)copylen); + ret = copylen; + + /* If a 'from' address poiner was supplied, copy the source address + * in the container there. + */ + + if (pstate->ir_from != NULL) + { + iaddr = (FAR struct sockaddr_ieee802154_s *)pstate->ir_from; + iaddr->sa_family = AF_IEEE802154; + memcpy(&iaddr->sa_addr, &container->ic_src, sizeof(struct ieee802154_saddr_s)); + } + + /* Free both the IOB and the container */ + + iob_free(iob); + ieee802154_container_free(container); + } + + return ret; } /**************************************************************************** @@ -182,6 +173,7 @@ static inline void * Returned Values: * * Assumptions: + * The network is locked. * ****************************************************************************/ @@ -191,6 +183,7 @@ static uint16_t ieee802154_recvfrom_interrupt(FAR struct net_driver_s *dev, { FAR struct ieee802154_recvfrom_s *pstate; FAR struct radio_driver_s *radio; + ssize_t ret; ninfo("flags: %04x\n", flags); @@ -209,156 +202,42 @@ static uint16_t ieee802154_recvfrom_interrupt(FAR struct net_driver_s *dev, pstate = (FAR struct ieee802154_recvfrom_s *)pvpriv; radio = (FAR struct radio_driver_s *)dev; - /* 'priv' might be null in some race conditions (?) */ + /* 'pstate' might be null in some race conditions (?) */ - if (pstate) + if (pstate != NULL) { /* If a new packet is available, then complete the read action. */ if ((flags & IEEE802154_NEWDATA) != 0) { - /* Copy the packet */ + /* Attempt to receive the frame */ - ieee802154_recvfrom_newdata(radio, pstate); + ret = ieee802154_recvfrom_rxqueue(radio, pstate); + if (ret > 0) + { + /* Don't allow any further call backs. */ - /* Don't allow any further call backs. */ + pstate->ir_cb->flags = 0; + pstate->ir_cb->priv = NULL; + pstate->ir_cb->event = NULL; + pstate->ir_result = ret; - pstate->ir_cb->flags = 0; - pstate->ir_cb->priv = NULL; - pstate->ir_cb->event = NULL; -#if 0 - /* Save the sender's address in the caller's 'from' location */ + /* indicate that the data has been consumed */ - ieee802154_recvfrom_sender(radio, pstate); -#endif - /* indicate that the data has been consumed */ + flags &= ~IEEE802154_NEWDATA; - flags &= ~IEEE802154_NEWDATA; + /* Wake up the waiting thread, returning the number of bytes + * actually read. + */ - /* Wake up the waiting thread, returning the number of bytes - * actually read. - */ - - sem_post(&pstate->ir_sem); + sem_post(&pstate->ir_sem); + } } } return flags; } -/**************************************************************************** - * Name: ieee802154_recvfrom_initialize - * - * Description: - * Initialize the state structure - * - * Parameters: - * psock Pointer to the socket structure for the socket - * buf Buffer to receive data - * len Length of buffer - * pstate A pointer to the state structure to be initialized - * - * Returned Value: - * None - * - * Assumptions: - * - ****************************************************************************/ - -static void ieee802154_recvfrom_initialize(FAR struct socket *psock, FAR void *buf, - size_t len, FAR struct sockaddr *infrom, - FAR socklen_t *fromlen, - FAR struct ieee802154_recvfrom_s *pstate) -{ - /* Initialize the state structure. */ - - memset(pstate, 0, sizeof(struct ieee802154_recvfrom_s)); - - /* This semaphore is used for signaling and, hence, should not have - * priority inheritance enabled. - */ - - (void)sem_init(&pstate->ir_sem, 0, 0); /* Doesn't really fail */ - (void)sem_setprotocol(&pstate->ir_sem, SEM_PRIO_NONE); - - pstate->ir_buflen = len; - pstate->ir_buffer = buf; -} - -/* The only un-initialization that has to be performed is destroying the - * semaphore. - */ - -#define ieee802154_recvfrom_uninitialize(s) sem_destroy(&(s)->ir_sem) - -/**************************************************************************** - * Name: ieee802154_recvfrom_result - * - * Description: - * Evaluate the result of the recv operations - * - * Parameters: - * result The result of the net_lockedwait operation (may indicate EINTR) - * pstate A pointer to the state structure to be initialized - * - * Returned Value: - * The result of the recv operation with errno set appropriately - * - * Assumptions: - * - ****************************************************************************/ - -static ssize_t ieee802154_recvfrom_result(int result, struct ieee802154_recvfrom_s *pstate) -{ - int save_errno = get_errno(); /* In case something we do changes it */ - - /* Check for a error/timeout detected by the interrupt handler. Errors are - * signaled by negative errno values for the rcv length - */ - - if (pstate->ir_result < 0) - { - /* This might return EAGAIN on a timeout or ENOTCONN on loss of - * connection (TCP only) - */ - - return pstate->ir_result; - } - - /* If net_lockedwait failed, then we were probably reawakened by a signal. In - * this case, net_lockedwait will have set errno appropriately. - */ - - if (result < 0) - { - return -save_errno; - } - - return pstate->ir_recvlen; -} - -/**************************************************************************** - * Name: ieee802154_recvfrom_rxnotify - * - * Description: - * Notify the appropriate device driver that we are ready to receive an - * IEEE 802.1.5.4 frame - * - * Parameters: - * conn - The PF_IEEE802154 connection structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -#if 0 /* Not implemented */ -static void ieee802154_recvfrom_rxnotify(FAR struct ieee802154_conn_s *conn) -{ -# warning Missing logic -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -392,11 +271,14 @@ static void ieee802154_recvfrom_rxnotify(FAR struct ieee802154_conn_s *conn) * recv() will return 0. Otherwise, on errors, a negated errno value is * returned (see recvfrom() for the list of appropriate error values). * + * Assumptions: + * The network is locked. + * ****************************************************************************/ -ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, - int flags, FAR struct sockaddr *from, - FAR socklen_t *fromlen) +ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, + size_t len, int flags, FAR struct sockaddr *from, + FAR socklen_t *fromlen) { FAR struct ieee802154_conn_s *conn = (FAR struct ieee802154_conn_s *)psock->s_conn; FAR struct radio_driver_s *radio; @@ -407,7 +289,7 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * enough to hold this address family. */ - if (from != NULL && *fromlen < sizeof(sa_family_t)) + if (from != NULL && *fromlen < sizeof(struct sockaddr_ieee802154_s)) { return -EINVAL; } @@ -415,39 +297,51 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, if (psock->s_type != SOCK_DGRAM) { nerr("ERROR: Unsupported socket type: %d\n", psock->s_type); - ret = -ENOSYS; + return -EPROTONOSUPPORT; } /* Perform the packet recvfrom() operation */ - /* Initialize the state structure. This is done with interrupts - * disabled because we don't want anything to happen until we - * are ready. + /* Initialize the state structure. This is done with the network + * locked because we don't want anything to happen until we are ready. */ net_lock(); - ieee802154_recvfrom_initialize(psock, buf, len, from, fromlen, &state); + memset(&state, 0, sizeof(struct ieee802154_recvfrom_s)); + + state.ir_buflen = len; + state.ir_buffer = buf; + state.ir_sock = psock; + state.ir_from = from; /* Get the device driver that will service this transfer */ - radio = ieee802154_find_device(conn, &conn->laddr); + radio = ieee802154_find_device(conn, &conn->laddr); if (radio == NULL) { ret = -ENODEV; - goto errout_with_state; + goto errout_with_lock; } - /* TODO ieee802154_recvfrom_initialize() expects from to be of type - * sockaddr_in, but in our case is sockaddr_ll + /* Before we wait for data, let's check if there are already frame(s) + * waiting in the RX queue. */ -#if 0 - ret = ieee802154_connect(conn, NULL); - if (ret < 0) + ret = ieee802154_recvfrom_rxqueue(radio, &state); + if (ret > 0) { - goto errout_with_state; + /* Good newe! We have a frame and we are done. */ + + net_unlock(); + return ret; } -#endif + + /* We will have to wait. This semaphore is used for signaling and, + * hence, should not have priority inheritance enabled. + */ + + (void)sem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */ + (void)sem_setprotocol(&state.ir_sem, SEM_PRIO_NONE); /* Set the socket state to receiving */ @@ -462,25 +356,18 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, state.ir_cb->priv = (FAR void *)&state; state.ir_cb->event = ieee802154_recvfrom_interrupt; - /* Notify the device driver of the receive call */ - -#if 0 /* Not implemented */ - ieee802154_recvfrom_rxnotify(conn); -#endif - /* Wait for either the receive to complete or for an error/timeout to * occur. NOTES: (1) net_lockedwait will also terminate if a signal - * is received, (2) interrupts are disabled! They will be re-enabled - * while the task sleeps and automatically re-enabled when the task - & restarts. + * is received, (2) the network is locked! It will be un-locked while + * the task sleeps and automatically re-locked when the task restarts. */ - ret = net_lockedwait(&state.ir_sem); + (void)net_lockedwait(&state.ir_sem); - /* Make sure that no further interrupts are processed */ + /* Make sure that no further events are processed */ ieee802154_callback_free(&radio->r_dev, conn, state.ir_cb); - ret = ieee802154_recvfrom_result(ret, &state); + ret = state.ir_result; } else { @@ -490,10 +377,10 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); + sem_destroy(&state.ir_sem); -errout_with_state: +errout_with_lock: net_unlock(); - ieee802154_recvfrom_uninitialize(&state); return ret; } diff --git a/net/ieee802154/ieee802154_sockif.c b/net/ieee802154/ieee802154_sockif.c index 8624c0fe04..c8bf2767e0 100644 --- a/net/ieee802154/ieee802154_sockif.c +++ b/net/ieee802154/ieee802154_sockif.c @@ -119,6 +119,9 @@ const struct sock_intf_s g_ieee802154_sockif = * Description: * Allocate and attach a PF_IEEE802154 connection structure. * + * Assumptions: + * The network is locked + * ****************************************************************************/ static int ieee802154_sockif_alloc(FAR struct socket *psock) @@ -127,7 +130,7 @@ static int ieee802154_sockif_alloc(FAR struct socket *psock) * socket instance. */ - FAR struct ieee802154_conn_s *conn = ieee802154_alloc(); + FAR struct ieee802154_conn_s *conn = ieee802154_conn_alloc(); if (conn == NULL) { /* Failed to reserve a connection structure */ @@ -681,7 +684,7 @@ static int ieee802154_close(FAR struct socket *psock) /* Yes... free the connection structure */ conn->crefs = 0; /* No more references on the connection */ - ieee802154_free(psock->s_conn); /* Free network resources */ + ieee802154_conn_free(psock->s_conn); /* Free network resources */ } else { diff --git a/net/pkt/pkt_recvfrom.c b/net/pkt/pkt_recvfrom.c index 63bbf76748..eb4c79485a 100644 --- a/net/pkt/pkt_recvfrom.c +++ b/net/pkt/pkt_recvfrom.c @@ -117,7 +117,7 @@ static inline void pkt_add_recvlen(FAR struct pkt_recvfrom_s *pstate, * Copy the read data from the packet * * Parameters: - * dev The structure of the network driver that caused the interrupt + * dev The structure of the network driver that caused the event. * pstate recvfrom state structure * * Returned Value: @@ -212,11 +212,11 @@ static uint16_t pkt_recvfrom_interrupt(FAR struct net_driver_s *dev, pstate->pr_cb->flags = 0; pstate->pr_cb->priv = NULL; pstate->pr_cb->event = NULL; -#if 0 + /* Save the sender's address in the caller's 'from' location */ pkt_recvfrom_sender(dev, pstate); -#endif + /* indicate that the data has been consumed */ flags &= ~PKT_NEWDATA; @@ -406,9 +406,8 @@ ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, /* Perform the packet recvfrom() operation */ - /* Initialize the state structure. This is done with interrupts - * disabled because we don't want anything to happen until we - * are ready. + /* Initialize the state structure. This is done with the network + * locked because we don't want anything to happen until we are ready. */ net_lock(); @@ -454,15 +453,15 @@ ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, pkt_recvfrom_rxnotify(conn); #endif - /* Wait for either the receive to complete or for an error/timeout to occur. - * NOTES: (1) net_lockedwait will also terminate if a signal is received, (2) - * interrupts are disabled! They will be re-enabled while the task sleeps - * and automatically re-enabled when the task restarts. + /* Wait for either the receive to complete or for an error/timeout to + * occur. NOTES: (1) net_lockedwait will also terminate if a signal + * is received, (2) the network is locked! It will be un-locked while + * the task sleeps and automatically re-locked when the task restarts. */ ret = net_lockedwait(&state.pr_sem); - /* Make sure that no further interrupts are processed */ + /* Make sure that no further events are processed */ pkt_callback_free(dev, conn, state.pr_cb); ret = pkt_recvfrom_result(ret, &state); diff --git a/wireless/pktradio/pktradio_metadata.c b/wireless/pktradio/pktradio_metadata.c index 2bc94fee9d..be819d19aa 100644 --- a/wireless/pktradio/pktradio_metadata.c +++ b/wireless/pktradio/pktradio_metadata.c @@ -60,7 +60,7 @@ * item. */ -static struct pktradio_metadata_s *g_free_metadata; +static FAR struct pktradio_metadata_s *g_free_metadata; /* Supports mutually exclusive access to the free list */ @@ -188,7 +188,7 @@ FAR struct pktradio_metadata_s *pktradio_metadata_allocate(void) if (metadata != NULL) { - /* Zero and tag the alloated meta-data structure. */ + /* Zero and tag the allocated meta-data structure. */ memset(metadata, 0, sizeof(struct pktradio_metadata_s)); metadata->pm_pool = pool;