net/mgmt: Add a function to wait on a event synchronously

Instead of creating a handler and a related callback structure on an
event_mask: net_mgmt_event_wait() can be used to wait synchronously on
such event_mask. The core mgmt part will seamlessly reuse the struct
net_mgmt_event_callback so the whole internal notification mechanism is
using the same code.

Change-Id: I426d782c770e75e5222aa3c5b703172b1f1f2e5e
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-03-13 11:54:37 +01:00 committed by Jukka Rissanen
parent c1ecd8c890
commit 35e5aa8865
4 changed files with 138 additions and 11 deletions

View file

@ -47,3 +47,15 @@
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
^.*dns_context.address
^[- \t]*\^
#
# include/net/net_mgmt.h
#
^(?P<filename>[-._/\w]+/doc/api/networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
^[ \t]*
^[ \t]*\^
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
^[ \t]*
^[ \t]*\^
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
^.*net_mgmt_event_callback.__unnamed__
^[- \t]*\^

View file

@ -29,11 +29,13 @@ struct net_if;
#define NET_MGMT_EVENT_MASK 0x80000000
#define NET_MGMT_ON_IFACE_MASK 0x40000000
#define NET_MGMT_LAYER_MASK 0x30000000
#define NET_MGMT_LAYER_CODE_MASK 0x0FFF0000
#define NET_MGMT_SYNC_EVENT_MASK 0x08000000
#define NET_MGMT_LAYER_CODE_MASK 0x07FF0000
#define NET_MGMT_COMMAND_MASK 0x0000FFFF
#define NET_MGMT_EVENT_BIT BIT(31)
#define NET_MGMT_IFACE_BIT BIT(30)
#define NET_MGMT_SYNC_EVENT_BIT BIT(27)
#define NET_MGMT_LAYER(_layer) (_layer << 28)
#define NET_MGMT_LAYER_CODE(_code) (_code << 16)
@ -44,6 +46,9 @@ struct net_if;
#define NET_MGMT_ON_IFACE(mgmt_request) \
(mgmt_request & NET_MGMT_ON_IFACE_MASK)
#define NET_MGMT_EVENT_SYNCHRONOUS(mgmt_request) \
(mgmt_request & NET_MGMT_SYNC_EVENT_MASK)
#define NET_MGMT_GET_LAYER(mgmt_request) \
((mgmt_request & NET_MGMT_LAYER_MASK) >> 28)
@ -115,16 +120,33 @@ struct net_mgmt_event_callback {
*/
sys_snode_t node;
/** Actual callback function being used to notify the owner
*/
net_mgmt_event_handler_t handler;
union {
/** Actual callback function being used to notify the owner
*/
net_mgmt_event_handler_t handler;
/** Semaphore meant to be used internaly for the synchronous
* net_mgmt_event_wait() function.
*/
struct k_sem *sync_call;
};
/** A mask of network events on which the above handler should be
* called in case those events come. Such mask can be modified
* whenever necessary by the owner, and thus will affect the handler
* being called or not.
*/
uint32_t event_mask;
union {
/** A mask of network events on which the above handler should
* be called in case those events come. Such mask can be
* modified whenever necessary by the owner, and thus will
* affect the handler being called or not.
*/
uint32_t event_mask;
/** Internal place holder when a synchronous event wait is
* successfully unlocked on a event.
*/
uint32_t raised_event;
};
};
#ifdef CONFIG_NET_MGMT_EVENT
@ -166,6 +188,28 @@ void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb);
*/
void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface);
/**
* @brief Used to wait synchronously on an event mask
* @param mgmt_event_mask A mask of relevant events to wait on.
* @param raised_event a pointer on a uint32_t to get which event from
* the mask generated the event. Can be NULL if the caller is not
* interested in that information.
* @param iface a pointer on a place holder for the iface on which the
* event has originated from. This is valid if only the event mask
* has bit NET_MGMT_IFACE_BIT set relevantly, depending on events
* the caller wants to listen to.
* @param timeout a delay in milliseconds. K_FOREVER can be used to wait
* undefinitely.
*
* @return 0 on success, a negative error code otherwise. -ETIMEDOUT will
* be specifically returned if the timeout kick-in instead of an
* actual event.
*/
int net_mgmt_event_wait(uint32_t mgmt_event_mask,
uint32_t *raised_event,
struct net_if **iface,
int timeout);
/**
* @brief Used by the core of the network stack to initialize the network
* event processing.
@ -176,6 +220,15 @@ void net_mgmt_event_init(void);
#define net_mgmt_add_event_callback(...)
#define net_mgmt_event_notify(...)
#define net_mgmt_event_init(...)
static inline int net_mgmt_event_wait(uint32_t mgmt_event_mask,
uint32_t *raised_event,
struct net_if **iface,
int timeout)
{
return 0;
}
#endif /* CONFIG_NET_MGMT_EVENT */
/**

View file

@ -22,6 +22,11 @@ struct mgmt_event_entry {
struct net_if *iface;
};
struct mgmt_event_wait {
struct k_sem sync_call;
struct net_if *iface;
};
static struct k_sem network_event;
NET_STACK_DEFINE(MGMT, mgmt_stack, CONFIG_NET_MGMT_EVENT_STACK_SIZE,
CONFIG_NET_MGMT_EVENT_STACK_SIZE);
@ -102,6 +107,7 @@ static inline bool mgmt_is_event_handled(uint32_t mgmt_event)
static inline void mgmt_run_callbacks(struct mgmt_event_entry *mgmt_event)
{
sys_snode_t *prev = NULL;
struct net_mgmt_event_callback *cb, *tmp;
NET_DBG("Event layer %u code %u type %u",
@ -110,10 +116,30 @@ static inline void mgmt_run_callbacks(struct mgmt_event_entry *mgmt_event)
NET_MGMT_GET_COMMAND(mgmt_event->event));
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&event_callbacks, cb, tmp, node) {
NET_DBG("Running callback %p : %p", cb, cb->handler);
if ((mgmt_event->event & cb->event_mask) == mgmt_event->event) {
cb->handler(cb, mgmt_event->event, mgmt_event->iface);
if (NET_MGMT_EVENT_SYNCHRONOUS(cb->event_mask)) {
struct mgmt_event_wait *sync_data =
CONTAINER_OF(cb->sync_call,
struct mgmt_event_wait,
sync_call);
NET_DBG("Unlocking %p synchronous call", cb);
cb->raised_event = mgmt_event->event;
sync_data->iface = mgmt_event->iface;
k_sem_give(cb->sync_call);
sys_slist_remove(&event_callbacks,
prev, &cb->node);
} else {
NET_DBG("Running callback %p : %p",
cb, cb->handler);
cb->handler(cb, mgmt_event->event,
mgmt_event->iface);
prev = &cb->node;
}
}
#ifdef CONFIG_NET_DEBUG_MGMT_EVENT_STACK
@ -186,6 +212,42 @@ void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface)
}
}
int net_mgmt_event_wait(uint32_t mgmt_event_mask,
uint32_t *raised_event,
struct net_if **iface,
int timeout)
{
struct mgmt_event_wait sync_data = {
.sync_call = K_SEM_INITIALIZER(sync_data.sync_call, 0, 1),
};
struct net_mgmt_event_callback sync = {
.sync_call = &sync_data.sync_call,
.event_mask = mgmt_event_mask | NET_MGMT_SYNC_EVENT_BIT,
};
int ret;
NET_DBG("Synchronous event wait %p", &cb);
net_mgmt_add_event_callback(&sync);
ret = k_sem_take(sync.sync_call, timeout);
if (ret == -EAGAIN) {
ret = -ETIMEDOUT;
} else {
if (!ret) {
if (raised_event) {
*raised_event = sync.raised_event;
}
if (iface) {
*iface = sync_data.iface;
}
}
}
return ret;
}
void net_mgmt_event_init(void)
{
sys_slist_init(&event_callbacks);

View file

@ -13,9 +13,9 @@
#include <net/net_mgmt.h>
#include <net/nbuf.h>
#define TEST_MGMT_REQUEST 0x0ABC1234
#define TEST_MGMT_EVENT 0x8ABC1234
#define TEST_MGMT_EVENT_UNHANDLED 0x8ABC4321
#define TEST_MGMT_REQUEST 0x07AB1234
#define TEST_MGMT_EVENT 0x87AB1234
#define TEST_MGMT_EVENT_UNHANDLED 0x87AB4321
/* Notifier infra */
static uint32_t event2throw;