zephyr/subsys/net/l2/openthread/openthread_utils.h
Robert Lubos 7acafda858 net: openthread: Fix possible deadlock in net_mgmt handlers
There is a risk of deadlock in case net_if APIs are used from within
net_mgmt handlers as both module APIs are protected with their own
mutexes.

The scenario observed with OpenThread happend when
NET_EVENT_IPV6_ADDR_ADD/NET_EVENT_IPV6_MADDR_ADD events were processed.
The net_mgmt mutex is locked when both, an event handler is being
processed (from a separate net_mgmt thread) and when an event is raised
(for example when a new address is added on an interface). In case a
net_mgmt handler tried to use some mutex-protected net_if API, we could
end up in a deadlock situation - the net_mgmt would wait for the net_if
mutex to release, while some other thread (in this case main during
initialization) could wait within some net_if function, pending on
net_mgmt mutex to be released to notify the event.

Fix this, by preventing net_if APIs from being used from within OT
net_mgmt handlers.

Additionally, simplify the net_mgmt handlers logic, by making use of
additional info provided with an event. Instead of blindy assuming that
recently added address was the last on the list (which might not always
be the case, if addresses are added/removed dynamically), read the
actual address being added from the net_mgmt_event_callback structure.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
2022-05-11 11:03:26 +02:00

46 lines
1.3 KiB
C

/*
* Copyright (c) 2018 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __OPENTHREAD_UTILS_H__
#define __OPENTHREAD_UTILS_H__
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_15_4) || \
defined(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)
void dump_pkt(const char *str, struct net_pkt *pkt);
#else
#define dump_pkt(...)
#endif
void add_ipv6_addr_to_zephyr(struct openthread_context *context);
void add_ipv6_addr_to_ot(struct openthread_context *context,
const struct in6_addr *addr6);
void add_ipv6_maddr_to_ot(struct openthread_context *context,
const struct in6_addr *addr6);
void add_ipv6_maddr_to_zephyr(struct openthread_context *context);
void rm_ipv6_addr_from_zephyr(struct openthread_context *context);
void rm_ipv6_maddr_from_zephyr(struct openthread_context *context);
int pkt_list_add(struct openthread_context *context, struct net_pkt *pkt);
struct net_pkt *pkt_list_peek(struct openthread_context *context);
void pkt_list_remove_last(struct openthread_context *context);
void pkt_list_remove_first(struct openthread_context *context);
static inline int pkt_list_is_full(struct openthread_context *context)
{
return context->pkt_list_full;
}
#ifdef __cplusplus
}
#endif
#endif /* __OPENTHREAD_UTILS_H__ */