mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-29 01:55:47 +00:00
Remove network specific default and max log level setting and start to use the zephyr logging values for those. Remove LOG_MODULE_REGISTER() from net_core.h and place the calls into .c files. This is done in order to avoid weird compiler errors in some cases and to make the code look similar as other subsystems. Fixes #11343 Fixes #11659 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
390 lines
8.9 KiB
C
390 lines
8.9 KiB
C
/*
|
|
* Copyright (c) 2016 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <logging/log.h>
|
|
LOG_MODULE_REGISTER(net_mgmt, CONFIG_NET_MGMT_EVENT_LOG_LEVEL);
|
|
|
|
#include <kernel.h>
|
|
#include <toolchain.h>
|
|
#include <linker/sections.h>
|
|
|
|
#include <misc/util.h>
|
|
#include <misc/slist.h>
|
|
#include <net/net_mgmt.h>
|
|
|
|
#include "net_private.h"
|
|
|
|
struct mgmt_event_entry {
|
|
u32_t event;
|
|
struct net_if *iface;
|
|
|
|
#ifdef CONFIG_NET_MGMT_EVENT_INFO
|
|
u8_t info[NET_EVENT_INFO_MAX_SIZE];
|
|
size_t info_length;
|
|
#endif /* CONFIG_NET_MGMT_EVENT_INFO */
|
|
};
|
|
|
|
struct mgmt_event_wait {
|
|
struct k_sem sync_call;
|
|
struct net_if *iface;
|
|
};
|
|
|
|
static K_SEM_DEFINE(network_event, 0, UINT_MAX);
|
|
static K_SEM_DEFINE(net_mgmt_lock, 1, 1);
|
|
|
|
NET_STACK_DEFINE(MGMT, mgmt_stack, CONFIG_NET_MGMT_EVENT_STACK_SIZE,
|
|
CONFIG_NET_MGMT_EVENT_STACK_SIZE);
|
|
static struct k_thread mgmt_thread_data;
|
|
static struct mgmt_event_entry events[CONFIG_NET_MGMT_EVENT_QUEUE_SIZE];
|
|
static u32_t global_event_mask;
|
|
static sys_slist_t event_callbacks;
|
|
static s16_t in_event;
|
|
static s16_t out_event;
|
|
|
|
static inline void mgmt_push_event(u32_t mgmt_event, struct net_if *iface,
|
|
void *info, size_t length)
|
|
{
|
|
s16_t i_idx;
|
|
|
|
#ifndef CONFIG_NET_MGMT_EVENT_INFO
|
|
ARG_UNUSED(info);
|
|
ARG_UNUSED(length);
|
|
#endif /* CONFIG_NET_MGMT_EVENT_INFO */
|
|
|
|
k_sem_take(&net_mgmt_lock, K_FOREVER);
|
|
|
|
i_idx = in_event + 1;
|
|
if (i_idx == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
|
|
i_idx = 0;
|
|
}
|
|
|
|
#ifdef CONFIG_NET_MGMT_EVENT_INFO
|
|
if (info && length) {
|
|
if (length <= NET_EVENT_INFO_MAX_SIZE) {
|
|
memcpy(events[i_idx].info, info, length);
|
|
events[i_idx].info_length = length;
|
|
} else {
|
|
NET_ERR("Event info length %zu > max size %zu",
|
|
length, NET_EVENT_INFO_MAX_SIZE);
|
|
k_sem_give(&net_mgmt_lock);
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
events[i_idx].info_length = 0;
|
|
}
|
|
#endif /* CONFIG_NET_MGMT_EVENT_INFO */
|
|
|
|
events[i_idx].event = mgmt_event;
|
|
events[i_idx].iface = iface;
|
|
|
|
if (i_idx == out_event) {
|
|
u16_t o_idx = out_event + 1;
|
|
|
|
if (o_idx == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
|
|
o_idx = 0U;
|
|
}
|
|
|
|
if (events[o_idx].event) {
|
|
out_event = o_idx;
|
|
}
|
|
} else if (out_event < 0) {
|
|
out_event = i_idx;
|
|
}
|
|
|
|
in_event = i_idx;
|
|
|
|
k_sem_give(&net_mgmt_lock);
|
|
}
|
|
|
|
static inline struct mgmt_event_entry *mgmt_pop_event(void)
|
|
{
|
|
s16_t o_idx;
|
|
|
|
if (out_event < 0 || !events[out_event].event) {
|
|
return NULL;
|
|
}
|
|
|
|
o_idx = out_event;
|
|
out_event++;
|
|
|
|
if (o_idx == in_event) {
|
|
in_event = -1;
|
|
out_event = -1;
|
|
} else if (out_event == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
|
|
out_event = 0;
|
|
}
|
|
|
|
return &events[o_idx];
|
|
}
|
|
|
|
static inline void mgmt_clean_event(struct mgmt_event_entry *mgmt_event)
|
|
{
|
|
mgmt_event->event = 0U;
|
|
mgmt_event->iface = NULL;
|
|
}
|
|
|
|
static inline void mgmt_add_event_mask(u32_t event_mask)
|
|
{
|
|
global_event_mask |= event_mask;
|
|
}
|
|
|
|
static inline void mgmt_rebuild_global_event_mask(void)
|
|
{
|
|
struct net_mgmt_event_callback *cb, *tmp;
|
|
|
|
global_event_mask = 0U;
|
|
|
|
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&event_callbacks, cb, tmp, node) {
|
|
mgmt_add_event_mask(cb->event_mask);
|
|
}
|
|
}
|
|
|
|
static inline bool mgmt_is_event_handled(u32_t mgmt_event)
|
|
{
|
|
return (((NET_MGMT_GET_LAYER(mgmt_event) &
|
|
NET_MGMT_GET_LAYER(global_event_mask)) ==
|
|
NET_MGMT_GET_LAYER(mgmt_event)) &&
|
|
((NET_MGMT_GET_LAYER_CODE(mgmt_event) &
|
|
NET_MGMT_GET_LAYER_CODE(global_event_mask)) ==
|
|
NET_MGMT_GET_LAYER_CODE(mgmt_event)) &&
|
|
((NET_MGMT_GET_COMMAND(mgmt_event) &
|
|
NET_MGMT_GET_COMMAND(global_event_mask)) ==
|
|
NET_MGMT_GET_COMMAND(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 cmd %u",
|
|
NET_MGMT_GET_LAYER(mgmt_event->event),
|
|
NET_MGMT_GET_LAYER_CODE(mgmt_event->event),
|
|
NET_MGMT_GET_COMMAND(mgmt_event->event));
|
|
|
|
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&event_callbacks, cb, tmp, node) {
|
|
if (!(NET_MGMT_GET_LAYER(mgmt_event->event) ==
|
|
NET_MGMT_GET_LAYER(cb->event_mask)) ||
|
|
!(NET_MGMT_GET_LAYER_CODE(mgmt_event->event) ==
|
|
NET_MGMT_GET_LAYER_CODE(cb->event_mask)) ||
|
|
(NET_MGMT_GET_COMMAND(mgmt_event->event) &&
|
|
NET_MGMT_GET_COMMAND(cb->event_mask) &&
|
|
!(NET_MGMT_GET_COMMAND(mgmt_event->event) &
|
|
NET_MGMT_GET_COMMAND(cb->event_mask)))) {
|
|
continue;
|
|
}
|
|
|
|
#ifdef CONFIG_NET_MGMT_EVENT_INFO
|
|
if (mgmt_event->info_length) {
|
|
cb->info = (void *)mgmt_event->info;
|
|
} else {
|
|
cb->info = NULL;
|
|
}
|
|
#endif /* CONFIG_NET_MGMT_EVENT_INFO */
|
|
|
|
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);
|
|
|
|
if (sync_data->iface &&
|
|
sync_data->iface != mgmt_event->iface) {
|
|
continue;
|
|
}
|
|
|
|
NET_DBG("Unlocking %p synchronous call", cb);
|
|
|
|
cb->raised_event = mgmt_event->event;
|
|
sync_data->iface = mgmt_event->iface;
|
|
|
|
sys_slist_remove(&event_callbacks, prev, &cb->node);
|
|
|
|
k_sem_give(cb->sync_call);
|
|
} 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
|
|
net_analyze_stack("Net MGMT event stack",
|
|
K_THREAD_STACK_BUFFER(mgmt_stack),
|
|
K_THREAD_STACK_SIZEOF(mgmt_stack));
|
|
#endif
|
|
}
|
|
|
|
static void mgmt_thread(void)
|
|
{
|
|
struct mgmt_event_entry *mgmt_event;
|
|
|
|
while (1) {
|
|
k_sem_take(&network_event, K_FOREVER);
|
|
k_sem_take(&net_mgmt_lock, K_FOREVER);
|
|
|
|
NET_DBG("Handling events, forwarding it relevantly");
|
|
|
|
mgmt_event = mgmt_pop_event();
|
|
if (!mgmt_event) {
|
|
/* System is over-loaded?
|
|
* At this point we have most probably notified
|
|
* more events than we could handle
|
|
*/
|
|
NET_DBG("Some event got probably lost (%u)",
|
|
k_sem_count_get(&network_event));
|
|
|
|
k_sem_init(&network_event, 0, UINT_MAX);
|
|
k_sem_give(&net_mgmt_lock);
|
|
|
|
continue;
|
|
}
|
|
|
|
mgmt_run_callbacks(mgmt_event);
|
|
|
|
mgmt_clean_event(mgmt_event);
|
|
|
|
k_sem_give(&net_mgmt_lock);
|
|
|
|
k_yield();
|
|
}
|
|
}
|
|
|
|
static int mgmt_event_wait_call(struct net_if *iface,
|
|
u32_t mgmt_event_mask,
|
|
u32_t *raised_event,
|
|
struct net_if **event_iface,
|
|
const void **info,
|
|
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;
|
|
|
|
if (iface) {
|
|
sync_data.iface = iface;
|
|
}
|
|
|
|
NET_DBG("Synchronous event 0x%08x wait %p", sync.event_mask, &sync);
|
|
|
|
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 (event_iface) {
|
|
*event_iface = sync_data.iface;
|
|
}
|
|
|
|
#ifdef CONFIG_NET_MGMT_EVENT_INFO
|
|
if (info) {
|
|
*info = sync.info;
|
|
}
|
|
#endif /* CONFIG_NET_MGMT_EVENT_INFO */
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void net_mgmt_add_event_callback(struct net_mgmt_event_callback *cb)
|
|
{
|
|
NET_DBG("Adding event callback %p", cb);
|
|
|
|
k_sem_take(&net_mgmt_lock, K_FOREVER);
|
|
|
|
sys_slist_prepend(&event_callbacks, &cb->node);
|
|
|
|
mgmt_add_event_mask(cb->event_mask);
|
|
|
|
k_sem_give(&net_mgmt_lock);
|
|
}
|
|
|
|
void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb)
|
|
{
|
|
NET_DBG("Deleting event callback %p", cb);
|
|
|
|
k_sem_take(&net_mgmt_lock, K_FOREVER);
|
|
|
|
sys_slist_find_and_remove(&event_callbacks, &cb->node);
|
|
|
|
mgmt_rebuild_global_event_mask();
|
|
|
|
k_sem_give(&net_mgmt_lock);
|
|
}
|
|
|
|
void net_mgmt_event_notify_with_info(u32_t mgmt_event, struct net_if *iface,
|
|
void *info, size_t length)
|
|
{
|
|
if (mgmt_is_event_handled(mgmt_event)) {
|
|
NET_DBG("Notifying Event layer %u code %u type %u",
|
|
NET_MGMT_GET_LAYER(mgmt_event),
|
|
NET_MGMT_GET_LAYER_CODE(mgmt_event),
|
|
NET_MGMT_GET_COMMAND(mgmt_event));
|
|
|
|
mgmt_push_event(mgmt_event, iface, info, length);
|
|
k_sem_give(&network_event);
|
|
}
|
|
}
|
|
|
|
int net_mgmt_event_wait(u32_t mgmt_event_mask,
|
|
u32_t *raised_event,
|
|
struct net_if **iface,
|
|
const void **info,
|
|
int timeout)
|
|
{
|
|
return mgmt_event_wait_call(NULL, mgmt_event_mask,
|
|
raised_event, iface, info, timeout);
|
|
}
|
|
|
|
int net_mgmt_event_wait_on_iface(struct net_if *iface,
|
|
u32_t mgmt_event_mask,
|
|
u32_t *raised_event,
|
|
const void **info,
|
|
int timeout)
|
|
{
|
|
NET_ASSERT(NET_MGMT_ON_IFACE(mgmt_event_mask));
|
|
NET_ASSERT(iface);
|
|
|
|
return mgmt_event_wait_call(iface, mgmt_event_mask,
|
|
raised_event, NULL, info, timeout);
|
|
}
|
|
|
|
void net_mgmt_event_init(void)
|
|
{
|
|
sys_slist_init(&event_callbacks);
|
|
global_event_mask = 0U;
|
|
|
|
in_event = -1;
|
|
out_event = -1;
|
|
|
|
(void)memset(events, 0, CONFIG_NET_MGMT_EVENT_QUEUE_SIZE *
|
|
sizeof(struct mgmt_event_entry));
|
|
|
|
k_thread_create(&mgmt_thread_data, mgmt_stack,
|
|
K_THREAD_STACK_SIZEOF(mgmt_stack),
|
|
(k_thread_entry_t)mgmt_thread, NULL, NULL, NULL,
|
|
K_PRIO_COOP(CONFIG_NET_MGMT_EVENT_THREAD_PRIO), 0, 0);
|
|
k_thread_name_set(&mgmt_thread_data, "net_mgmt");
|
|
|
|
NET_DBG("Net MGMT initialized: queue of %u entries, stack size of %u",
|
|
CONFIG_NET_MGMT_EVENT_QUEUE_SIZE,
|
|
CONFIG_NET_MGMT_EVENT_STACK_SIZE);
|
|
}
|