1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
9 
10 #include <zephyr/net/net_core.h>
11 #include <zephyr/net/net_pkt.h>
12 #include <zephyr/net/net_mgmt.h>
13 #include <zephyr/net/openthread.h>
14 
15 #include <net_private.h>
16 
17 #include <zephyr/init.h>
18 #include <zephyr/sys/check.h>
19 #include <zephyr/sys/slist.h>
20 #include <zephyr/sys/util.h>
21 #include <zephyr/sys/__assert.h>
22 #include <zephyr/version.h>
23 
24 #include <openthread/child_supervision.h>
25 #include <openthread/cli.h>
26 #include <openthread/ip6.h>
27 #include <openthread/link.h>
28 #include <openthread/link_raw.h>
29 #include <openthread/ncp.h>
30 #include <openthread/message.h>
31 #include <openthread/platform/diag.h>
32 #include <openthread/tasklet.h>
33 #include <openthread/thread.h>
34 #include <openthread/dataset.h>
35 #include <openthread/joiner.h>
36 #include <openthread-system.h>
37 #include <utils/uart.h>
38 
39 #include <platform-zephyr.h>
40 
41 #include "openthread_utils.h"
42 
43 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
44 #include <openthread/nat64.h>
45 #endif  /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
46 
47 #define PKT_IS_IPv4(_p) ((NET_IPV6_HDR(_p)->vtc & 0xf0) == 0x40)
48 
49 #define OT_STACK_SIZE (CONFIG_OPENTHREAD_THREAD_STACK_SIZE)
50 
51 #if defined(CONFIG_OPENTHREAD_THREAD_PREEMPTIVE)
52 #define OT_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_THREAD_PRIORITY)
53 #else
54 #define OT_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
55 #endif
56 
57 #if defined(CONFIG_OPENTHREAD_NETWORK_NAME)
58 #define OT_NETWORK_NAME CONFIG_OPENTHREAD_NETWORK_NAME
59 #else
60 #define OT_NETWORK_NAME ""
61 #endif
62 
63 #if defined(CONFIG_OPENTHREAD_CHANNEL)
64 #define OT_CHANNEL CONFIG_OPENTHREAD_CHANNEL
65 #else
66 #define OT_CHANNEL 0
67 #endif
68 
69 #if defined(CONFIG_OPENTHREAD_PANID)
70 #define OT_PANID CONFIG_OPENTHREAD_PANID
71 #else
72 #define OT_PANID 0
73 #endif
74 
75 #if defined(CONFIG_OPENTHREAD_XPANID)
76 #define OT_XPANID CONFIG_OPENTHREAD_XPANID
77 #else
78 #define OT_XPANID ""
79 #endif
80 
81 #if defined(CONFIG_OPENTHREAD_NETWORKKEY)
82 #define OT_NETWORKKEY CONFIG_OPENTHREAD_NETWORKKEY
83 #else
84 #define OT_NETWORKKEY ""
85 #endif
86 
87 #if defined(CONFIG_OPENTHREAD_JOINER_PSKD)
88 #define OT_JOINER_PSKD CONFIG_OPENTHREAD_JOINER_PSKD
89 #else
90 #define OT_JOINER_PSKD ""
91 #endif
92 
93 #if defined(CONFIG_OPENTHREAD_PLATFORM_INFO)
94 #define OT_PLATFORM_INFO CONFIG_OPENTHREAD_PLATFORM_INFO
95 #else
96 #define OT_PLATFORM_INFO ""
97 #endif
98 
99 #if defined(CONFIG_OPENTHREAD_POLL_PERIOD)
100 #define OT_POLL_PERIOD CONFIG_OPENTHREAD_POLL_PERIOD
101 #else
102 #define OT_POLL_PERIOD 0
103 #endif
104 
105 #define ZEPHYR_PACKAGE_NAME "Zephyr"
106 #define PACKAGE_VERSION KERNEL_VERSION_STRING
107 
108 extern void platformShellInit(otInstance *aInstance);
109 
110 K_KERNEL_STACK_DEFINE(ot_stack_area, OT_STACK_SIZE);
111 
112 static struct net_linkaddr *ll_addr;
113 static otStateChangedCallback state_changed_cb;
114 
openthread_thread_id_get(void)115 k_tid_t openthread_thread_id_get(void)
116 {
117 	struct openthread_context *ot_context = openthread_get_default_context();
118 
119 	return ot_context ? (k_tid_t)&ot_context->work_q.thread : 0;
120 }
121 
122 #ifdef CONFIG_NET_MGMT_EVENT
123 static struct net_mgmt_event_callback ip6_addr_cb;
124 
ipv6_addr_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)125 static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb,
126 				    uint32_t mgmt_event, struct net_if *iface)
127 {
128 	if (net_if_l2(iface) != &NET_L2_GET_NAME(OPENTHREAD)) {
129 		return;
130 	}
131 
132 #ifdef CONFIG_NET_MGMT_EVENT_INFO
133 	struct openthread_context *ot_context = net_if_l2_data(iface);
134 
135 	if (cb->info == NULL || cb->info_length != sizeof(struct in6_addr)) {
136 		return;
137 	}
138 
139 	if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
140 		add_ipv6_addr_to_ot(ot_context, (const struct in6_addr *)cb->info);
141 	} else if (mgmt_event == NET_EVENT_IPV6_MADDR_ADD) {
142 		add_ipv6_maddr_to_ot(ot_context, (const struct in6_addr *)cb->info);
143 	}
144 #else
145 	NET_WARN("No address info provided with event, "
146 		 "please enable CONFIG_NET_MGMT_EVENT_INFO");
147 #endif /* CONFIG_NET_MGMT_EVENT_INFO */
148 }
149 #endif /* CONFIG_NET_MGMT_EVENT */
150 
ncp_hdlc_send(const uint8_t * buf,uint16_t len)151 static int ncp_hdlc_send(const uint8_t *buf, uint16_t len)
152 {
153 	otError err;
154 
155 	err = otPlatUartSend(buf, len);
156 	if (err != OT_ERROR_NONE) {
157 		return 0;
158 	}
159 
160 	return len;
161 }
162 
163 #ifndef CONFIG_HDLC_RCP_IF
otPlatRadioGetIeeeEui64(otInstance * instance,uint8_t * ieee_eui64)164 void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
165 {
166 	ARG_UNUSED(instance);
167 
168 	memcpy(ieee_eui64, ll_addr->addr, ll_addr->len);
169 }
170 #endif /* CONFIG_HDLC_RCP_IF */
171 
otTaskletsSignalPending(otInstance * instance)172 void otTaskletsSignalPending(otInstance *instance)
173 {
174 	struct openthread_context *ot_context = openthread_get_default_context();
175 
176 	if (ot_context) {
177 		k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
178 	}
179 }
180 
otSysEventSignalPending(void)181 void otSysEventSignalPending(void)
182 {
183 	otTaskletsSignalPending(NULL);
184 }
185 
ot_state_changed_handler(uint32_t flags,void * context)186 static void ot_state_changed_handler(uint32_t flags, void *context)
187 {
188 	struct openthread_state_changed_cb *entry, *next;
189 	struct openthread_context *ot_context = context;
190 
191 	NET_INFO("State changed! Flags: 0x%08" PRIx32 " Current role: %s",
192 		flags,
193 		otThreadDeviceRoleToString(otThreadGetDeviceRole(ot_context->instance))
194 		);
195 
196 	if (flags & OT_CHANGED_THREAD_ROLE) {
197 		switch (otThreadGetDeviceRole(ot_context->instance)) {
198 		case OT_DEVICE_ROLE_CHILD:
199 		case OT_DEVICE_ROLE_ROUTER:
200 		case OT_DEVICE_ROLE_LEADER:
201 			net_if_dormant_off(ot_context->iface);
202 			break;
203 
204 		case OT_DEVICE_ROLE_DISABLED:
205 		case OT_DEVICE_ROLE_DETACHED:
206 		default:
207 			net_if_dormant_on(ot_context->iface);
208 			break;
209 		}
210 	}
211 
212 	if (flags & OT_CHANGED_IP6_ADDRESS_REMOVED) {
213 		NET_DBG("Ipv6 address removed");
214 		rm_ipv6_addr_from_zephyr(ot_context);
215 	}
216 
217 	if (flags & OT_CHANGED_IP6_ADDRESS_ADDED) {
218 		NET_DBG("Ipv6 address added");
219 		add_ipv6_addr_to_zephyr(ot_context);
220 	}
221 
222 	if (flags & OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED) {
223 		NET_DBG("Ipv6 multicast address removed");
224 		rm_ipv6_maddr_from_zephyr(ot_context);
225 	}
226 
227 	if (flags & OT_CHANGED_IP6_MULTICAST_SUBSCRIBED) {
228 		NET_DBG("Ipv6 multicast address added");
229 		add_ipv6_maddr_to_zephyr(ot_context);
230 	}
231 
232 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
233 
234 	if (flags & OT_CHANGED_NAT64_TRANSLATOR_STATE) {
235 		NET_DBG("Nat64 translator state changed to %x",
236 			otNat64GetTranslatorState(ot_context->instance));
237 	}
238 
239 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
240 
241 	if (state_changed_cb) {
242 		state_changed_cb(flags, context);
243 	}
244 
245 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ot_context->state_change_cbs, entry, next, node) {
246 		if (entry->state_changed_cb != NULL) {
247 			entry->state_changed_cb(flags, ot_context, entry->user_data);
248 		}
249 	}
250 }
251 
ot_receive_handler(otMessage * aMessage,void * context)252 static void ot_receive_handler(otMessage *aMessage, void *context)
253 {
254 	struct openthread_context *ot_context = context;
255 
256 	uint16_t offset = 0U;
257 	uint16_t read_len;
258 	struct net_pkt *pkt;
259 	struct net_buf *pkt_buf;
260 
261 	pkt = net_pkt_rx_alloc_with_buffer(ot_context->iface,
262 					   otMessageGetLength(aMessage),
263 					   AF_UNSPEC, 0, K_NO_WAIT);
264 	if (!pkt) {
265 		NET_ERR("Failed to reserve net pkt");
266 		goto out;
267 	}
268 
269 	pkt_buf = pkt->buffer;
270 
271 	while (1) {
272 		read_len = otMessageRead(aMessage, offset, pkt_buf->data,
273 					 net_buf_tailroom(pkt_buf));
274 		if (!read_len) {
275 			break;
276 		}
277 
278 		net_buf_add(pkt_buf, read_len);
279 
280 		offset += read_len;
281 
282 		if (!net_buf_tailroom(pkt_buf)) {
283 			pkt_buf = pkt_buf->frags;
284 			if (!pkt_buf) {
285 				break;
286 			}
287 		}
288 	}
289 
290 	NET_DBG("Injecting %s packet to Zephyr net stack",
291 		PKT_IS_IPv4(pkt) ? "translated IPv4" : "Ip6");
292 
293 	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
294 		if (IS_ENABLED(CONFIG_OPENTHREAD_NAT64_TRANSLATOR) && PKT_IS_IPv4(pkt)) {
295 			net_pkt_hexdump(pkt, "Received NAT64 IPv4 packet");
296 		} else {
297 			net_pkt_hexdump(pkt, "Received IPv6 packet");
298 		}
299 	}
300 
301 	if (!pkt_list_is_full(ot_context)) {
302 		if (pkt_list_add(ot_context, pkt) != 0) {
303 			NET_ERR("pkt_list_add failed");
304 			goto out;
305 		}
306 
307 		if (net_recv_data(ot_context->iface, pkt) < 0) {
308 			NET_ERR("net_recv_data failed");
309 			pkt_list_remove_first(ot_context);
310 			goto out;
311 		}
312 
313 		pkt = NULL;
314 	} else {
315 		NET_INFO("Packet list is full");
316 	}
317 out:
318 	if (pkt) {
319 		net_pkt_unref(pkt);
320 	}
321 
322 	otMessageFree(aMessage);
323 }
324 
ot_joiner_start_handler(otError error,void * context)325 static void ot_joiner_start_handler(otError error, void *context)
326 {
327 	struct openthread_context *ot_context = context;
328 
329 	switch (error) {
330 	case OT_ERROR_NONE:
331 		NET_INFO("Join success");
332 		otThreadSetEnabled(ot_context->instance, true);
333 		break;
334 	default:
335 		NET_ERR("Join failed [%d]", error);
336 		break;
337 	}
338 }
339 
openthread_process(struct k_work * work)340 static void openthread_process(struct k_work *work)
341 {
342 	struct openthread_context *ot_context
343 		= CONTAINER_OF(work, struct openthread_context, api_work);
344 
345 	openthread_api_mutex_lock(ot_context);
346 
347 	while (otTaskletsArePending(ot_context->instance)) {
348 		otTaskletsProcess(ot_context->instance);
349 	}
350 
351 	otSysProcessDrivers(ot_context->instance);
352 
353 	openthread_api_mutex_unlock(ot_context);
354 }
355 
is_ipv6_frag(struct net_pkt * pkt)356 static bool is_ipv6_frag(struct net_pkt *pkt)
357 {
358 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
359 	struct net_ipv6_hdr *hdr;
360 
361 	hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
362 	if (!hdr) {
363 		return false;
364 	}
365 
366 	return hdr->nexthdr == NET_IPV6_NEXTHDR_FRAG ? true : false;
367 }
368 
openthread_recv(struct net_if * iface,struct net_pkt * pkt)369 static enum net_verdict openthread_recv(struct net_if *iface, struct net_pkt *pkt)
370 {
371 	struct openthread_context *ot_context = net_if_l2_data(iface);
372 
373 	if (pkt_list_peek(ot_context) == pkt) {
374 		pkt_list_remove_last(ot_context);
375 		NET_DBG("Got injected Ip6 packet, sending to upper layers");
376 
377 		if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
378 			net_pkt_hexdump(pkt, "Injected IPv6 packet");
379 		}
380 
381 		if (IS_ENABLED(CONFIG_OPENTHREAD_IP6_FRAGM) && is_ipv6_frag(pkt)) {
382 			return NET_DROP;
383 		}
384 
385 		return NET_CONTINUE;
386 	}
387 
388 	NET_DBG("Got 802.15.4 packet, sending to OT");
389 
390 	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
391 		net_pkt_hexdump(pkt, "Received 802.15.4 frame");
392 	}
393 
394 	if (notify_new_rx_frame(pkt) != 0) {
395 		NET_ERR("Failed to queue RX packet for OpenThread");
396 		return NET_DROP;
397 	}
398 
399 	return NET_OK;
400 }
401 
openthread_send(struct net_if * iface,struct net_pkt * pkt)402 int openthread_send(struct net_if *iface, struct net_pkt *pkt)
403 {
404 	int len = net_pkt_get_len(pkt);
405 
406 	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
407 		net_pkt_hexdump(pkt, "IPv6 packet to send");
408 	}
409 
410 	net_capture_pkt(iface, pkt);
411 
412 	if (notify_new_tx_frame(pkt) != 0) {
413 		net_pkt_unref(pkt);
414 	}
415 
416 	return len;
417 }
418 
openthread_start(struct openthread_context * ot_context)419 int openthread_start(struct openthread_context *ot_context)
420 {
421 	otInstance *ot_instance = ot_context->instance;
422 	otError error = OT_ERROR_NONE;
423 
424 	openthread_api_mutex_lock(ot_context);
425 
426 	NET_INFO("OpenThread version: %s", otGetVersionString());
427 
428 	if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
429 		NET_DBG("OpenThread co-processor.");
430 		goto exit;
431 	}
432 
433 	otIp6SetEnabled(ot_context->instance, true);
434 
435 	/* Sleepy End Device specific configuration. */
436 	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
437 		otLinkModeConfig ot_mode = otThreadGetLinkMode(ot_instance);
438 
439 		/* A SED should always attach the network as a SED to indicate
440 		 * increased buffer requirement to a parent.
441 		 */
442 		ot_mode.mRxOnWhenIdle = false;
443 
444 		otThreadSetLinkMode(ot_context->instance, ot_mode);
445 		otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD);
446 	}
447 
448 	/* Configure Child Supervision and MLE Child timeouts. */
449 	otChildSupervisionSetInterval(ot_context->instance,
450 				      CONFIG_OPENTHREAD_CHILD_SUPERVISION_INTERVAL);
451 	otChildSupervisionSetCheckTimeout(ot_context->instance,
452 					  CONFIG_OPENTHREAD_CHILD_SUPERVISION_CHECK_TIMEOUT);
453 	otThreadSetChildTimeout(ot_context->instance, CONFIG_OPENTHREAD_MLE_CHILD_TIMEOUT);
454 
455 	if (otDatasetIsCommissioned(ot_instance)) {
456 		/* OpenThread already has dataset stored - skip the
457 		 * configuration.
458 		 */
459 		NET_DBG("OpenThread already commissioned.");
460 	} else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
461 		/* No dataset - initiate network join procedure. */
462 		NET_DBG("Starting OpenThread join procedure.");
463 
464 		error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL, ZEPHYR_PACKAGE_NAME,
465 				      OT_PLATFORM_INFO, PACKAGE_VERSION, NULL,
466 				      &ot_joiner_start_handler, ot_context);
467 
468 		if (error != OT_ERROR_NONE) {
469 			NET_ERR("Failed to start joiner [%d]", error);
470 		}
471 
472 		goto exit;
473 	} else {
474 		/* No dataset - load the default configuration. */
475 		NET_DBG("Loading OpenThread default configuration.");
476 
477 		otExtendedPanId xpanid;
478 		otNetworkKey    networkKey;
479 
480 		otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME);
481 		otLinkSetChannel(ot_instance, OT_CHANNEL);
482 		otLinkSetPanId(ot_instance, OT_PANID);
483 		net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID);
484 		otThreadSetExtendedPanId(ot_instance, &xpanid);
485 
486 		if (strlen(OT_NETWORKKEY)) {
487 			net_bytes_from_str(networkKey.m8, OT_NETWORK_KEY_SIZE,
488 					   (char *)OT_NETWORKKEY);
489 			otThreadSetNetworkKey(ot_instance, &networkKey);
490 		}
491 	}
492 
493 	NET_INFO("Network name: %s",
494 		 otThreadGetNetworkName(ot_instance));
495 
496 	/* Start the network. */
497 	error = otThreadSetEnabled(ot_instance, true);
498 	if (error != OT_ERROR_NONE) {
499 		NET_ERR("Failed to start the OpenThread network [%d]", error);
500 	}
501 
502 exit:
503 
504 	openthread_api_mutex_unlock(ot_context);
505 
506 	return error == OT_ERROR_NONE ? 0 : -EIO;
507 }
508 
openthread_stop(struct openthread_context * ot_context)509 int openthread_stop(struct openthread_context *ot_context)
510 {
511 	otError error;
512 
513 	if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
514 		return 0;
515 	}
516 
517 	openthread_api_mutex_lock(ot_context);
518 
519 	error = otThreadSetEnabled(ot_context->instance, false);
520 	if (error == OT_ERROR_INVALID_STATE) {
521 		NET_DBG("Openthread interface was not up [%d]", error);
522 	}
523 
524 	openthread_api_mutex_unlock(ot_context);
525 
526 	return 0;
527 }
528 
openthread_init(struct net_if * iface)529 static int openthread_init(struct net_if *iface)
530 {
531 	struct openthread_context *ot_context = net_if_l2_data(iface);
532 	struct k_work_queue_config q_cfg = {
533 		.name = "openthread",
534 		.no_yield = true,
535 	};
536 	otError err;
537 
538 	NET_DBG("openthread_init");
539 
540 	k_mutex_init(&ot_context->api_lock);
541 	k_work_init(&ot_context->api_work, openthread_process);
542 
543 	ll_addr = net_if_get_link_addr(iface);
544 
545 	openthread_api_mutex_lock(ot_context);
546 
547 	otSysInit(0, NULL);
548 
549 	ot_context->instance = otInstanceInitSingle();
550 	ot_context->iface = iface;
551 
552 	__ASSERT(ot_context->instance, "OT instance is NULL");
553 
554 	if (IS_ENABLED(CONFIG_OPENTHREAD_SHELL)) {
555 		platformShellInit(ot_context->instance);
556 	}
557 
558 	if (IS_ENABLED(CONFIG_OPENTHREAD_COPROCESSOR)) {
559 		otPlatUartEnable();
560 		otNcpHdlcInit(ot_context->instance, ncp_hdlc_send);
561 	} else {
562 		otIp6SetReceiveFilterEnabled(ot_context->instance, true);
563 		otIp6SetReceiveCallback(ot_context->instance,
564 					ot_receive_handler, ot_context);
565 
566 #if defined(CONFIG_OPENTHREAD_NAT64_TRANSLATOR)
567 
568 		otIp4Cidr nat64_cidr;
569 
570 		if (otIp4CidrFromString(CONFIG_OPENTHREAD_NAT64_CIDR, &nat64_cidr) ==
571 		    OT_ERROR_NONE) {
572 			if (otNat64SetIp4Cidr(openthread_get_default_instance(), &nat64_cidr) !=
573 			    OT_ERROR_NONE) {
574 				NET_ERR("Incorrect NAT64 CIDR");
575 			}
576 		} else {
577 			NET_ERR("Failed to parse NAT64 CIDR");
578 		}
579 		otNat64SetReceiveIp4Callback(ot_context->instance, ot_receive_handler, ot_context);
580 
581 #endif /* CONFIG_OPENTHREAD_NAT64_TRANSLATOR */
582 
583 		sys_slist_init(&ot_context->state_change_cbs);
584 		err = otSetStateChangedCallback(ot_context->instance,
585 						&ot_state_changed_handler,
586 						ot_context);
587 		if (err != OT_ERROR_NONE) {
588 			NET_ERR("Could not set state changed callback: %d", err);
589 		}
590 
591 		net_mgmt_init_event_callback(
592 			&ip6_addr_cb, ipv6_addr_event_handler,
593 			NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_MADDR_ADD);
594 		net_mgmt_add_event_callback(&ip6_addr_cb);
595 
596 		net_if_dormant_on(iface);
597 	}
598 
599 	openthread_api_mutex_unlock(ot_context);
600 
601 	k_work_queue_start(&ot_context->work_q, ot_stack_area,
602 			   K_KERNEL_STACK_SIZEOF(ot_stack_area),
603 			   OT_PRIORITY, &q_cfg);
604 
605 	(void)k_work_submit_to_queue(&ot_context->work_q, &ot_context->api_work);
606 
607 	return 0;
608 }
609 
ieee802154_init(struct net_if * iface)610 void ieee802154_init(struct net_if *iface)
611 {
612 	if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) {
613 		LOG_DBG("Interface auto start disabled.");
614 		net_if_flag_set(iface, NET_IF_NO_AUTO_START);
615 	}
616 
617 	net_if_flag_set(iface, NET_IF_IPV6_NO_ND);
618 	net_if_flag_set(iface, NET_IF_IPV6_NO_MLD);
619 
620 	openthread_init(iface);
621 }
622 
openthread_flags(struct net_if * iface)623 static enum net_l2_flags openthread_flags(struct net_if *iface)
624 {
625 	/* TODO: Should report NET_L2_PROMISC_MODE if the radio driver
626 	 *       reports the IEEE802154_HW_PROMISC capability.
627 	 */
628 	return NET_L2_MULTICAST | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE;
629 }
630 
openthread_enable(struct net_if * iface,bool state)631 static int openthread_enable(struct net_if *iface, bool state)
632 {
633 	struct openthread_context *ot_context = net_if_l2_data(iface);
634 
635 	NET_DBG("iface %p %s", iface, state ? "up" : "down");
636 
637 	if (state) {
638 		if (IS_ENABLED(CONFIG_OPENTHREAD_MANUAL_START)) {
639 			NET_DBG("OpenThread manual start.");
640 			return 0;
641 		}
642 
643 		return openthread_start(ot_context);
644 	}
645 
646 	return openthread_stop(ot_context);
647 }
648 
openthread_get_default_context(void)649 struct openthread_context *openthread_get_default_context(void)
650 {
651 	struct net_if *iface;
652 	struct openthread_context *ot_context = NULL;
653 
654 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(OPENTHREAD));
655 	if (!iface) {
656 		NET_ERR("There is no net interface for OpenThread");
657 		goto exit;
658 	}
659 
660 	ot_context = net_if_l2_data(iface);
661 	if (!ot_context) {
662 		NET_ERR("There is no Openthread context in net interface data");
663 		goto exit;
664 	}
665 
666 exit:
667 	return ot_context;
668 }
669 
openthread_get_default_instance(void)670 struct otInstance *openthread_get_default_instance(void)
671 {
672 	struct openthread_context *ot_context =
673 		openthread_get_default_context();
674 
675 	return ot_context ? ot_context->instance : NULL;
676 }
677 
openthread_state_changed_cb_register(struct openthread_context * ot_context,struct openthread_state_changed_cb * cb)678 int openthread_state_changed_cb_register(struct openthread_context *ot_context,
679 					 struct openthread_state_changed_cb *cb)
680 {
681 	CHECKIF(cb == NULL || cb->state_changed_cb == NULL) {
682 		return -EINVAL;
683 	}
684 
685 	openthread_api_mutex_lock(ot_context);
686 	sys_slist_append(&ot_context->state_change_cbs, &cb->node);
687 	openthread_api_mutex_unlock(ot_context);
688 
689 	return 0;
690 }
691 
openthread_state_changed_cb_unregister(struct openthread_context * ot_context,struct openthread_state_changed_cb * cb)692 int openthread_state_changed_cb_unregister(struct openthread_context *ot_context,
693 					   struct openthread_state_changed_cb *cb)
694 {
695 	bool removed;
696 
697 	CHECKIF(cb == NULL) {
698 		return -EINVAL;
699 	}
700 
701 	openthread_api_mutex_lock(ot_context);
702 	removed = sys_slist_find_and_remove(&ot_context->state_change_cbs, &cb->node);
703 	openthread_api_mutex_unlock(ot_context);
704 
705 	if (!removed) {
706 		return -EALREADY;
707 	}
708 
709 	return 0;
710 }
711 
openthread_set_state_changed_cb(otStateChangedCallback cb)712 void openthread_set_state_changed_cb(otStateChangedCallback cb)
713 {
714 	state_changed_cb = cb;
715 }
716 
openthread_api_mutex_lock(struct openthread_context * ot_context)717 void openthread_api_mutex_lock(struct openthread_context *ot_context)
718 {
719 	(void)k_mutex_lock(&ot_context->api_lock, K_FOREVER);
720 }
721 
openthread_api_mutex_try_lock(struct openthread_context * ot_context)722 int openthread_api_mutex_try_lock(struct openthread_context *ot_context)
723 {
724 	return k_mutex_lock(&ot_context->api_lock, K_NO_WAIT);
725 }
726 
openthread_api_mutex_unlock(struct openthread_context * ot_context)727 void openthread_api_mutex_unlock(struct openthread_context *ot_context)
728 {
729 	(void)k_mutex_unlock(&ot_context->api_lock);
730 }
731 
732 NET_L2_INIT(OPENTHREAD_L2, openthread_recv, openthread_send, openthread_enable,
733 	    openthread_flags);
734