blob: a3cdc903c6c8c4b7a02a9f757d9d8ba56a81dfcf [file] [log] [blame]
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(conn_mgr, CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL);
#include <errno.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_mgmt.h>
#include "conn_mgr_private.h"
extern uint16_t iface_states[CONN_MGR_IFACE_MAX];
static struct net_mgmt_event_callback iface_events_cb;
static struct net_mgmt_event_callback ipv6_events_cb;
static struct net_mgmt_event_callback ipv4_events_cb;
static void conn_mgr_iface_events_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
int idx;
NET_DBG("Iface event %u received on iface %d (%p)", mgmt_event,
net_if_get_by_iface(iface), iface);
if ((mgmt_event & CONN_MGR_IFACE_EVENTS_MASK) != mgmt_event) {
return;
}
idx = net_if_get_by_iface(iface) - 1;
NET_DBG("Iface index %u", idx);
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
case NET_EVENT_IF_CMD_DOWN:
iface_states[idx] &= ~CONN_MGR_IF_UP;
break;
case NET_EVENT_IF_CMD_UP:
iface_states[idx] |= CONN_MGR_IF_UP;
break;
default:
goto done;
}
iface_states[idx] |= CONN_MGR_IF_CHANGED;
k_sem_give(&conn_mgr_event_signal);
done:
k_mutex_unlock(&conn_mgr_lock);
}
#if defined(CONFIG_NET_IPV6)
static void conn_mgr_ipv6_events_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
int idx;
NET_DBG("IPv6 event %u received on iface %d (%p)", mgmt_event,
net_if_get_by_iface(iface), iface);
if ((mgmt_event & CONN_MGR_IPV6_EVENTS_MASK) != mgmt_event) {
return;
}
idx = net_if_get_by_iface(iface) - 1;
NET_DBG("Iface index %u", idx);
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
case NET_EVENT_IPV6_CMD_DAD_SUCCEED:
__fallthrough;
case NET_EVENT_IPV6_CMD_ADDR_ADD:
if (net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
iface_states[idx] |= CONN_MGR_IF_IPV6_SET;
}
break;
case NET_EVENT_IPV6_CMD_DAD_FAILED:
__fallthrough;
case NET_EVENT_IPV6_CMD_ADDR_DEL:
if (!net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
iface_states[idx] &= ~CONN_MGR_IF_IPV6_SET;
}
break;
default:
goto done;
}
iface_states[idx] |= CONN_MGR_IF_CHANGED;
k_sem_give(&conn_mgr_event_signal);
done:
k_mutex_unlock(&conn_mgr_lock);
}
#else
static inline
void conn_mgr_ipv6_events_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
ARG_UNUSED(cb);
ARG_UNUSED(mgmt_event);
ARG_UNUSED(iface);
}
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
static void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
int idx;
NET_DBG("IPv4 event %u received on iface %d (%p)", mgmt_event,
net_if_get_by_iface(iface), iface);
if ((mgmt_event & CONN_MGR_IPV4_EVENTS_MASK) != mgmt_event) {
return;
}
idx = net_if_get_by_iface(iface) - 1;
NET_DBG("Iface index %u", idx);
k_mutex_lock(&conn_mgr_lock, K_FOREVER);
switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
case NET_EVENT_IPV4_CMD_ADDR_ADD:
iface_states[idx] |= CONN_MGR_IF_IPV4_SET;
break;
case NET_EVENT_IPV4_CMD_ADDR_DEL:
if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) {
break;
}
iface_states[idx] &= ~CONN_MGR_IF_IPV4_SET;
break;
default:
goto done;
}
iface_states[idx] |= CONN_MGR_IF_CHANGED;
k_sem_give(&conn_mgr_event_signal);
done:
k_mutex_unlock(&conn_mgr_lock);
}
#else
static inline
void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
ARG_UNUSED(cb);
ARG_UNUSED(mgmt_event);
ARG_UNUSED(iface);
}
#endif /* CONFIG_NET_IPV4 */
void conn_mgr_init_events_handler(void)
{
net_mgmt_init_event_callback(&iface_events_cb,
conn_mgr_iface_events_handler,
CONN_MGR_IFACE_EVENTS_MASK);
net_mgmt_add_event_callback(&iface_events_cb);
if (IS_ENABLED(CONFIG_NET_IPV6)) {
net_mgmt_init_event_callback(&ipv6_events_cb,
conn_mgr_ipv6_events_handler,
CONN_MGR_IPV6_EVENTS_MASK);
net_mgmt_add_event_callback(&ipv6_events_cb);
}
if (IS_ENABLED(CONFIG_NET_IPV4)) {
net_mgmt_init_event_callback(&ipv4_events_cb,
conn_mgr_ipv4_events_handler,
CONN_MGR_IPV4_EVENTS_MASK);
net_mgmt_add_event_callback(&ipv4_events_cb);
}
}