1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief IEEE 802.15.4 MAC layer implementation
10  *
11  * All references to the spec refer to IEEE 802.15.4-2020.
12  */
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
16 
17 #include <errno.h>
18 
19 #include <zephyr/net/capture.h>
20 #include <zephyr/net/ethernet.h>
21 #include <zephyr/net/net_core.h>
22 #include <zephyr/net/net_if.h>
23 #include <zephyr/net/net_l2.h>
24 #include <zephyr/net/net_linkaddr.h>
25 #include <zephyr/random/random.h>
26 
27 #ifdef CONFIG_NET_6LO
28 #include "ieee802154_6lo.h"
29 
30 #include <6lo.h>
31 #include <ipv6.h>
32 
33 #ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
34 #include "ieee802154_6lo_fragment.h"
35 #endif /* CONFIG_NET_L2_IEEE802154_FRAGMENT */
36 #endif /* CONFIG_NET_6LO */
37 
38 #include "ieee802154_frame.h"
39 #include "ieee802154_mgmt_priv.h"
40 #include "ieee802154_priv.h"
41 #include "ieee802154_security.h"
42 #include "ieee802154_utils.h"
43 
44 #define BUF_TIMEOUT K_MSEC(50)
45 
46 NET_BUF_POOL_DEFINE(tx_frame_buf_pool, 1, IEEE802154_MTU, 8, NULL);
47 
48 #define PKT_TITLE    "IEEE 802.15.4 packet content:"
49 #define TX_PKT_TITLE "> " PKT_TITLE
50 #define RX_PKT_TITLE "< " PKT_TITLE
51 
52 #ifdef CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET
53 
54 #include "net_private.h"
55 
pkt_hexdump(const char * title,struct net_pkt * pkt,bool in)56 static inline void pkt_hexdump(const char *title, struct net_pkt *pkt, bool in)
57 {
58 	if (IS_ENABLED(CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_RX) && in) {
59 		net_pkt_hexdump(pkt, title);
60 	}
61 
62 	if (IS_ENABLED(CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_TX) && !in) {
63 		net_pkt_hexdump(pkt, title);
64 	}
65 }
66 
67 #else
68 #define pkt_hexdump(...)
69 #endif /* CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET */
70 
ieee802154_acknowledge(struct net_if * iface,struct ieee802154_mpdu * mpdu)71 static inline void ieee802154_acknowledge(struct net_if *iface, struct ieee802154_mpdu *mpdu)
72 {
73 	struct net_pkt *pkt;
74 
75 	if (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_RX_TX_ACK) {
76 		return;
77 	}
78 
79 	if (!mpdu->mhr.fs->fc.ar) {
80 		return;
81 	}
82 
83 	pkt = net_pkt_alloc_with_buffer(iface, IEEE802154_ACK_PKT_LENGTH, AF_UNSPEC, 0,
84 					BUF_TIMEOUT);
85 	if (!pkt) {
86 		return;
87 	}
88 
89 	if (ieee802154_create_ack_frame(iface, pkt, mpdu->mhr.fs->sequence)) {
90 		/* ACK frames must not use the CSMA/CA procedure, see section 6.2.5.1. */
91 		ieee802154_radio_tx(iface, IEEE802154_TX_MODE_DIRECT, pkt, pkt->buffer);
92 	}
93 
94 	net_pkt_unref(pkt);
95 
96 	return;
97 }
98 
ieee802154_prepare_for_ack(struct net_if * iface,struct net_pkt * pkt,struct net_buf * frag)99 inline bool ieee802154_prepare_for_ack(struct net_if *iface, struct net_pkt *pkt,
100 				       struct net_buf *frag)
101 {
102 	bool ack_required = ieee802154_is_ar_flag_set(frag);
103 
104 	if (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_TX_RX_ACK) {
105 		return ack_required;
106 	}
107 
108 	if (ack_required) {
109 		struct ieee802154_fcf_seq *fs = (struct ieee802154_fcf_seq *)frag->data;
110 		struct ieee802154_context *ctx = net_if_l2_data(iface);
111 
112 		ctx->ack_seq = fs->sequence;
113 		if (k_sem_count_get(&ctx->ack_lock) == 1U) {
114 			k_sem_take(&ctx->ack_lock, K_NO_WAIT);
115 		}
116 
117 		return true;
118 	}
119 
120 	return false;
121 }
122 
ieee802154_handle_ack(struct net_if * iface,struct net_pkt * pkt)123 enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt)
124 {
125 	struct ieee802154_context *ctx = net_if_l2_data(iface);
126 
127 	if (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_TX_RX_ACK) {
128 		__ASSERT_NO_MSG(ctx->ack_seq == 0U);
129 		/* TODO: Release packet in L2 as we're taking ownership. */
130 		return NET_OK;
131 	}
132 
133 	if (pkt->buffer->len == IEEE802154_ACK_PKT_LENGTH) {
134 		uint8_t len = IEEE802154_ACK_PKT_LENGTH;
135 		struct ieee802154_fcf_seq *fs;
136 
137 		fs = ieee802154_validate_fc_seq(net_pkt_data(pkt), NULL, &len);
138 		if (!fs || fs->fc.frame_type != IEEE802154_FRAME_TYPE_ACK ||
139 		    fs->sequence != ctx->ack_seq) {
140 			return NET_CONTINUE;
141 		}
142 
143 		k_sem_give(&ctx->ack_lock);
144 
145 		/* TODO: Release packet in L2 as we're taking ownership. */
146 		return NET_OK;
147 	}
148 
149 	return NET_CONTINUE;
150 }
151 
ieee802154_wait_for_ack(struct net_if * iface,bool ack_required)152 inline int ieee802154_wait_for_ack(struct net_if *iface, bool ack_required)
153 {
154 	struct ieee802154_context *ctx = net_if_l2_data(iface);
155 	int ret;
156 
157 	if (!ack_required ||
158 	    (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_TX_RX_ACK)) {
159 		__ASSERT_NO_MSG(ctx->ack_seq == 0U);
160 		return 0;
161 	}
162 
163 	ret = k_sem_take(&ctx->ack_lock, K_MSEC(10));
164 	if (ret == 0) {
165 		/* no-op */
166 	} else if (ret == -EAGAIN) {
167 		ret = -ETIME;
168 	} else {
169 		NET_ERR("Error while waiting for ACK.");
170 		ret = -EFAULT;
171 	}
172 
173 	ctx->ack_seq = 0U;
174 	return ret;
175 }
176 
ieee802154_radio_send(struct net_if * iface,struct net_pkt * pkt,struct net_buf * frag)177 int ieee802154_radio_send(struct net_if *iface, struct net_pkt *pkt, struct net_buf *frag)
178 {
179 	uint8_t remaining_attempts = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES + 1;
180 	bool hw_csma, ack_required;
181 	int ret;
182 
183 	NET_DBG("frag %p", frag);
184 
185 	if (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_RETRANSMISSION) {
186 		/* A driver that claims retransmission capability must also be able
187 		 * to wait for ACK frames otherwise it could not decide whether or
188 		 * not retransmission is required in a standard conforming way.
189 		 */
190 		__ASSERT_NO_MSG(ieee802154_radio_get_hw_capabilities(iface) &
191 				IEEE802154_HW_TX_RX_ACK);
192 		remaining_attempts = 1;
193 	}
194 
195 	hw_csma = IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
196 		  ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_CSMA;
197 
198 	/* Media access (CSMA, ALOHA, ...) and retransmission, see section 6.7.4.4. */
199 	while (remaining_attempts) {
200 		if (!hw_csma) {
201 			ret = ieee802154_wait_for_clear_channel(iface);
202 			if (ret != 0) {
203 				NET_WARN("Clear channel assessment failed: dropping fragment %p on "
204 					 "interface %p.",
205 					 frag, iface);
206 				return ret;
207 			}
208 		}
209 
210 		/* No-op in case the driver has IEEE802154_HW_TX_RX_ACK capability. */
211 		ack_required = ieee802154_prepare_for_ack(iface, pkt, frag);
212 
213 		/* TX including:
214 		 *  - CSMA/CA in case the driver has IEEE802154_HW_CSMA capability,
215 		 *  - waiting for ACK in case the driver has IEEE802154_HW_TX_RX_ACK capability,
216 		 *  - retransmission on ACK timeout in case the driver has
217 		 *    IEEE802154_HW_RETRANSMISSION capability.
218 		 */
219 		ret = ieee802154_radio_tx(
220 			iface, hw_csma ? IEEE802154_TX_MODE_CSMA_CA : IEEE802154_TX_MODE_DIRECT,
221 			pkt, frag);
222 		if (ret) {
223 			/* Transmission failure. */
224 			return ret;
225 		}
226 
227 		if (!ack_required) {
228 			/* See section 6.7.4.4: "A device that sends a frame with the AR field set
229 			 * to indicate no acknowledgment requested may assume that the transmission
230 			 * was successfully received and shall not perform the retransmission
231 			 * procedure."
232 			 */
233 			return 0;
234 		}
235 
236 
237 		/* No-op in case the driver has IEEE802154_HW_TX_RX_ACK capability. */
238 		ret = ieee802154_wait_for_ack(iface, ack_required);
239 		if (ret == 0) {
240 			/* ACK received - transmission is successful. */
241 			return 0;
242 		}
243 
244 		remaining_attempts--;
245 	}
246 
247 	return -EIO;
248 }
249 
swap_and_set_pkt_ll_addr(struct net_linkaddr * addr,bool has_pan_id,enum ieee802154_addressing_mode mode,struct ieee802154_address_field * ll)250 static inline void swap_and_set_pkt_ll_addr(struct net_linkaddr *addr, bool has_pan_id,
251 					    enum ieee802154_addressing_mode mode,
252 					    struct ieee802154_address_field *ll)
253 {
254 	addr->type = NET_LINK_IEEE802154;
255 
256 	switch (mode) {
257 	case IEEE802154_ADDR_MODE_EXTENDED:
258 		addr->len = IEEE802154_EXT_ADDR_LENGTH;
259 		addr->addr = has_pan_id ? ll->plain.addr.ext_addr : ll->comp.addr.ext_addr;
260 		break;
261 
262 	case IEEE802154_ADDR_MODE_SHORT:
263 		addr->len = IEEE802154_SHORT_ADDR_LENGTH;
264 		addr->addr = (uint8_t *)(has_pan_id ? &ll->plain.addr.short_addr
265 						    : &ll->comp.addr.short_addr);
266 		break;
267 
268 	case IEEE802154_ADDR_MODE_NONE:
269 	default:
270 		addr->len = 0U;
271 		addr->addr = NULL;
272 	}
273 
274 	/* The net stack expects big endian link layer addresses for POSIX compliance
275 	 * so we must swap it. This is ok as the L2 address field points into the L2
276 	 * header of the frame buffer which will no longer be accessible once the
277 	 * packet reaches upper layers.
278 	 */
279 	if (addr->len > 0) {
280 		sys_mem_swap(addr->addr, addr->len);
281 	}
282 }
283 
284 /**
285  * Filters the destination address of the frame.
286  *
287  * This is done before deciphering and authenticating encrypted frames.
288  */
ieee802154_check_dst_addr(struct net_if * iface,struct ieee802154_mhr * mhr)289 static bool ieee802154_check_dst_addr(struct net_if *iface, struct ieee802154_mhr *mhr)
290 {
291 	struct ieee802154_address_field_plain *dst_plain = &mhr->dst_addr->plain;
292 	struct ieee802154_context *ctx = net_if_l2_data(iface);
293 	bool ret = false;
294 
295 	/* Apply filtering requirements from section 6.7.2 c)-e). For a)-b),
296 	 * see ieee802154_parse_fcf_seq()
297 	 */
298 
299 	if (mhr->fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_NONE) {
300 		if (mhr->fs->fc.frame_version < IEEE802154_VERSION_802154 &&
301 		    mhr->fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
302 			/* See IEEE 802.15.4-2015, section 7.3.1.1. */
303 			return true;
304 		}
305 
306 		/* TODO: apply d.4 and d.5 when PAN coordinator is implemented */
307 		/* also, macImplicitBroadcast is not implemented */
308 		return false;
309 	}
310 
311 	k_sem_take(&ctx->ctx_lock, K_FOREVER);
312 
313 	/* c) If a destination PAN ID is included in the frame, it shall match
314 	 * macPanId or shall be the broadcast PAN ID.
315 	 */
316 	if (!(dst_plain->pan_id == IEEE802154_BROADCAST_PAN_ID ||
317 	      dst_plain->pan_id == sys_cpu_to_le16(ctx->pan_id))) {
318 		LOG_DBG("Frame PAN ID does not match!");
319 		goto out;
320 	}
321 
322 	if (mhr->fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
323 		/* d.1) A short destination address is included in the frame,
324 		 * and it matches either macShortAddress or the broadcast
325 		 * address.
326 		 */
327 		if (!(dst_plain->addr.short_addr == IEEE802154_BROADCAST_ADDRESS ||
328 		      dst_plain->addr.short_addr == sys_cpu_to_le16(ctx->short_addr))) {
329 			LOG_DBG("Frame dst address (short) does not match!");
330 			goto out;
331 		}
332 
333 	} else if (mhr->fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_EXTENDED) {
334 		/* d.2) An extended destination address is included in the frame and
335 		 * matches [...] macExtendedAddress [...].
336 		 */
337 		if (memcmp(dst_plain->addr.ext_addr, ctx->ext_addr,
338 				IEEE802154_EXT_ADDR_LENGTH) != 0) {
339 			LOG_DBG("Frame dst address (ext) does not match!");
340 			goto out;
341 		}
342 
343 		/* TODO: d.3) The Destination Address field and the Destination PAN ID
344 		 *       field are not included in the frame and macImplicitBroadcast is TRUE.
345 		 */
346 
347 		/* TODO: d.4) The device is the PAN coordinator, only source addressing fields
348 		 *       are included in a Data frame or MAC command and the source PAN ID
349 		 *       matches macPanId.
350 		 */
351 	}
352 	ret = true;
353 
354 out:
355 	k_sem_give(&ctx->ctx_lock);
356 	return ret;
357 }
358 
ieee802154_recv(struct net_if * iface,struct net_pkt * pkt)359 static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pkt)
360 {
361 	const struct ieee802154_radio_api *radio = net_if_get_device(iface)->api;
362 	enum net_verdict verdict = NET_CONTINUE;
363 	struct ieee802154_fcf_seq *fs;
364 	struct ieee802154_mpdu mpdu;
365 	bool is_broadcast;
366 	size_t ll_hdr_len;
367 
368 	/* The IEEE 802.15.4 stack assumes that drivers provide a single-fragment package. */
369 	__ASSERT_NO_MSG(pkt->buffer && pkt->buffer->frags == NULL);
370 
371 	if (!ieee802154_validate_frame(net_pkt_data(pkt), net_pkt_get_len(pkt), &mpdu)) {
372 		return NET_DROP;
373 	}
374 
375 	/* validate LL destination address (when IEEE802154_HW_FILTER not available) */
376 	if (!(radio->get_capabilities(net_if_get_device(iface)) & IEEE802154_HW_FILTER) &&
377 	    !ieee802154_check_dst_addr(iface, &mpdu.mhr)) {
378 		return NET_DROP;
379 	}
380 
381 	fs = mpdu.mhr.fs;
382 
383 	if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_ACK) {
384 		return NET_DROP;
385 	}
386 
387 	if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
388 		verdict = ieee802154_handle_beacon(iface, &mpdu, net_pkt_ieee802154_lqi(pkt));
389 		if (verdict == NET_CONTINUE) {
390 			net_pkt_unref(pkt);
391 			return NET_OK;
392 		}
393 		/* Beacons must not be acknowledged, see section 6.7.4.1. */
394 		return verdict;
395 	}
396 
397 	if (ieee802154_is_scanning(iface)) {
398 		return NET_DROP;
399 	}
400 
401 	if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) {
402 		verdict = ieee802154_handle_mac_command(iface, &mpdu);
403 		if (verdict == NET_DROP) {
404 			return verdict;
405 		}
406 	}
407 
408 	/* At this point the frame is either a MAC command or a data frame
409 	 * which may have to be acknowledged, see section 6.7.4.1.
410 	 */
411 
412 	is_broadcast = false;
413 
414 	if (fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
415 		struct ieee802154_address_field *dst_addr = mpdu.mhr.dst_addr;
416 		uint16_t short_dst_addr;
417 
418 		short_dst_addr = fs->fc.pan_id_comp ? dst_addr->comp.addr.short_addr
419 						    : dst_addr->plain.addr.short_addr;
420 		is_broadcast = short_dst_addr == IEEE802154_BROADCAST_ADDRESS;
421 	}
422 
423 	/* Frames that are broadcast must not be acknowledged, see section 6.7.2. */
424 	if (!is_broadcast) {
425 		ieee802154_acknowledge(iface, &mpdu);
426 	}
427 
428 	if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) {
429 		net_pkt_unref(pkt);
430 		return NET_OK;
431 	}
432 
433 	if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) {
434 		return NET_DROP;
435 	}
436 
437 	/* Setting LL addresses for upper layers must be done after L2 packet
438 	 * handling as it will mangle the L2 frame header to comply with upper
439 	 * layers' (POSIX) requirement to represent network addresses in big endian.
440 	 */
441 	swap_and_set_pkt_ll_addr(net_pkt_lladdr_src(pkt), !fs->fc.pan_id_comp,
442 				 fs->fc.src_addr_mode, mpdu.mhr.src_addr);
443 
444 	swap_and_set_pkt_ll_addr(net_pkt_lladdr_dst(pkt), true, fs->fc.dst_addr_mode,
445 				 mpdu.mhr.dst_addr);
446 
447 	net_pkt_set_ll_proto_type(pkt, ETH_P_IEEE802154);
448 
449 	pkt_hexdump(RX_PKT_TITLE " (with ll)", pkt, true);
450 
451 	ll_hdr_len = (uint8_t *)mpdu.payload - net_pkt_data(pkt);
452 	net_buf_pull(pkt->buffer, ll_hdr_len);
453 
454 #ifdef CONFIG_NET_6LO
455 	verdict = ieee802154_6lo_decode_pkt(iface, pkt);
456 #endif /* CONFIG_NET_6LO */
457 
458 	if (verdict == NET_CONTINUE) {
459 		pkt_hexdump(RX_PKT_TITLE, pkt, true);
460 	}
461 
462 	return verdict;
463 
464 	/* At this point the call amounts to (part of) an
465 	 * MCPS-DATA.indication primitive, see section 8.3.3.
466 	 */
467 }
468 
469 /**
470  * Implements (part of) the MCPS-DATA.request/confirm primitives, see sections 8.3.2/3.
471  */
ieee802154_send(struct net_if * iface,struct net_pkt * pkt)472 static int ieee802154_send(struct net_if *iface, struct net_pkt *pkt)
473 {
474 	struct ieee802154_context *ctx = net_if_l2_data(iface);
475 	uint8_t ll_hdr_len = 0, authtag_len = 0;
476 	static struct net_buf *frame_buf;
477 	static struct net_buf *pkt_buf;
478 	bool send_raw = false;
479 	int len;
480 #ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
481 	struct ieee802154_6lo_fragment_ctx frag_ctx;
482 	int requires_fragmentation = 0;
483 #endif
484 
485 	if (frame_buf == NULL) {
486 		frame_buf = net_buf_alloc(&tx_frame_buf_pool, K_FOREVER);
487 	}
488 
489 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && net_pkt_family(pkt) == AF_PACKET) {
490 		enum net_sock_type socket_type;
491 		struct net_context *context;
492 
493 		context = net_pkt_context(pkt);
494 		if (!context) {
495 			return -EINVAL;
496 		}
497 
498 		socket_type = net_context_get_type(context);
499 		if (socket_type == SOCK_RAW) {
500 			send_raw = true;
501 		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) &&
502 			   socket_type == SOCK_DGRAM) {
503 			struct sockaddr_ll *dst_addr = (struct sockaddr_ll *)&context->remote;
504 			struct sockaddr_ll_ptr *src_addr =
505 				(struct sockaddr_ll_ptr *)&context->local;
506 
507 			net_pkt_lladdr_dst(pkt)->addr = dst_addr->sll_addr;
508 			net_pkt_lladdr_dst(pkt)->len = dst_addr->sll_halen;
509 			net_pkt_lladdr_src(pkt)->addr = src_addr->sll_addr;
510 			net_pkt_lladdr_src(pkt)->len = src_addr->sll_halen;
511 		} else {
512 			return -EINVAL;
513 		}
514 	}
515 
516 	if (!send_raw) {
517 		ieee802154_compute_header_and_authtag_len(iface, net_pkt_lladdr_dst(pkt),
518 							  net_pkt_lladdr_src(pkt), &ll_hdr_len,
519 							  &authtag_len);
520 
521 #ifdef CONFIG_NET_6LO
522 #ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
523 		requires_fragmentation =
524 			ieee802154_6lo_encode_pkt(iface, pkt, &frag_ctx, ll_hdr_len, authtag_len);
525 		if (requires_fragmentation < 0) {
526 			return requires_fragmentation;
527 		}
528 #else
529 		ieee802154_6lo_encode_pkt(iface, pkt, NULL, ll_hdr_len, authtag_len);
530 #endif /* CONFIG_NET_L2_IEEE802154_FRAGMENT */
531 #endif /* CONFIG_NET_6LO */
532 	}
533 
534 	net_capture_pkt(iface, pkt);
535 
536 	len = 0;
537 	pkt_buf = pkt->buffer;
538 	while (pkt_buf) {
539 		int ret;
540 
541 		/* Reinitializing frame_buf */
542 		net_buf_reset(frame_buf);
543 		net_buf_add(frame_buf, ll_hdr_len);
544 
545 #ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
546 		if (requires_fragmentation) {
547 			pkt_buf = ieee802154_6lo_fragment(&frag_ctx, frame_buf, true);
548 		} else {
549 			net_buf_add_mem(frame_buf, pkt_buf->data, pkt_buf->len);
550 			pkt_buf = pkt_buf->frags;
551 		}
552 #else
553 		if (ll_hdr_len + pkt_buf->len + authtag_len > IEEE802154_MTU) {
554 			NET_ERR("Frame too long: %d", pkt_buf->len);
555 			return -EINVAL;
556 		}
557 		net_buf_add_mem(frame_buf, pkt_buf->data, pkt_buf->len);
558 		pkt_buf = pkt_buf->frags;
559 #endif /* CONFIG_NET_L2_IEEE802154_FRAGMENT */
560 
561 		__ASSERT_NO_MSG(authtag_len <= net_buf_tailroom(frame_buf));
562 		net_buf_add(frame_buf, authtag_len);
563 
564 		if (!(send_raw || ieee802154_create_data_frame(ctx, net_pkt_lladdr_dst(pkt),
565 							       net_pkt_lladdr_src(pkt),
566 							       frame_buf, ll_hdr_len))) {
567 			return -EINVAL;
568 		}
569 
570 		ret = ieee802154_radio_send(iface, pkt, frame_buf);
571 		if (ret) {
572 			return ret;
573 		}
574 
575 		len += frame_buf->len;
576 	}
577 
578 	net_pkt_unref(pkt);
579 
580 	return len;
581 }
582 
ieee802154_enable(struct net_if * iface,bool state)583 static int ieee802154_enable(struct net_if *iface, bool state)
584 {
585 	struct ieee802154_context *ctx = net_if_l2_data(iface);
586 
587 	NET_DBG("iface %p %s", iface, state ? "up" : "down");
588 
589 	k_sem_take(&ctx->ctx_lock, K_FOREVER);
590 
591 	if (ctx->channel == IEEE802154_NO_CHANNEL) {
592 		k_sem_give(&ctx->ctx_lock);
593 		return -ENETDOWN;
594 	}
595 
596 	k_sem_give(&ctx->ctx_lock);
597 
598 	if (state) {
599 		return ieee802154_radio_start(iface);
600 	}
601 
602 	return ieee802154_radio_stop(iface);
603 }
604 
ieee802154_flags(struct net_if * iface)605 static enum net_l2_flags ieee802154_flags(struct net_if *iface)
606 {
607 	struct ieee802154_context *ctx = net_if_l2_data(iface);
608 
609 	/* No need for locking as these flags are set once
610 	 * during L2 initialization and then never changed.
611 	 */
612 	return ctx->flags;
613 }
614 
615 NET_L2_INIT(IEEE802154_L2, ieee802154_recv, ieee802154_send, ieee802154_enable, ieee802154_flags);
616 
ieee802154_init(struct net_if * iface)617 void ieee802154_init(struct net_if *iface)
618 {
619 	struct ieee802154_context *ctx = net_if_l2_data(iface);
620 	const uint8_t *eui64_be = net_if_get_link_addr(iface)->addr;
621 	int16_t tx_power = CONFIG_NET_L2_IEEE802154_RADIO_DFLT_TX_POWER;
622 
623 	NET_DBG("Initializing IEEE 802.15.4 stack on iface %p", iface);
624 
625 	k_sem_init(&ctx->ctx_lock, 1, 1);
626 	k_sem_init(&ctx->ack_lock, 0, 1);
627 
628 	/* no need to lock the context here as it has
629 	 * not been published yet.
630 	 */
631 
632 	/* See section 6.7.1 - Transmission: "Each device shall initialize its data sequence number
633 	 * (DSN) to a random value and store its current DSN value in the MAC PIB attribute macDsn
634 	 * [...]."
635 	 */
636 	ctx->sequence = sys_rand32_get() & 0xFF;
637 
638 	ctx->channel = IEEE802154_NO_CHANNEL;
639 	ctx->flags = NET_L2_MULTICAST;
640 	if (ieee802154_radio_get_hw_capabilities(iface) & IEEE802154_HW_PROMISC) {
641 		ctx->flags |= NET_L2_PROMISC_MODE;
642 	}
643 
644 	ctx->pan_id = IEEE802154_PAN_ID_NOT_ASSOCIATED;
645 	ctx->short_addr = IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED;
646 	ctx->coord_short_addr = IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED;
647 	sys_memcpy_swap(ctx->ext_addr, eui64_be, IEEE802154_EXT_ADDR_LENGTH);
648 
649 	/* We switch to a link address store that we
650 	 * own so that we can write user defined short
651 	 * or extended addresses w/o mutating internal
652 	 * driver storage.
653 	 */
654 	ctx->linkaddr.type = NET_LINK_IEEE802154;
655 	ctx->linkaddr.len = IEEE802154_EXT_ADDR_LENGTH;
656 	memcpy(ctx->linkaddr.addr, eui64_be, IEEE802154_EXT_ADDR_LENGTH);
657 	net_if_set_link_addr(iface, ctx->linkaddr.addr, ctx->linkaddr.len, ctx->linkaddr.type);
658 
659 	if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START) ||
660 	    IS_ENABLED(CONFIG_NET_CONFIG_SETTINGS)) {
661 		LOG_DBG("Interface auto start disabled.");
662 		net_if_flag_set(iface, NET_IF_NO_AUTO_START);
663 	}
664 
665 	ieee802154_mgmt_init(iface);
666 
667 #ifdef CONFIG_NET_L2_IEEE802154_SECURITY
668 	if (ieee802154_security_init(&ctx->sec_ctx)) {
669 		NET_ERR("Initializing link-layer security failed");
670 	}
671 #endif
672 
673 	sys_memcpy_swap(ctx->ext_addr, eui64_be, IEEE802154_EXT_ADDR_LENGTH);
674 	ieee802154_radio_filter_ieee_addr(iface, ctx->ext_addr);
675 
676 	if (!ieee802154_radio_set_tx_power(iface, tx_power)) {
677 		ctx->tx_power = tx_power;
678 	}
679 }
680