Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc_netreg: mbox and arbitrary callback support #5526

Merged
merged 3 commits into from
Oct 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Makefile.pseudomodules
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ PSEUDOMODULES += gnrc_ipv6_router
PSEUDOMODULES += gnrc_ipv6_router_default
PSEUDOMODULES += gnrc_netdev_default
PSEUDOMODULES += gnrc_neterr
PSEUDOMODULES += gnrc_netapi_callbacks
PSEUDOMODULES += gnrc_netapi_mbox
PSEUDOMODULES += gnrc_pktbuf
PSEUDOMODULES += gnrc_sixlowpan_border_router_default
PSEUDOMODULES += gnrc_sixlowpan_default
Expand Down
8 changes: 4 additions & 4 deletions examples/gnrc_networking/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static void start_server(char *port_str)
uint16_t port;

/* check if server is already running */
if (server.pid != KERNEL_PID_UNDEF) {
if (server.target.pid != KERNEL_PID_UNDEF) {
printf("Error: server already running on port %" PRIu32 "\n",
server.demux_ctx);
return;
Expand All @@ -106,7 +106,7 @@ static void start_server(char *port_str)
return;
}
/* start server (which means registering pktdump for the chosen port) */
server.pid = gnrc_pktdump_pid;
server.target.pid = gnrc_pktdump_pid;
server.demux_ctx = (uint32_t)port;
gnrc_netreg_register(GNRC_NETTYPE_UDP, &server);
printf("Success: started UDP server on port %" PRIu16 "\n", port);
Expand All @@ -115,13 +115,13 @@ static void start_server(char *port_str)
static void stop_server(void)
{
/* check if server is running at all */
if (server.pid == KERNEL_PID_UNDEF) {
if (server.target.pid == KERNEL_PID_UNDEF) {
printf("Error: server was not running\n");
return;
}
/* stop server */
gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &server);
server.pid = KERNEL_PID_UNDEF;
server.target.pid = KERNEL_PID_UNDEF;
puts("Success: stopped UDP server");
}

Expand Down
30 changes: 30 additions & 0 deletions sys/include/net/gnrc/netapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,36 @@
* @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
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* @}
*
* @defgroup net_gnrc_netapi_callbacks Callback extension
* @ingroup net_gnrc_netapi
* @brief Callback extension for @ref net_gnrc_netapi
* @{
* @details The submodule `gnrc_netapi_callbacks` provides an extension for
* callbacks to run GNRC thread-less.
*
* To use, add the module `gnrc_netapi_callbacks` to the `USEMODULE` macro in
* your application's Makefile:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk}
* USEMODULE += gnrc_netapi_callbacks
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* @}
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
Expand Down
164 changes: 161 additions & 3 deletions sys/include/net/gnrc/netreg.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,27 @@
#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(MODULE_GNRC_NETAPI_CALLBACKS) || \
defined(DOXYGEN)
typedef enum {
GNRC_NETREG_TYPE_DEFAULT = 0,
#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN)
GNRC_NETREG_TYPE_MBOX,
#endif
#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN)
GNRC_NETREG_TYPE_CB,
#endif
} gnrc_netreg_type_t;
#endif

/**
* @brief Demux context value to get all packets of a certain type.
*
Expand All @@ -47,7 +64,72 @@ 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_netapi_mbox.
*
* @return An initialized netreg entry
*/
#define GNRC_NETREG_ENTRY_INIT_MBOX(demux_ctx, mbox) { NULL, demux_ctx, \
GNRC_NETREG_TYPE_MBOX, \
{ .mbox = mbox } }
#endif

#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN)
/**
* @brief Initializes a netreg entry statically with callback
*
* @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context"
* for the netreg entry
* @param[in] cb Target callback for the registry entry
*
* @note Only available with @ref net_gnrc_netapi_callbacks.
*
* @return An initialized netreg entry
*/
#define GNRC_NETREG_ENTRY_INIT_CB(demux_ctx, cbd) { NULL, demux_ctx, \
GNRC_NETREG_TYPE_CB, \
{ .cbd = cbd } }

/**
* @brief Packet handler callback for netreg entries with callback.
*
* @pre `cmd` $\in$ { @ref GNRC_NETAPI_MSG_TYPE_RCV, @ref GNRC_NETAPI_MSG_TYPE_SND }
*
* @note Only available with @ref net_gnrc_netapi_callbacks.
*
* @param[in] cmd @ref net_gnrc_netapi command type. Must be either
* @ref GNRC_NETAPI_MSG_TYPE_SND or
* @ref GNRC_NETAPI_MSG_TYPE_RCV
* @param[in] pkt The packet to handle.
* @param[in] ctx Application context.
*/
typedef void (*gnrc_netreg_entry_cb_t)(uint16_t cmd, gnrc_pktsnip_t *pkt,
void *ctx);

/**
* @brief Callback + Context descriptor
* @note Only available with @ref net_gnrc_netapi_callbacks.
*/
typedef struct {
gnrc_netreg_entry_cb_t cb; /**< the callback */
void *ctx; /**< application context for the callback */
} gnrc_netreg_entry_cbd_t;
#endif

/**
* @brief Entry to the @ref net_gnrc_netreg
Expand All @@ -68,7 +150,36 @@ 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(MODULE_GNRC_NETAPI_CALLBACKS) || \
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

#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN)
/**
* @brief Target callback for the registry entry
*
* @note Only available with @ref net_gnrc_netapi_callbacks.
*/
gnrc_netreg_entry_cbd_t *cbd;
#endif
} target; /**< Target for the registry entry */
} gnrc_netreg_entry_t;

/**
Expand All @@ -91,9 +202,56 @@ static inline void gnrc_netreg_entry_init_pid(gnrc_netreg_entry_t *entry,
{
entry->next = NULL;
entry->demux_ctx = demux_ctx;
entry->pid = pid;
#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS)
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

#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN)
/**
* @brief Initializes a netreg entry dynamically with callback
*
* @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 callback for the registry entry
*
* @note Only available with @ref net_gnrc_netapi_callbacks.
*/
static inline void gnrc_netreg_entry_init_cb(gnrc_netreg_entry_t *entry,
uint32_t demux_ctx,
gnrc_netreg_entry_cbd_t *cbd)
{
entry->next = NULL;
entry->demux_ctx = demux_ctx;
entry->type = GNRC_NETREG_TYPE_CB;
entry->target.cbd = cbd;
}
#endif

/**
* @brief Registers a thread to the registry.
*
Expand Down
2 changes: 1 addition & 1 deletion sys/net/gnrc/conn/ip/gnrc_conn_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int conn_ip_create(conn_ip_t *conn, const void *addr, size_t addr_len, int famil
void conn_ip_close(conn_ip_t *conn)
{
assert(conn->l4_type == GNRC_NETTYPE_UNDEF);
if (conn->netreg_entry.pid != KERNEL_PID_UNDEF) {
if (conn->netreg_entry.target.pid != KERNEL_PID_UNDEF) {
gnrc_netreg_unregister(conn->l3_type, &conn->netreg_entry);
}
}
Expand Down
4 changes: 2 additions & 2 deletions sys/net/gnrc/conn/udp/gnrc_conn_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ int conn_udp_create(conn_udp_t *conn, const void *addr, size_t addr_len,
void conn_udp_close(conn_udp_t *conn)
{
assert(conn->l4_type == GNRC_NETTYPE_UDP);
if (conn->netreg_entry.pid != KERNEL_PID_UNDEF) {
if (conn->netreg_entry.target.pid != KERNEL_PID_UNDEF) {
gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &conn->netreg_entry);
conn->netreg_entry.pid = KERNEL_PID_UNDEF;
conn->netreg_entry.target.pid = KERNEL_PID_UNDEF;
}
}

Expand Down
51 changes: 50 additions & 1 deletion sys/net/gnrc/netapi/gnrc_netapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @}
*/

#include "mbox.h"
#include "msg.h"
#include "net/gnrc/netreg.h"
#include "net/gnrc/pktbuf.h"
Expand Down Expand Up @@ -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)
{
Expand All @@ -85,10 +102,42 @@ 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) {
#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS)
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;
#ifdef MODULE_GNRC_NETAPI_MBOX
case GNRC_NETREG_TYPE_MBOX:
if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) {
/* unable to dispatch packet */
release = 1;
}
break;
#endif
#ifdef MODULE_GNRC_NETAPI_CALLBACKS
case GNRC_NETREG_TYPE_CB:
sendto->target.cbd->cb(cmd, pkt, sendto->target.cbd->ctx);
break;
#endif
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);
}
}
Expand Down
Loading