From b84d9559219b1e1a92e7340253d913df745e6e36 Mon Sep 17 00:00:00 2001 From: Martine Lenders <mail@martine-lenders.eu> Date: Tue, 7 Jun 2016 13:31:32 +0200 Subject: [PATCH] gnrc_netreg: add mbox support --- Makefile.dep | 4 ++ Makefile.pseudomodules | 1 + sys/include/net/gnrc/netapi.h | 15 ++++++ sys/include/net/gnrc/netreg.h | 87 +++++++++++++++++++++++++++++-- sys/net/gnrc/netapi/gnrc_netapi.c | 44 +++++++++++++++- sys/net/gnrc/netreg/gnrc_netreg.c | 10 +++- 6 files changed, 156 insertions(+), 5 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index f596f883f6..802f98b2aa 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -57,6 +57,10 @@ ifneq (,$(filter gnrc_conn_udp,$(USEMODULE))) USEMODULE += gnrc_udp endif +ifneq (,$(filter gnrc_netapi_mbox,$(USEMODULE))) + USEMODULE += core_mbox +endif + ifneq (,$(filter netdev2_tap,$(USEMODULE))) USEMODULE += netif USEMODULE += netdev2_eth diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 9e02789345..438fa415ad 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -12,6 +12,7 @@ PSEUDOMODULES += gnrc_ipv6_router PSEUDOMODULES += gnrc_ipv6_router_default PSEUDOMODULES += gnrc_netdev_default PSEUDOMODULES += gnrc_neterr +PSEUDOMODULES += gnrc_netapi_mbox PSEUDOMODULES += gnrc_pktbuf PSEUDOMODULES += gnrc_sixlowpan_border_router_default PSEUDOMODULES += gnrc_sixlowpan_default diff --git a/sys/include/net/gnrc/netapi.h b/sys/include/net/gnrc/netapi.h index 52ce4ae7a9..63ea497b78 100644 --- a/sys/include/net/gnrc/netapi.h +++ b/sys/include/net/gnrc/netapi.h @@ -21,6 +21,21 @@ * @file * @brief Generic interface to communicate with GNRC modules * + * @defgroup net_gnrc_netapi_mbox Mailbox IPC extension + * @ingroup net_gnrc_netapi + * @brief @ref core_mbox "Mailbox IPC" extension for @ref net_gnrc_netapi + * @{ + * + * @details The submodule `gnrc_netapi_mbox` provides an extension for + * @ref core_mbox "Mailbox IPC". + * + * To use, add the module `gnrc_netapi_mbox` to the `USEMODULE` macro in your + * application's Makefile: + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} + * USEMODULE += gnrc_netapi_mbox + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * @} * @author Martine Lenders <mlenders@inf.fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de> */ diff --git a/sys/include/net/gnrc/netreg.h b/sys/include/net/gnrc/netreg.h index 0b7b48a86f..d040f332c9 100644 --- a/sys/include/net/gnrc/netreg.h +++ b/sys/include/net/gnrc/netreg.h @@ -27,10 +27,24 @@ #include "net/gnrc/nettype.h" #include "net/gnrc/pkt.h" +#ifdef MODULE_GNRC_NETAPI_MBOX +#include "mbox.h" +#endif + #ifdef __cplusplus extern "C" { #endif +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) +typedef enum { + GNRC_NETREG_TYPE_DEFAULT = 0, +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) + GNRC_NETREG_TYPE_MBOX, +#endif + GNRC_NETREG_TYPE_CB, +} gnrc_netreg_type_t; +#endif + /** * @brief Demux context value to get all packets of a certain type. * @@ -47,7 +61,30 @@ extern "C" { * * @return An initialized netreg entry */ -#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid) { NULL, demux_ctx, pid } +#ifdef MODULE_GNRC_NETAPI_MBOX +#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid) { NULL, demux_ctx, \ + GNRC_NETREG_TYPE_DEFAULT, \ + { pid } } +#else +#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid) { NULL, demux_ctx, { pid } } +#endif + +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) +/** + * @brief Initializes a netreg entry statically with mbox + * + * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context" + * for the netreg entry + * @param[in] mbox Target @ref core_mbox "mailbox" for the registry entry + * + * @note Only available with @ref net_gnrc_netreg_extra. + * + * @return An initialized netreg entry + */ +#define GNRC_NETREG_ENTRY_INIT_MBOX(demux_ctx, mbox) { NULL, demux_ctx, \ + GNRC_NETREG_TYPE_MBOX, \ + { .mbox = mbox } } +#endif /** * @brief Entry to the @ref net_gnrc_netreg @@ -68,7 +105,26 @@ typedef struct gnrc_netreg_entry { * ports in UDP/TCP, or similar. */ uint32_t demux_ctx; - kernel_pid_t pid; /**< The PID of the registering thread */ +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) + /** + * @brief Type of the registry entry + * + * @note Only available with @ref net_gnrc_netapi_mbox or + * @ref net_gnrc_netapi_callbacks. + */ + gnrc_netreg_type_t type; +#endif + union { + kernel_pid_t pid; /**< The PID of the registering thread */ +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) + /** + * @brief Target @ref core_mbox "mailbox" for the registry entry + * + * @note Only available with @ref net_gnrc_netapi_mbox. + */ + mbox_t *mbox; +#endif + } target; /**< Target for the registry entry */ } gnrc_netreg_entry_t; /** @@ -91,9 +147,34 @@ static inline void gnrc_netreg_entry_init_pid(gnrc_netreg_entry_t *entry, { entry->next = NULL; entry->demux_ctx = demux_ctx; - entry->pid = pid; +#ifdef MODULE_GNRC_NETAPI_MBOX + entry->type = GNRC_NETREG_TYPE_DEFAULT; +#endif + entry->target.pid = pid; } +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) +/** + * @brief Initializes a netreg entry dynamically with mbox + * + * @param[out] entry A netreg entry + * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context" + * for the netreg entry + * @param[in] mbox Target @ref core_mbox "mailbox" for the registry entry + * + * @note Only available with @ref net_gnrc_netapi_mbox. + */ +static inline void gnrc_netreg_entry_init_mbox(gnrc_netreg_entry_t *entry, + uint32_t demux_ctx, + mbox_t *mbox) +{ + entry->next = NULL; + entry->demux_ctx = demux_ctx; + entry->type = GNRC_NETREG_TYPE_MBOX; + entry->target.mbox = mbox; +} +#endif + /** * @brief Registers a thread to the registry. * diff --git a/sys/net/gnrc/netapi/gnrc_netapi.c b/sys/net/gnrc/netapi/gnrc_netapi.c index a6294cbcab..5f80302524 100644 --- a/sys/net/gnrc/netapi/gnrc_netapi.c +++ b/sys/net/gnrc/netapi/gnrc_netapi.c @@ -18,6 +18,7 @@ * @} */ +#include "mbox.h" #include "msg.h" #include "net/gnrc/netreg.h" #include "net/gnrc/pktbuf.h" @@ -74,6 +75,22 @@ static inline int _snd_rcv(kernel_pid_t pid, uint16_t type, gnrc_pktsnip_t *pkt) return ret; } +#ifdef MODULE_GNRC_NETAPI_MBOX +static inline int _snd_rcv_mbox(mbox_t *mbox, uint16_t type, gnrc_pktsnip_t *pkt) +{ + msg_t msg; + /* set the outgoing message's fields */ + msg.type = type; + msg.content.ptr = (void *)pkt; + /* send message */ + int ret = mbox_try_put(mbox, &msg); + if (ret < 1) { + DEBUG("gnrc_netapi: dropped message to %p (was full)\n", mbox); + } + return ret; +} +#endif + int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx, uint16_t cmd, gnrc_pktsnip_t *pkt) { @@ -85,10 +102,35 @@ int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx, gnrc_pktbuf_hold(pkt, numof - 1); while (sendto) { - if (_snd_rcv(sendto->pid, cmd, pkt) < 1) { +#ifdef MODULE_GNRC_NETAPI_MBOX + int release = 0; + switch (sendto->type) { + case GNRC_NETREG_TYPE_DEFAULT: + if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { + /* unable to dispatch packet */ + release = 1; + } + break; + case GNRC_NETREG_TYPE_MBOX: + if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) { + /* unable to dispatch packet */ + release = 1; + } + break; + default: + /* unknown dispatch type */ + release = 1; + break; + } + if (release) { + gnrc_pktbuf_release(pkt); + } +#else + if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { /* unable to dispatch packet */ gnrc_pktbuf_release(pkt); } +#endif sendto = gnrc_netreg_getnext(sendto); } } diff --git a/sys/net/gnrc/netreg/gnrc_netreg.c b/sys/net/gnrc/netreg/gnrc_netreg.c index 7effd16f12..a01c557c72 100644 --- a/sys/net/gnrc/netreg/gnrc_netreg.c +++ b/sys/net/gnrc/netreg/gnrc_netreg.c @@ -37,8 +37,16 @@ void gnrc_netreg_init(void) int gnrc_netreg_register(gnrc_nettype_t type, gnrc_netreg_entry_t *entry) { +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) +#ifdef DEVELHELP /* only threads with a message queue are allowed to register at gnrc */ - assert(sched_threads[entry->pid]->msg_array); + assert((entry->type != GNRC_NETREG_TYPE_DEFAULT) || + sched_threads[entry->target.pid]->msg_array); +#endif +#else + /* only threads with a message queue are allowed to register at gnrc */ + assert(sched_threads[entry->target.pid]->msg_array); +#endif if (_INVALID_TYPE(type)) { return -EINVAL; -- GitLab