1 /** @file
2  @brief Network packet buffers for IP stack
3 
4  Network data is passed between components using net_pkt.
5  */
6 
7 /*
8  * Copyright (c) 2016 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(net_pkt, CONFIG_NET_PKT_LOG_LEVEL);
15 
16 /* This enables allocation debugging but does not print so much output
17  * as that can slow things down a lot.
18  */
19 #undef NET_LOG_LEVEL
20 #if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
21 #define NET_LOG_LEVEL 5
22 #else
23 #define NET_LOG_LEVEL CONFIG_NET_PKT_LOG_LEVEL
24 #endif
25 
26 #include <zephyr/kernel.h>
27 #include <zephyr/toolchain.h>
28 #include <string.h>
29 #include <zephyr/types.h>
30 #include <sys/types.h>
31 
32 #include <zephyr/sys/util.h>
33 
34 #include <zephyr/net/net_core.h>
35 #include <zephyr/net/net_ip.h>
36 #include <zephyr/net/buf.h>
37 #include <zephyr/net/net_pkt.h>
38 #include <zephyr/net/ethernet.h>
39 #include <zephyr/net/udp.h>
40 
41 #include "net_private.h"
42 #include "tcp_internal.h"
43 
44 /* Find max header size of IP protocol (IPv4 or IPv6) */
45 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_RAW_MODE) || \
46     defined(CONFIG_NET_SOCKETS_PACKET) || defined(CONFIG_NET_SOCKETS_OFFLOAD)
47 #define MAX_IP_PROTO_LEN NET_IPV6H_LEN
48 #else
49 #if defined(CONFIG_NET_IPV4)
50 #define MAX_IP_PROTO_LEN NET_IPV4H_LEN
51 #else
52 #if defined(CONFIG_NET_SOCKETS_CAN)
53 /* TODO: Use CAN MTU here instead of hard coded value. There was
54  * weird circular dependency issue so this needs more TLC.
55  */
56 #define MAX_IP_PROTO_LEN 8
57 #else
58 #if defined(CONFIG_NET_ETHERNET_BRIDGE) || \
59 	defined(CONFIG_NET_L2_IEEE802154) || \
60 	defined(CONFIG_NET_L2_CUSTOM_IEEE802154)
61 #define MAX_IP_PROTO_LEN 0
62 #else
63 #error "Some packet protocol (e.g. IPv6, IPv4, ETH, IEEE 802.15.4) needs to be selected."
64 #endif /* ETHERNET_BRIDGE / L2_IEEE802154 */
65 #endif /* SOCKETS_CAN */
66 #endif /* IPv4 */
67 #endif /* IPv6 */
68 
69 /* Find max header size of "next" protocol (TCP, UDP or ICMP) */
70 #if defined(CONFIG_NET_TCP)
71 #define MAX_NEXT_PROTO_LEN NET_TCPH_LEN
72 #else
73 #if defined(CONFIG_NET_UDP)
74 #define MAX_NEXT_PROTO_LEN NET_UDPH_LEN
75 #else
76 #if defined(CONFIG_NET_SOCKETS_CAN)
77 #define MAX_NEXT_PROTO_LEN 0
78 #else
79 /* If no TCP and no UDP, apparently we still want pings to work. */
80 #define MAX_NEXT_PROTO_LEN NET_ICMPH_LEN
81 #endif /* SOCKETS_CAN */
82 #endif /* UDP */
83 #endif /* TCP */
84 
85 /* Make sure that IP + TCP/UDP/ICMP headers fit into one fragment. This
86  * makes possible to cast a fragment pointer to protocol header struct.
87  */
88 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
89 #if CONFIG_NET_BUF_DATA_SIZE < (MAX_IP_PROTO_LEN + MAX_NEXT_PROTO_LEN)
90 #if defined(STRING2)
91 #undef STRING2
92 #endif
93 #if defined(STRING)
94 #undef STRING
95 #endif
96 #define STRING2(x) #x
97 #define STRING(x) STRING2(x)
98 #pragma message "Data len " STRING(CONFIG_NET_BUF_DATA_SIZE)
99 #pragma message "Minimum len " STRING(MAX_IP_PROTO_LEN + MAX_NEXT_PROTO_LEN)
100 #error "Too small net_buf fragment size"
101 #endif
102 #endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
103 
104 #if CONFIG_NET_PKT_RX_COUNT <= 0
105 #error "Minimum value for CONFIG_NET_PKT_RX_COUNT is 1"
106 #endif
107 
108 #if CONFIG_NET_PKT_TX_COUNT <= 0
109 #error "Minimum value for CONFIG_NET_PKT_TX_COUNT is 1"
110 #endif
111 
112 #if CONFIG_NET_BUF_RX_COUNT <= 0
113 #error "Minimum value for CONFIG_NET_BUF_RX_COUNT is 1"
114 #endif
115 
116 #if CONFIG_NET_BUF_TX_COUNT <= 0
117 #error "Minimum value for CONFIG_NET_BUF_TX_COUNT is 1"
118 #endif
119 
120 K_MEM_SLAB_DEFINE(rx_pkts, sizeof(struct net_pkt), CONFIG_NET_PKT_RX_COUNT, 4);
121 K_MEM_SLAB_DEFINE(tx_pkts, sizeof(struct net_pkt), CONFIG_NET_PKT_TX_COUNT, 4);
122 
123 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
124 
125 NET_BUF_POOL_FIXED_DEFINE(rx_bufs, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_BUF_DATA_SIZE,
126 			  CONFIG_NET_PKT_BUF_USER_DATA_SIZE, NULL);
127 NET_BUF_POOL_FIXED_DEFINE(tx_bufs, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_BUF_DATA_SIZE,
128 			  CONFIG_NET_PKT_BUF_USER_DATA_SIZE, NULL);
129 
130 #else /* !CONFIG_NET_BUF_FIXED_DATA_SIZE */
131 
132 NET_BUF_POOL_VAR_DEFINE(rx_bufs, CONFIG_NET_BUF_RX_COUNT, CONFIG_NET_PKT_BUF_RX_DATA_POOL_SIZE,
133 			CONFIG_NET_PKT_BUF_USER_DATA_SIZE, NULL);
134 NET_BUF_POOL_VAR_DEFINE(tx_bufs, CONFIG_NET_BUF_TX_COUNT, CONFIG_NET_PKT_BUF_TX_DATA_POOL_SIZE,
135 			CONFIG_NET_PKT_BUF_USER_DATA_SIZE, NULL);
136 
137 #endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
138 
139 /* Allocation tracking is only available if separately enabled */
140 #if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
141 struct net_pkt_alloc {
142 	union {
143 		struct net_pkt *pkt;
144 		struct net_buf *buf;
145 		void *alloc_data;
146 	};
147 	const char *func_alloc;
148 	const char *func_free;
149 	uint16_t line_alloc;
150 	uint16_t line_free;
151 	uint8_t in_use;
152 	bool is_pkt;
153 };
154 
155 #define MAX_NET_PKT_ALLOCS (CONFIG_NET_PKT_RX_COUNT + \
156 			    CONFIG_NET_PKT_TX_COUNT + \
157 			    CONFIG_NET_BUF_RX_COUNT + \
158 			    CONFIG_NET_BUF_TX_COUNT + \
159 			    CONFIG_NET_DEBUG_NET_PKT_EXTERNALS)
160 
161 static struct net_pkt_alloc net_pkt_allocs[MAX_NET_PKT_ALLOCS];
162 
net_pkt_alloc_add(void * alloc_data,bool is_pkt,const char * func,int line)163 static void net_pkt_alloc_add(void *alloc_data, bool is_pkt,
164 			      const char *func, int line)
165 {
166 	int i;
167 
168 	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
169 		if (net_pkt_allocs[i].in_use) {
170 			continue;
171 		}
172 
173 		net_pkt_allocs[i].in_use = true;
174 		net_pkt_allocs[i].is_pkt = is_pkt;
175 		net_pkt_allocs[i].alloc_data = alloc_data;
176 		net_pkt_allocs[i].func_alloc = func;
177 		net_pkt_allocs[i].line_alloc = line;
178 
179 		return;
180 	}
181 }
182 
net_pkt_alloc_del(void * alloc_data,const char * func,int line)183 static void net_pkt_alloc_del(void *alloc_data, const char *func, int line)
184 {
185 	int i;
186 
187 	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
188 		if (net_pkt_allocs[i].in_use &&
189 		    net_pkt_allocs[i].alloc_data == alloc_data) {
190 			net_pkt_allocs[i].func_free = func;
191 			net_pkt_allocs[i].line_free = line;
192 			net_pkt_allocs[i].in_use = false;
193 
194 			return;
195 		}
196 	}
197 }
198 
net_pkt_alloc_find(void * alloc_data,const char ** func_free,int * line_free)199 static bool net_pkt_alloc_find(void *alloc_data,
200 			       const char **func_free,
201 			       int *line_free)
202 {
203 	int i;
204 
205 	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
206 		if (!net_pkt_allocs[i].in_use &&
207 		    net_pkt_allocs[i].alloc_data == alloc_data) {
208 			*func_free = net_pkt_allocs[i].func_free;
209 			*line_free = net_pkt_allocs[i].line_free;
210 
211 			return true;
212 		}
213 	}
214 
215 	return false;
216 }
217 
net_pkt_allocs_foreach(net_pkt_allocs_cb_t cb,void * user_data)218 void net_pkt_allocs_foreach(net_pkt_allocs_cb_t cb, void *user_data)
219 {
220 	int i;
221 
222 	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
223 		if (net_pkt_allocs[i].in_use) {
224 			cb(net_pkt_allocs[i].is_pkt ?
225 			   net_pkt_allocs[i].pkt : NULL,
226 			   net_pkt_allocs[i].is_pkt ?
227 			   NULL : net_pkt_allocs[i].buf,
228 			   net_pkt_allocs[i].func_alloc,
229 			   net_pkt_allocs[i].line_alloc,
230 			   net_pkt_allocs[i].func_free,
231 			   net_pkt_allocs[i].line_free,
232 			   net_pkt_allocs[i].in_use,
233 			   user_data);
234 		}
235 	}
236 
237 	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
238 		if (!net_pkt_allocs[i].in_use) {
239 			cb(net_pkt_allocs[i].is_pkt ?
240 			   net_pkt_allocs[i].pkt : NULL,
241 			   net_pkt_allocs[i].is_pkt ?
242 			   NULL : net_pkt_allocs[i].buf,
243 			   net_pkt_allocs[i].func_alloc,
244 			   net_pkt_allocs[i].line_alloc,
245 			   net_pkt_allocs[i].func_free,
246 			   net_pkt_allocs[i].line_free,
247 			   net_pkt_allocs[i].in_use,
248 			   user_data);
249 		}
250 	}
251 }
252 #else
253 #define net_pkt_alloc_add(alloc_data, is_pkt, func, line)
254 #define net_pkt_alloc_del(alloc_data, func, line)
255 #define net_pkt_alloc_find(alloc_data, func_free, line_free) false
256 #endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
257 
258 #if defined(NET_PKT_DEBUG_ENABLED)
259 
260 #define NET_FRAG_CHECK_IF_NOT_IN_USE(frag, ref)				\
261 	do {								\
262 		if (!(ref)) {                                           \
263 			NET_ERR("**ERROR** frag %p not in use (%s:%s():%d)", \
264 				frag, __FILE__, __func__, __LINE__);     \
265 		}                                                       \
266 	} while (false)
267 
net_pkt_slab2str(struct k_mem_slab * slab)268 const char *net_pkt_slab2str(struct k_mem_slab *slab)
269 {
270 	if (slab == &rx_pkts) {
271 		return "RX";
272 	} else if (slab == &tx_pkts) {
273 		return "TX";
274 	}
275 
276 	return "EXT";
277 }
278 
net_pkt_pool2str(struct net_buf_pool * pool)279 const char *net_pkt_pool2str(struct net_buf_pool *pool)
280 {
281 	if (pool == &rx_bufs) {
282 		return "RDATA";
283 	} else if (pool == &tx_bufs) {
284 		return "TDATA";
285 	}
286 
287 	return "EDATA";
288 }
289 
get_frees(struct net_buf_pool * pool)290 static inline int16_t get_frees(struct net_buf_pool *pool)
291 {
292 #if defined(CONFIG_NET_BUF_POOL_USAGE)
293 	return atomic_get(&pool->avail_count);
294 #else
295 	return 0;
296 #endif
297 }
298 
net_pkt_print_frags(struct net_pkt * pkt)299 void net_pkt_print_frags(struct net_pkt *pkt)
300 {
301 	struct net_buf *frag;
302 	size_t total = 0;
303 	int count = 0, frag_size = 0;
304 
305 	if (!pkt) {
306 		NET_INFO("pkt %p", pkt);
307 		return;
308 	}
309 
310 	NET_INFO("pkt %p frags %p", pkt, pkt->frags);
311 
312 	NET_ASSERT(pkt->frags);
313 
314 	frag = pkt->frags;
315 	while (frag) {
316 		total += frag->len;
317 
318 		frag_size = net_buf_max_len(frag);
319 
320 		NET_INFO("[%d] frag %p len %d max len %u size %d pool %p",
321 			 count, frag, frag->len, frag->size,
322 			 frag_size, net_buf_pool_get(frag->pool_id));
323 
324 		count++;
325 
326 		frag = frag->frags;
327 	}
328 
329 	NET_INFO("Total data size %zu, occupied %d bytes, utilization %zu%%",
330 		 total, count * frag_size,
331 		 count ? (total * 100) / (count * frag_size) : 0);
332 }
333 #endif
334 
335 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
get_name(struct net_buf_pool * pool)336 static inline const char *get_name(struct net_buf_pool *pool)
337 {
338 #if defined(CONFIG_NET_BUF_POOL_USAGE)
339 	return pool->name;
340 #else
341 	return "?";
342 #endif
343 }
344 
get_size(struct net_buf_pool * pool)345 static inline int16_t get_size(struct net_buf_pool *pool)
346 {
347 #if defined(CONFIG_NET_BUF_POOL_USAGE)
348 	return pool->pool_size;
349 #else
350 	return 0;
351 #endif
352 }
353 
slab2str(struct k_mem_slab * slab)354 static inline const char *slab2str(struct k_mem_slab *slab)
355 {
356 	return net_pkt_slab2str(slab);
357 }
358 
pool2str(struct net_buf_pool * pool)359 static inline const char *pool2str(struct net_buf_pool *pool)
360 {
361 	return net_pkt_pool2str(pool);
362 }
363 #endif /* CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG */
364 
365 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
net_pkt_get_reserve_data_debug(struct net_buf_pool * pool,size_t min_len,k_timeout_t timeout,const char * caller,int line)366 struct net_buf *net_pkt_get_reserve_data_debug(struct net_buf_pool *pool,
367 					       size_t min_len,
368 					       k_timeout_t timeout,
369 					       const char *caller,
370 					       int line)
371 #else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
372 struct net_buf *net_pkt_get_reserve_data(struct net_buf_pool *pool,
373 					 size_t min_len, k_timeout_t timeout)
374 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
375 {
376 	struct net_buf *frag;
377 
378 	if (k_is_in_isr()) {
379 		timeout = K_NO_WAIT;
380 	}
381 
382 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
383 	if (min_len > CONFIG_NET_BUF_DATA_SIZE) {
384 		NET_ERR("Requested too large fragment. Increase CONFIG_NET_BUF_DATA_SIZE.");
385 		return NULL;
386 	}
387 
388 	frag = net_buf_alloc(pool, timeout);
389 #else
390 	frag = net_buf_alloc_len(pool, min_len, timeout);
391 #endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
392 
393 	if (!frag) {
394 		return NULL;
395 	}
396 
397 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
398 	NET_FRAG_CHECK_IF_NOT_IN_USE(frag, frag->ref + 1U);
399 #endif
400 
401 	net_pkt_alloc_add(frag, false, caller, line);
402 
403 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
404 	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
405 		pool2str(pool), get_name(pool), get_frees(pool),
406 		frag, frag->ref, caller, line);
407 #endif
408 
409 	return frag;
410 }
411 
412 /* Get a fragment, try to figure out the pool from where to get
413  * the data.
414  */
415 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
net_pkt_get_frag_debug(struct net_pkt * pkt,size_t min_len,k_timeout_t timeout,const char * caller,int line)416 struct net_buf *net_pkt_get_frag_debug(struct net_pkt *pkt, size_t min_len,
417 				       k_timeout_t timeout,
418 				       const char *caller, int line)
419 #else
420 struct net_buf *net_pkt_get_frag(struct net_pkt *pkt, size_t min_len,
421 				 k_timeout_t timeout)
422 #endif
423 {
424 #if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
425 	struct net_context *context;
426 
427 	context = net_pkt_context(pkt);
428 	if (context && context->data_pool) {
429 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
430 		return net_pkt_get_reserve_data_debug(context->data_pool(),
431 						      min_len, timeout,
432 						      caller, line);
433 #else
434 		return net_pkt_get_reserve_data(context->data_pool(), min_len,
435 						timeout);
436 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
437 	}
438 #endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
439 
440 	if (pkt->slab == &rx_pkts) {
441 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
442 		return net_pkt_get_reserve_rx_data_debug(min_len, timeout,
443 							 caller, line);
444 #else
445 		return net_pkt_get_reserve_rx_data(min_len, timeout);
446 #endif
447 	}
448 
449 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
450 	return net_pkt_get_reserve_tx_data_debug(min_len, timeout, caller, line);
451 #else
452 	return net_pkt_get_reserve_tx_data(min_len, timeout);
453 #endif
454 }
455 
456 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
net_pkt_get_reserve_rx_data_debug(size_t min_len,k_timeout_t timeout,const char * caller,int line)457 struct net_buf *net_pkt_get_reserve_rx_data_debug(size_t min_len, k_timeout_t timeout,
458 						  const char *caller, int line)
459 {
460 	return net_pkt_get_reserve_data_debug(&rx_bufs, min_len, timeout, caller, line);
461 }
462 
net_pkt_get_reserve_tx_data_debug(size_t min_len,k_timeout_t timeout,const char * caller,int line)463 struct net_buf *net_pkt_get_reserve_tx_data_debug(size_t min_len, k_timeout_t timeout,
464 						  const char *caller, int line)
465 {
466 	return net_pkt_get_reserve_data_debug(&tx_bufs, min_len, timeout, caller, line);
467 }
468 
469 #else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
470 
net_pkt_get_reserve_rx_data(size_t min_len,k_timeout_t timeout)471 struct net_buf *net_pkt_get_reserve_rx_data(size_t min_len, k_timeout_t timeout)
472 {
473 	return net_pkt_get_reserve_data(&rx_bufs, min_len, timeout);
474 }
475 
net_pkt_get_reserve_tx_data(size_t min_len,k_timeout_t timeout)476 struct net_buf *net_pkt_get_reserve_tx_data(size_t min_len, k_timeout_t timeout)
477 {
478 	return net_pkt_get_reserve_data(&tx_bufs, min_len, timeout);
479 }
480 
481 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
482 
483 
484 #if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
get_tx_slab(struct net_context * context)485 static inline struct k_mem_slab *get_tx_slab(struct net_context *context)
486 {
487 	if (context->tx_slab) {
488 		return context->tx_slab();
489 	}
490 
491 	return NULL;
492 }
493 
get_data_pool(struct net_context * context)494 static inline struct net_buf_pool *get_data_pool(struct net_context *context)
495 {
496 	if (context->data_pool) {
497 		return context->data_pool();
498 	}
499 
500 	return NULL;
501 }
502 #else
503 #define get_tx_slab(...) NULL
504 #define get_data_pool(...) NULL
505 #endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
506 
507 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
net_pkt_unref_debug(struct net_pkt * pkt,const char * caller,int line)508 void net_pkt_unref_debug(struct net_pkt *pkt, const char *caller, int line)
509 {
510 	struct net_buf *frag;
511 
512 #else
513 void net_pkt_unref(struct net_pkt *pkt)
514 {
515 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
516 	atomic_val_t ref;
517 
518 	if (!pkt) {
519 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
520 		NET_ERR("*** ERROR *** pkt %p (%s():%d)", pkt, caller, line);
521 #endif
522 		return;
523 	}
524 
525 	do {
526 		ref = atomic_get(&pkt->atomic_ref);
527 		if (!ref) {
528 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
529 			const char *func_freed;
530 			int line_freed;
531 
532 			if (net_pkt_alloc_find(pkt, &func_freed, &line_freed)) {
533 				NET_ERR("*** ERROR *** pkt %p is freed already "
534 					"by %s():%d (%s():%d)",
535 					pkt, func_freed, line_freed, caller,
536 					line);
537 			} else {
538 				NET_ERR("*** ERROR *** pkt %p is freed already "
539 					"(%s():%d)", pkt, caller, line);
540 			}
541 #endif
542 			return;
543 		}
544 	} while (!atomic_cas(&pkt->atomic_ref, ref, ref - 1));
545 
546 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
547 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
548 	NET_DBG("%s [%d] pkt %p ref %ld frags %p (%s():%d)",
549 		slab2str(pkt->slab), k_mem_slab_num_free_get(pkt->slab),
550 		pkt, ref - 1, pkt->frags, caller, line);
551 #endif
552 	if (ref > 1) {
553 		goto done;
554 	}
555 
556 	frag = pkt->frags;
557 	while (frag) {
558 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
559 		NET_DBG("%s (%s) [%d] frag %p ref %d frags %p (%s():%d)",
560 			pool2str(net_buf_pool_get(frag->pool_id)),
561 			get_name(net_buf_pool_get(frag->pool_id)),
562 			get_frees(net_buf_pool_get(frag->pool_id)), frag,
563 			frag->ref - 1U, frag->frags, caller, line);
564 #endif
565 
566 		if (!frag->ref) {
567 			const char *func_freed;
568 			int line_freed;
569 
570 			if (net_pkt_alloc_find(frag,
571 					       &func_freed, &line_freed)) {
572 				NET_ERR("*** ERROR *** frag %p is freed "
573 					"already by %s():%d (%s():%d)",
574 					frag, func_freed, line_freed,
575 					caller, line);
576 			} else {
577 				NET_ERR("*** ERROR *** frag %p is freed "
578 					"already (%s():%d)",
579 					frag, caller, line);
580 			}
581 		}
582 
583 		net_pkt_alloc_del(frag, caller, line);
584 
585 		frag = frag->frags;
586 	}
587 
588 	net_pkt_alloc_del(pkt, caller, line);
589 done:
590 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
591 
592 	if (ref > 1) {
593 		return;
594 	}
595 
596 	if (pkt->frags) {
597 		net_pkt_frag_unref(pkt->frags);
598 	}
599 
600 	if (IS_ENABLED(CONFIG_NET_DEBUG_NET_PKT_NON_FRAGILE_ACCESS)) {
601 		pkt->buffer = NULL;
602 		net_pkt_cursor_init(pkt);
603 	}
604 
605 	k_mem_slab_free(pkt->slab, (void *)pkt);
606 }
607 
608 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
609 struct net_pkt *net_pkt_ref_debug(struct net_pkt *pkt, const char *caller,
610 				  int line)
611 #else
612 struct net_pkt *net_pkt_ref(struct net_pkt *pkt)
613 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
614 {
615 	atomic_val_t ref;
616 
617 	do {
618 		ref = pkt ? atomic_get(&pkt->atomic_ref) : 0;
619 		if (!ref) {
620 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
621 			NET_ERR("*** ERROR *** pkt %p (%s():%d)",
622 				pkt, caller, line);
623 #endif
624 			return NULL;
625 		}
626 	} while (!atomic_cas(&pkt->atomic_ref, ref, ref + 1));
627 
628 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
629 	NET_DBG("%s [%d] pkt %p ref %ld (%s():%d)",
630 		slab2str(pkt->slab), k_mem_slab_num_free_get(pkt->slab),
631 		pkt, ref + 1, caller, line);
632 #endif
633 
634 
635 	return pkt;
636 }
637 
638 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
639 struct net_buf *net_pkt_frag_ref_debug(struct net_buf *frag,
640 				       const char *caller, int line)
641 #else
642 struct net_buf *net_pkt_frag_ref(struct net_buf *frag)
643 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
644 {
645 	if (!frag) {
646 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
647 		NET_ERR("*** ERROR *** frag %p (%s():%d)", frag, caller, line);
648 #endif
649 		return NULL;
650 	}
651 
652 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
653 	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
654 		pool2str(net_buf_pool_get(frag->pool_id)),
655 		get_name(net_buf_pool_get(frag->pool_id)),
656 		get_frees(net_buf_pool_get(frag->pool_id)),
657 		frag, frag->ref + 1U, caller, line);
658 #endif
659 
660 	return net_buf_ref(frag);
661 }
662 
663 
664 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
665 void net_pkt_frag_unref_debug(struct net_buf *frag,
666 			      const char *caller, int line)
667 #else
668 void net_pkt_frag_unref(struct net_buf *frag)
669 #endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
670 {
671 	if (!frag) {
672 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
673 		NET_ERR("*** ERROR *** frag %p (%s():%d)", frag, caller, line);
674 #endif
675 		return;
676 	}
677 
678 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
679 	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
680 		pool2str(net_buf_pool_get(frag->pool_id)),
681 		get_name(net_buf_pool_get(frag->pool_id)),
682 		get_frees(net_buf_pool_get(frag->pool_id)),
683 		frag, frag->ref - 1U, caller, line);
684 #endif
685 
686 	if (frag->ref == 1U) {
687 		net_pkt_alloc_del(frag, caller, line);
688 	}
689 
690 	net_buf_unref(frag);
691 }
692 
693 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
694 struct net_buf *net_pkt_frag_del_debug(struct net_pkt *pkt,
695 				       struct net_buf *parent,
696 				       struct net_buf *frag,
697 				       const char *caller, int line)
698 #else
699 struct net_buf *net_pkt_frag_del(struct net_pkt *pkt,
700 				 struct net_buf *parent,
701 				 struct net_buf *frag)
702 #endif
703 {
704 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
705 	NET_DBG("pkt %p parent %p frag %p ref %u (%s:%d)",
706 		pkt, parent, frag, frag->ref, caller, line);
707 #endif
708 
709 	if (pkt->frags == frag && !parent) {
710 		struct net_buf *tmp;
711 
712 		if (frag->ref == 1U) {
713 			net_pkt_alloc_del(frag, caller, line);
714 		}
715 
716 		tmp = net_buf_frag_del(NULL, frag);
717 		pkt->frags = tmp;
718 
719 		return tmp;
720 	}
721 
722 	if (frag->ref == 1U) {
723 		net_pkt_alloc_del(frag, caller, line);
724 	}
725 
726 	return net_buf_frag_del(parent, frag);
727 }
728 
729 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
730 void net_pkt_frag_add_debug(struct net_pkt *pkt, struct net_buf *frag,
731 			    const char *caller, int line)
732 #else
733 void net_pkt_frag_add(struct net_pkt *pkt, struct net_buf *frag)
734 #endif
735 {
736 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
737 	NET_DBG("pkt %p frag %p (%s:%d)", pkt, frag, caller, line);
738 #endif
739 
740 	/* We do not use net_buf_frag_add() as this one will refcount
741 	 * the frag once more if !pkt->frags
742 	 */
743 	if (!pkt->frags) {
744 		pkt->frags = frag;
745 		return;
746 	}
747 
748 	net_buf_frag_insert(net_buf_frag_last(pkt->frags), frag);
749 }
750 
751 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
752 void net_pkt_frag_insert_debug(struct net_pkt *pkt, struct net_buf *frag,
753 			       const char *caller, int line)
754 #else
755 void net_pkt_frag_insert(struct net_pkt *pkt, struct net_buf *frag)
756 #endif
757 {
758 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
759 	NET_DBG("pkt %p frag %p (%s:%d)", pkt, frag, caller, line);
760 #endif
761 
762 	net_buf_frag_last(frag)->frags = pkt->frags;
763 	pkt->frags = frag;
764 }
765 
766 void net_pkt_compact(struct net_pkt *pkt)
767 {
768 	struct net_buf *frag, *prev;
769 
770 	NET_DBG("Compacting data in pkt %p", pkt);
771 
772 	frag = pkt->frags;
773 	prev = NULL;
774 
775 	while (frag) {
776 		if (frag->frags) {
777 			/* Copy amount of data from next fragment to this
778 			 * fragment.
779 			 */
780 			size_t copy_len;
781 
782 			copy_len = frag->frags->len;
783 			if (copy_len > net_buf_tailroom(frag)) {
784 				copy_len = net_buf_tailroom(frag);
785 			}
786 
787 			memcpy(net_buf_tail(frag), frag->frags->data, copy_len);
788 			net_buf_add(frag, copy_len);
789 
790 			memmove(frag->frags->data,
791 				frag->frags->data + copy_len,
792 				frag->frags->len - copy_len);
793 
794 			frag->frags->len -= copy_len;
795 
796 			/* Is there any more space in this fragment */
797 			if (net_buf_tailroom(frag)) {
798 				/* There is. This also means that the next
799 				 * fragment is empty as otherwise we could
800 				 * not have copied all data. Remove next
801 				 * fragment as there is no data in it any more.
802 				 */
803 				net_pkt_frag_del(pkt, frag, frag->frags);
804 
805 				/* Then check next fragment */
806 				continue;
807 			}
808 		} else {
809 			if (!frag->len) {
810 				/* Remove the last fragment because there is no
811 				 * data in it.
812 				 */
813 				net_pkt_frag_del(pkt, prev, frag);
814 
815 				break;
816 			}
817 		}
818 
819 		prev = frag;
820 		frag = frag->frags;
821 	}
822 }
823 
824 void net_pkt_get_info(struct k_mem_slab **rx,
825 		      struct k_mem_slab **tx,
826 		      struct net_buf_pool **rx_data,
827 		      struct net_buf_pool **tx_data)
828 {
829 	if (rx) {
830 		*rx = &rx_pkts;
831 	}
832 
833 	if (tx) {
834 		*tx = &tx_pkts;
835 	}
836 
837 	if (rx_data) {
838 		*rx_data = &rx_bufs;
839 	}
840 
841 	if (tx_data) {
842 		*tx_data = &tx_bufs;
843 	}
844 }
845 
846 #if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
847 void net_pkt_print(void)
848 {
849 	NET_DBG("TX %u RX %u RDATA %d TDATA %d",
850 		k_mem_slab_num_free_get(&tx_pkts),
851 		k_mem_slab_num_free_get(&rx_pkts),
852 		get_frees(&rx_bufs), get_frees(&tx_bufs));
853 }
854 #endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
855 
856 /* New allocator and API starts here */
857 
858 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
859 
860 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
861 static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
862 					size_t size, k_timeout_t timeout,
863 					const char *caller, int line)
864 #else
865 static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
866 					size_t size, k_timeout_t timeout)
867 #endif
868 {
869 	k_timepoint_t end = sys_timepoint_calc(timeout);
870 	struct net_buf *first = NULL;
871 	struct net_buf *current = NULL;
872 
873 	do {
874 		struct net_buf *new;
875 
876 		new = net_buf_alloc_fixed(pool, timeout);
877 		if (!new) {
878 			goto error;
879 		}
880 
881 		if (!first && !current) {
882 			first = new;
883 		} else {
884 			current->frags = new;
885 		}
886 
887 		current = new;
888 		if (current->size > size) {
889 			current->size = size;
890 		}
891 
892 		size -= current->size;
893 
894 		timeout = sys_timepoint_timeout(end);
895 
896 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
897 		NET_FRAG_CHECK_IF_NOT_IN_USE(new, new->ref + 1);
898 
899 		net_pkt_alloc_add(new, false, caller, line);
900 
901 		NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
902 			pool2str(pool), get_name(pool), get_frees(pool),
903 			new, new->ref, caller, line);
904 #endif
905 	} while (size);
906 
907 	return first;
908 error:
909 	if (first) {
910 		net_buf_unref(first);
911 	}
912 
913 	return NULL;
914 }
915 
916 #else /* !CONFIG_NET_BUF_FIXED_DATA_SIZE */
917 
918 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
919 static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
920 					size_t size, k_timeout_t timeout,
921 					const char *caller, int line)
922 #else
923 static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
924 					size_t size, k_timeout_t timeout)
925 #endif
926 {
927 	struct net_buf *buf;
928 
929 	buf = net_buf_alloc_len(pool, size, timeout);
930 
931 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
932 	NET_FRAG_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1);
933 
934 	net_pkt_alloc_add(buf, false, caller, line);
935 
936 	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
937 		pool2str(pool), get_name(pool), get_frees(pool),
938 		buf, buf->ref, caller, line);
939 #endif
940 
941 	return buf;
942 }
943 
944 #endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
945 
946 static size_t pkt_buffer_length(struct net_pkt *pkt,
947 				size_t size,
948 				enum net_ip_protocol proto,
949 				size_t existing)
950 {
951 	sa_family_t family = net_pkt_family(pkt);
952 	size_t max_len;
953 
954 	if (net_pkt_iface(pkt)) {
955 		max_len = net_if_get_mtu(net_pkt_iface(pkt));
956 	} else {
957 		max_len = 0;
958 	}
959 
960 	/* Family vs iface MTU */
961 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
962 		if (IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) && (size > max_len)) {
963 			/* We support larger packets if IPv6 fragmentation is
964 			 * enabled.
965 			 */
966 			max_len = size;
967 		}
968 
969 		max_len = MAX(max_len, NET_IPV6_MTU);
970 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
971 		if (IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT) && (size > max_len)) {
972 			/* We support larger packets if IPv4 fragmentation is enabled */
973 			max_len = size;
974 		}
975 
976 		max_len = MAX(max_len, NET_IPV4_MTU);
977 	} else { /* family == AF_UNSPEC */
978 #if defined (CONFIG_NET_L2_ETHERNET)
979 		if (net_if_l2(net_pkt_iface(pkt)) ==
980 		    &NET_L2_GET_NAME(ETHERNET)) {
981 			max_len += NET_ETH_MAX_HDR_SIZE;
982 		} else
983 #endif /* CONFIG_NET_L2_ETHERNET */
984 		{
985 			/* Other L2 are not checked as the pkt MTU in this case
986 			 * is based on the IP layer (IPv6 most of the time).
987 			 */
988 			max_len = size;
989 		}
990 	}
991 
992 	max_len -= existing;
993 
994 	return MIN(size, max_len);
995 }
996 
997 static size_t pkt_estimate_headers_length(struct net_pkt *pkt,
998 					  sa_family_t family,
999 					  enum net_ip_protocol proto)
1000 {
1001 	size_t hdr_len = 0;
1002 
1003 	if (family == AF_UNSPEC) {
1004 		return  0;
1005 	}
1006 
1007 	/* Family header */
1008 	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
1009 		hdr_len += NET_IPV6H_LEN;
1010 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
1011 		hdr_len += NET_IPV4H_LEN;
1012 	}
1013 
1014 	/* + protocol header */
1015 	if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
1016 		hdr_len += NET_TCPH_LEN + NET_TCP_MAX_OPT_SIZE;
1017 	} else if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
1018 		hdr_len += NET_UDPH_LEN;
1019 	} else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
1020 		hdr_len += NET_ICMPH_LEN;
1021 	}
1022 
1023 	NET_DBG("HDRs length estimation %zu", hdr_len);
1024 
1025 	return hdr_len;
1026 }
1027 
1028 static size_t pkt_get_max_len(struct net_pkt *pkt)
1029 {
1030 	struct net_buf *buf = pkt->buffer;
1031 	size_t size = 0;
1032 
1033 	while (buf) {
1034 		size += net_buf_max_len(buf);
1035 		buf = buf->frags;
1036 	}
1037 
1038 	return size;
1039 }
1040 
1041 size_t net_pkt_available_buffer(struct net_pkt *pkt)
1042 {
1043 	if (!pkt) {
1044 		return 0;
1045 	}
1046 
1047 	return pkt_get_max_len(pkt) - net_pkt_get_len(pkt);
1048 }
1049 
1050 size_t net_pkt_available_payload_buffer(struct net_pkt *pkt,
1051 					enum net_ip_protocol proto)
1052 {
1053 	size_t hdr_len = 0;
1054 	size_t len;
1055 
1056 	if (!pkt) {
1057 		return 0;
1058 	}
1059 
1060 	hdr_len = pkt_estimate_headers_length(pkt, net_pkt_family(pkt), proto);
1061 	len = net_pkt_get_len(pkt);
1062 
1063 	hdr_len = hdr_len <= len ? 0 : hdr_len - len;
1064 
1065 	len = net_pkt_available_buffer(pkt) - hdr_len;
1066 
1067 	return len;
1068 }
1069 
1070 void net_pkt_trim_buffer(struct net_pkt *pkt)
1071 {
1072 	struct net_buf *buf, *prev;
1073 
1074 	buf = pkt->buffer;
1075 	prev = buf;
1076 
1077 	while (buf) {
1078 		struct net_buf *next = buf->frags;
1079 
1080 		if (!buf->len) {
1081 			if (buf == pkt->buffer) {
1082 				pkt->buffer = next;
1083 			} else if (buf == prev->frags) {
1084 				prev->frags = next;
1085 			}
1086 
1087 			buf->frags = NULL;
1088 			net_buf_unref(buf);
1089 		} else {
1090 			prev = buf;
1091 		}
1092 
1093 		buf = next;
1094 	}
1095 }
1096 
1097 int net_pkt_remove_tail(struct net_pkt *pkt, size_t length)
1098 {
1099 	struct net_buf *buf = pkt->buffer;
1100 	size_t remaining_len = net_pkt_get_len(pkt);
1101 
1102 	if (remaining_len < length) {
1103 		return -EINVAL;
1104 	}
1105 
1106 	remaining_len -= length;
1107 
1108 	while (buf) {
1109 		if (buf->len >= remaining_len) {
1110 			buf->len = remaining_len;
1111 
1112 			if (buf->frags) {
1113 				net_pkt_frag_unref(buf->frags);
1114 				buf->frags = NULL;
1115 			}
1116 
1117 			break;
1118 		}
1119 
1120 		remaining_len -= buf->len;
1121 		buf = buf->frags;
1122 	}
1123 
1124 	return 0;
1125 }
1126 
1127 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1128 int net_pkt_alloc_buffer_debug(struct net_pkt *pkt,
1129 			       size_t size,
1130 			       enum net_ip_protocol proto,
1131 			       k_timeout_t timeout,
1132 			       const char *caller,
1133 			       int line)
1134 #else
1135 int net_pkt_alloc_buffer(struct net_pkt *pkt,
1136 			 size_t size,
1137 			 enum net_ip_protocol proto,
1138 			 k_timeout_t timeout)
1139 #endif
1140 {
1141 	struct net_buf_pool *pool = NULL;
1142 	size_t alloc_len = 0;
1143 	size_t hdr_len = 0;
1144 	struct net_buf *buf;
1145 
1146 	if (!size && proto == 0 && net_pkt_family(pkt) == AF_UNSPEC) {
1147 		return 0;
1148 	}
1149 
1150 	if (k_is_in_isr()) {
1151 		timeout = K_NO_WAIT;
1152 	}
1153 
1154 	/* Verifying existing buffer and take into account free space there */
1155 	alloc_len = net_pkt_available_buffer(pkt);
1156 	if (!alloc_len) {
1157 		/* In case of no free space, it will account for header
1158 		 * space estimation
1159 		 */
1160 		hdr_len = pkt_estimate_headers_length(pkt,
1161 						      net_pkt_family(pkt),
1162 						      proto);
1163 	}
1164 
1165 	/* Calculate the maximum that can be allocated depending on size */
1166 	alloc_len = pkt_buffer_length(pkt, size + hdr_len, proto, alloc_len);
1167 
1168 	NET_DBG("Data allocation maximum size %zu (requested %zu)",
1169 		alloc_len, size);
1170 
1171 	if (pkt->context) {
1172 		pool = get_data_pool(pkt->context);
1173 	}
1174 
1175 	if (!pool) {
1176 		pool = pkt->slab == &tx_pkts ? &tx_bufs : &rx_bufs;
1177 	}
1178 
1179 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1180 	buf = pkt_alloc_buffer(pool, alloc_len, timeout, caller, line);
1181 #else
1182 	buf = pkt_alloc_buffer(pool, alloc_len, timeout);
1183 #endif
1184 
1185 	if (!buf) {
1186 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1187 		NET_ERR("Data buffer (%zd) allocation failed (%s:%d)",
1188 			alloc_len, caller, line);
1189 #else
1190 		NET_ERR("Data buffer (%zd) allocation failed.", alloc_len);
1191 #endif
1192 		return -ENOMEM;
1193 	}
1194 
1195 	net_pkt_append_buffer(pkt, buf);
1196 
1197 	return 0;
1198 }
1199 
1200 
1201 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1202 int net_pkt_alloc_buffer_raw_debug(struct net_pkt *pkt, size_t size,
1203 				   k_timeout_t timeout, const char *caller,
1204 				   int line)
1205 #else
1206 int net_pkt_alloc_buffer_raw(struct net_pkt *pkt, size_t size,
1207 			     k_timeout_t timeout)
1208 #endif
1209 {
1210 	struct net_buf_pool *pool = NULL;
1211 	struct net_buf *buf;
1212 
1213 	if (size == 0) {
1214 		return 0;
1215 	}
1216 
1217 	if (k_is_in_isr()) {
1218 		timeout = K_NO_WAIT;
1219 	}
1220 
1221 	NET_DBG("Data allocation size %zu", size);
1222 
1223 	if (pkt->context) {
1224 		pool = get_data_pool(pkt->context);
1225 	}
1226 
1227 	if (!pool) {
1228 		pool = pkt->slab == &tx_pkts ? &tx_bufs : &rx_bufs;
1229 	}
1230 
1231 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1232 	buf = pkt_alloc_buffer(pool, size, timeout, caller, line);
1233 #else
1234 	buf = pkt_alloc_buffer(pool, size, timeout);
1235 #endif
1236 
1237 	if (!buf) {
1238 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1239 		NET_ERR("Data buffer (%zd) allocation failed (%s:%d)",
1240 			size, caller, line);
1241 #else
1242 		NET_ERR("Data buffer (%zd) allocation failed.", size);
1243 #endif
1244 		return -ENOMEM;
1245 	}
1246 
1247 	net_pkt_append_buffer(pkt, buf);
1248 
1249 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
1250 	/* net_buf allocators shrink the buffer size to the requested size.
1251 	 * We don't want this behavior here, so restore the real size of the
1252 	 * last fragment.
1253 	 */
1254 	buf = net_buf_frag_last(buf);
1255 	buf->size = CONFIG_NET_BUF_DATA_SIZE;
1256 #endif
1257 
1258 	return 0;
1259 }
1260 
1261 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1262 static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, k_timeout_t timeout,
1263 				 const char *caller, int line)
1264 #else
1265 static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, k_timeout_t timeout)
1266 #endif
1267 {
1268 	struct net_pkt *pkt;
1269 	uint32_t create_time;
1270 	int ret;
1271 
1272 	if (k_is_in_isr()) {
1273 		timeout = K_NO_WAIT;
1274 	}
1275 
1276 	if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) ||
1277 	    IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
1278 		create_time = k_cycle_get_32();
1279 	} else {
1280 		ARG_UNUSED(create_time);
1281 	}
1282 
1283 	ret = k_mem_slab_alloc(slab, (void **)&pkt, timeout);
1284 	if (ret) {
1285 		return NULL;
1286 	}
1287 
1288 	memset(pkt, 0, sizeof(struct net_pkt));
1289 
1290 	pkt->atomic_ref = ATOMIC_INIT(1);
1291 	pkt->slab = slab;
1292 
1293 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
1294 		net_pkt_set_ipv6_next_hdr(pkt, 255);
1295 	}
1296 
1297 #if defined(CONFIG_NET_TX_DEFAULT_PRIORITY)
1298 #define TX_DEFAULT_PRIORITY CONFIG_NET_TX_DEFAULT_PRIORITY
1299 #else
1300 #define TX_DEFAULT_PRIORITY 0
1301 #endif
1302 
1303 #if defined(CONFIG_NET_RX_DEFAULT_PRIORITY)
1304 #define RX_DEFAULT_PRIORITY CONFIG_NET_RX_DEFAULT_PRIORITY
1305 #else
1306 #define RX_DEFAULT_PRIORITY 0
1307 #endif
1308 
1309 	if (&tx_pkts == slab) {
1310 		net_pkt_set_priority(pkt, TX_DEFAULT_PRIORITY);
1311 	} else if (&rx_pkts == slab) {
1312 		net_pkt_set_priority(pkt, RX_DEFAULT_PRIORITY);
1313 	}
1314 
1315 	if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) ||
1316 	    IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
1317 		net_pkt_set_create_time(pkt, create_time);
1318 	}
1319 
1320 	net_pkt_set_vlan_tag(pkt, NET_VLAN_TAG_UNSPEC);
1321 
1322 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1323 	net_pkt_alloc_add(pkt, true, caller, line);
1324 #endif
1325 
1326 	net_pkt_cursor_init(pkt);
1327 
1328 	return pkt;
1329 }
1330 
1331 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1332 struct net_pkt *net_pkt_alloc_debug(k_timeout_t timeout,
1333 				    const char *caller, int line)
1334 #else
1335 struct net_pkt *net_pkt_alloc(k_timeout_t timeout)
1336 #endif
1337 {
1338 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1339 	return pkt_alloc(&tx_pkts, timeout, caller, line);
1340 #else
1341 	return pkt_alloc(&tx_pkts, timeout);
1342 #endif
1343 }
1344 
1345 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1346 struct net_pkt *net_pkt_alloc_from_slab_debug(struct k_mem_slab *slab,
1347 					      k_timeout_t timeout,
1348 					      const char *caller, int line)
1349 #else
1350 struct net_pkt *net_pkt_alloc_from_slab(struct k_mem_slab *slab,
1351 					k_timeout_t timeout)
1352 #endif
1353 {
1354 	if (!slab) {
1355 		return NULL;
1356 	}
1357 
1358 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1359 	return pkt_alloc(slab, timeout, caller, line);
1360 #else
1361 	return pkt_alloc(slab, timeout);
1362 #endif
1363 }
1364 
1365 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1366 struct net_pkt *net_pkt_rx_alloc_debug(k_timeout_t timeout,
1367 				       const char *caller, int line)
1368 #else
1369 struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout)
1370 #endif
1371 {
1372 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1373 	return pkt_alloc(&rx_pkts, timeout, caller, line);
1374 #else
1375 	return pkt_alloc(&rx_pkts, timeout);
1376 #endif
1377 }
1378 
1379 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1380 static struct net_pkt *pkt_alloc_on_iface(struct k_mem_slab *slab,
1381 					  struct net_if *iface,
1382 					  k_timeout_t timeout,
1383 					  const char *caller, int line)
1384 #else
1385 static struct net_pkt *pkt_alloc_on_iface(struct k_mem_slab *slab,
1386 					  struct net_if *iface,
1387 					  k_timeout_t timeout)
1388 
1389 #endif
1390 {
1391 	struct net_pkt *pkt;
1392 
1393 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1394 	pkt = pkt_alloc(slab, timeout, caller, line);
1395 #else
1396 	pkt = pkt_alloc(slab, timeout);
1397 #endif
1398 
1399 	if (pkt) {
1400 		net_pkt_set_iface(pkt, iface);
1401 	}
1402 
1403 	return pkt;
1404 }
1405 
1406 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1407 struct net_pkt *net_pkt_alloc_on_iface_debug(struct net_if *iface,
1408 					     k_timeout_t timeout,
1409 					     const char *caller,
1410 					     int line)
1411 #else
1412 struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface,
1413 				       k_timeout_t timeout)
1414 #endif
1415 {
1416 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1417 	return pkt_alloc_on_iface(&tx_pkts, iface, timeout, caller, line);
1418 #else
1419 	return pkt_alloc_on_iface(&tx_pkts, iface, timeout);
1420 #endif
1421 }
1422 
1423 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1424 struct net_pkt *net_pkt_rx_alloc_on_iface_debug(struct net_if *iface,
1425 						k_timeout_t timeout,
1426 						const char *caller,
1427 						int line)
1428 #else
1429 struct net_pkt *net_pkt_rx_alloc_on_iface(struct net_if *iface,
1430 					  k_timeout_t timeout)
1431 #endif
1432 {
1433 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1434 	return pkt_alloc_on_iface(&rx_pkts, iface, timeout, caller, line);
1435 #else
1436 	return pkt_alloc_on_iface(&rx_pkts, iface, timeout);
1437 #endif
1438 }
1439 
1440 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1441 static struct net_pkt *
1442 pkt_alloc_with_buffer(struct k_mem_slab *slab,
1443 		      struct net_if *iface,
1444 		      size_t size,
1445 		      sa_family_t family,
1446 		      enum net_ip_protocol proto,
1447 		      k_timeout_t timeout,
1448 		      const char *caller,
1449 		      int line)
1450 #else
1451 static struct net_pkt *
1452 pkt_alloc_with_buffer(struct k_mem_slab *slab,
1453 		      struct net_if *iface,
1454 		      size_t size,
1455 		      sa_family_t family,
1456 		      enum net_ip_protocol proto,
1457 		      k_timeout_t timeout)
1458 #endif
1459 {
1460 	k_timepoint_t end = sys_timepoint_calc(timeout);
1461 	struct net_pkt *pkt;
1462 	int ret;
1463 
1464 	NET_DBG("On iface %p size %zu", iface, size);
1465 
1466 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1467 	pkt = pkt_alloc_on_iface(slab, iface, timeout, caller, line);
1468 #else
1469 	pkt = pkt_alloc_on_iface(slab, iface, timeout);
1470 #endif
1471 
1472 	if (!pkt) {
1473 		return NULL;
1474 	}
1475 
1476 	net_pkt_set_family(pkt, family);
1477 
1478 	timeout = sys_timepoint_timeout(end);
1479 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1480 	ret = net_pkt_alloc_buffer_debug(pkt, size, proto, timeout,
1481 					 caller, line);
1482 #else
1483 	ret = net_pkt_alloc_buffer(pkt, size, proto, timeout);
1484 #endif
1485 
1486 	if (ret) {
1487 		net_pkt_unref(pkt);
1488 		return NULL;
1489 	}
1490 
1491 	return pkt;
1492 }
1493 
1494 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1495 struct net_pkt *net_pkt_alloc_with_buffer_debug(struct net_if *iface,
1496 						size_t size,
1497 						sa_family_t family,
1498 						enum net_ip_protocol proto,
1499 						k_timeout_t timeout,
1500 						const char *caller,
1501 						int line)
1502 #else
1503 struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface,
1504 					  size_t size,
1505 					  sa_family_t family,
1506 					  enum net_ip_protocol proto,
1507 					  k_timeout_t timeout)
1508 #endif
1509 {
1510 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1511 	return pkt_alloc_with_buffer(&tx_pkts, iface, size, family,
1512 				     proto, timeout, caller, line);
1513 #else
1514 	return pkt_alloc_with_buffer(&tx_pkts, iface, size, family,
1515 				     proto, timeout);
1516 #endif
1517 }
1518 
1519 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1520 struct net_pkt *net_pkt_rx_alloc_with_buffer_debug(struct net_if *iface,
1521 						   size_t size,
1522 						   sa_family_t family,
1523 						   enum net_ip_protocol proto,
1524 						   k_timeout_t timeout,
1525 						   const char *caller,
1526 						   int line)
1527 #else
1528 struct net_pkt *net_pkt_rx_alloc_with_buffer(struct net_if *iface,
1529 					     size_t size,
1530 					     sa_family_t family,
1531 					     enum net_ip_protocol proto,
1532 					     k_timeout_t timeout)
1533 #endif
1534 {
1535 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1536 	return pkt_alloc_with_buffer(&rx_pkts, iface, size, family,
1537 					proto, timeout, caller, line);
1538 #else
1539 	return pkt_alloc_with_buffer(&rx_pkts, iface, size, family,
1540 					proto, timeout);
1541 #endif
1542 }
1543 
1544 void net_pkt_append_buffer(struct net_pkt *pkt, struct net_buf *buffer)
1545 {
1546 	if (!pkt->buffer) {
1547 		pkt->buffer = buffer;
1548 		net_pkt_cursor_init(pkt);
1549 	} else {
1550 		net_buf_frag_insert(net_buf_frag_last(pkt->buffer), buffer);
1551 	}
1552 }
1553 
1554 void net_pkt_cursor_init(struct net_pkt *pkt)
1555 {
1556 	pkt->cursor.buf = pkt->buffer;
1557 	if (pkt->cursor.buf) {
1558 		pkt->cursor.pos = pkt->cursor.buf->data;
1559 	} else {
1560 		pkt->cursor.pos = NULL;
1561 	}
1562 }
1563 
1564 static void pkt_cursor_jump(struct net_pkt *pkt, bool write)
1565 {
1566 	struct net_pkt_cursor *cursor = &pkt->cursor;
1567 
1568 	cursor->buf = cursor->buf->frags;
1569 	while (cursor->buf) {
1570 		const size_t len =
1571 			write ? net_buf_max_len(cursor->buf) : cursor->buf->len;
1572 
1573 		if (!len) {
1574 			cursor->buf = cursor->buf->frags;
1575 		} else {
1576 			break;
1577 		}
1578 	}
1579 
1580 	if (cursor->buf) {
1581 		cursor->pos = cursor->buf->data;
1582 	} else {
1583 		cursor->pos = NULL;
1584 	}
1585 }
1586 
1587 static void pkt_cursor_advance(struct net_pkt *pkt, bool write)
1588 {
1589 	struct net_pkt_cursor *cursor = &pkt->cursor;
1590 	size_t len;
1591 
1592 	if (!cursor->buf) {
1593 		return;
1594 	}
1595 
1596 	len = write ? net_buf_max_len(cursor->buf) : cursor->buf->len;
1597 	if ((cursor->pos - cursor->buf->data) == len) {
1598 		pkt_cursor_jump(pkt, write);
1599 	}
1600 }
1601 
1602 static void pkt_cursor_update(struct net_pkt *pkt,
1603 			      size_t length, bool write)
1604 {
1605 	struct net_pkt_cursor *cursor = &pkt->cursor;
1606 	size_t len;
1607 
1608 	if (net_pkt_is_being_overwritten(pkt)) {
1609 		write = false;
1610 	}
1611 
1612 	len = write ? net_buf_max_len(cursor->buf) : cursor->buf->len;
1613 	if (length + (cursor->pos - cursor->buf->data) == len &&
1614 	    !(net_pkt_is_being_overwritten(pkt) &&
1615 	      len < net_buf_max_len(cursor->buf))) {
1616 		pkt_cursor_jump(pkt, write);
1617 	} else {
1618 		cursor->pos += length;
1619 	}
1620 }
1621 
1622 /* Internal function that does all operation (skip/read/write/memset) */
1623 static int net_pkt_cursor_operate(struct net_pkt *pkt,
1624 				  void *data, size_t length,
1625 				  bool copy, bool write)
1626 {
1627 	/* We use such variable to avoid lengthy lines */
1628 	struct net_pkt_cursor *c_op = &pkt->cursor;
1629 
1630 	while (c_op->buf && length) {
1631 		size_t d_len, len;
1632 
1633 		pkt_cursor_advance(pkt, net_pkt_is_being_overwritten(pkt) ?
1634 				   false : write);
1635 		if (c_op->buf == NULL) {
1636 			break;
1637 		}
1638 
1639 		if (write && !net_pkt_is_being_overwritten(pkt)) {
1640 			d_len = net_buf_max_len(c_op->buf) -
1641 				(c_op->pos - c_op->buf->data);
1642 		} else {
1643 			d_len = c_op->buf->len - (c_op->pos - c_op->buf->data);
1644 		}
1645 
1646 		if (!d_len) {
1647 			break;
1648 		}
1649 
1650 		if (length < d_len) {
1651 			len = length;
1652 		} else {
1653 			len = d_len;
1654 		}
1655 
1656 		if (copy && data) {
1657 			memcpy(write ? c_op->pos : data,
1658 			       write ? data : c_op->pos,
1659 			       len);
1660 		} else if (data) {
1661 			memset(c_op->pos, *(int *)data, len);
1662 		}
1663 
1664 		if (write && !net_pkt_is_being_overwritten(pkt)) {
1665 			net_buf_add(c_op->buf, len);
1666 		}
1667 
1668 		pkt_cursor_update(pkt, len, write);
1669 
1670 		if (copy && data) {
1671 			data = (uint8_t *) data + len;
1672 		}
1673 
1674 		length -= len;
1675 	}
1676 
1677 	if (length) {
1678 		NET_DBG("Still some length to go %zu", length);
1679 		return -ENOBUFS;
1680 	}
1681 
1682 	return 0;
1683 }
1684 
1685 int net_pkt_skip(struct net_pkt *pkt, size_t skip)
1686 {
1687 	NET_DBG("pkt %p skip %zu", pkt, skip);
1688 
1689 	return net_pkt_cursor_operate(pkt, NULL, skip, false, true);
1690 }
1691 
1692 int net_pkt_memset(struct net_pkt *pkt, int byte, size_t amount)
1693 {
1694 	NET_DBG("pkt %p byte %d amount %zu", pkt, byte, amount);
1695 
1696 	return net_pkt_cursor_operate(pkt, &byte, amount, false, true);
1697 }
1698 
1699 int net_pkt_read(struct net_pkt *pkt, void *data, size_t length)
1700 {
1701 	NET_DBG("pkt %p data %p length %zu", pkt, data, length);
1702 
1703 	return net_pkt_cursor_operate(pkt, data, length, true, false);
1704 }
1705 
1706 int net_pkt_read_be16(struct net_pkt *pkt, uint16_t *data)
1707 {
1708 	uint8_t d16[2];
1709 	int ret;
1710 
1711 	ret = net_pkt_read(pkt, d16, sizeof(uint16_t));
1712 
1713 	*data = d16[0] << 8 | d16[1];
1714 
1715 	return ret;
1716 }
1717 
1718 int net_pkt_read_le16(struct net_pkt *pkt, uint16_t *data)
1719 {
1720 	uint8_t d16[2];
1721 	int ret;
1722 
1723 	ret = net_pkt_read(pkt, d16, sizeof(uint16_t));
1724 
1725 	*data = d16[1] << 8 | d16[0];
1726 
1727 	return ret;
1728 }
1729 
1730 int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data)
1731 {
1732 	uint8_t d32[4];
1733 	int ret;
1734 
1735 	ret = net_pkt_read(pkt, d32, sizeof(uint32_t));
1736 
1737 	*data = d32[0] << 24 | d32[1] << 16 | d32[2] << 8 | d32[3];
1738 
1739 	return ret;
1740 }
1741 
1742 int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length)
1743 {
1744 	NET_DBG("pkt %p data %p length %zu", pkt, data, length);
1745 
1746 	if (data == pkt->cursor.pos && net_pkt_is_contiguous(pkt, length)) {
1747 		return net_pkt_skip(pkt, length);
1748 	}
1749 
1750 	return net_pkt_cursor_operate(pkt, (void *)data, length, true, true);
1751 }
1752 
1753 int net_pkt_copy(struct net_pkt *pkt_dst,
1754 		 struct net_pkt *pkt_src,
1755 		 size_t length)
1756 {
1757 	struct net_pkt_cursor *c_dst = &pkt_dst->cursor;
1758 	struct net_pkt_cursor *c_src = &pkt_src->cursor;
1759 
1760 	while (c_dst->buf && c_src->buf && length) {
1761 		size_t s_len, d_len, len;
1762 
1763 		pkt_cursor_advance(pkt_dst, true);
1764 		pkt_cursor_advance(pkt_src, false);
1765 
1766 		if (!c_dst->buf || !c_src->buf) {
1767 			break;
1768 		}
1769 
1770 		s_len = c_src->buf->len - (c_src->pos - c_src->buf->data);
1771 		d_len = net_buf_max_len(c_dst->buf) - (c_dst->pos - c_dst->buf->data);
1772 		if (length < s_len && length < d_len) {
1773 			len = length;
1774 		} else {
1775 			if (d_len < s_len) {
1776 				len = d_len;
1777 			} else {
1778 				len = s_len;
1779 			}
1780 		}
1781 
1782 		if (!len) {
1783 			break;
1784 		}
1785 
1786 		memcpy(c_dst->pos, c_src->pos, len);
1787 
1788 		if (!net_pkt_is_being_overwritten(pkt_dst)) {
1789 			net_buf_add(c_dst->buf, len);
1790 		}
1791 
1792 		pkt_cursor_update(pkt_dst, len, true);
1793 		pkt_cursor_update(pkt_src, len, false);
1794 
1795 		length -= len;
1796 	}
1797 
1798 	if (length) {
1799 		NET_DBG("Still some length to go %zu", length);
1800 		return -ENOBUFS;
1801 	}
1802 
1803 	return 0;
1804 }
1805 
1806 static int32_t net_pkt_find_offset(struct net_pkt *pkt, uint8_t *ptr)
1807 {
1808 	struct net_buf *buf;
1809 	uint32_t ret = -EINVAL;
1810 	uint16_t offset;
1811 
1812 	if (!ptr || !pkt || !pkt->buffer) {
1813 		return ret;
1814 	}
1815 
1816 	offset = 0U;
1817 	buf = pkt->buffer;
1818 
1819 	while (buf) {
1820 		if (buf->data <= ptr && ptr < (buf->data + buf->len)) {
1821 			ret = offset + (ptr - buf->data);
1822 			break;
1823 		}
1824 		offset += buf->len;
1825 		buf = buf->frags;
1826 	}
1827 
1828 	return ret;
1829 }
1830 
1831 static void clone_pkt_lladdr(struct net_pkt *pkt, struct net_pkt *clone_pkt,
1832 			     struct net_linkaddr *lladdr)
1833 {
1834 	int32_t ll_addr_offset;
1835 
1836 	if (!lladdr->addr)
1837 		return;
1838 
1839 	ll_addr_offset = net_pkt_find_offset(pkt, lladdr->addr);
1840 
1841 	if (ll_addr_offset >= 0) {
1842 		net_pkt_cursor_init(clone_pkt);
1843 		net_pkt_skip(clone_pkt, ll_addr_offset);
1844 		lladdr->addr = net_pkt_cursor_get_pos(clone_pkt);
1845 	}
1846 }
1847 
1848 #if defined(NET_PKT_HAS_CONTROL_BLOCK)
1849 static inline void clone_pkt_cb(struct net_pkt *pkt, struct net_pkt *clone_pkt)
1850 {
1851 	memcpy(net_pkt_cb(clone_pkt), net_pkt_cb(pkt), sizeof(clone_pkt->cb));
1852 }
1853 #else
1854 static inline void clone_pkt_cb(struct net_pkt *pkt, struct net_pkt *clone_pkt)
1855 {
1856 	ARG_UNUSED(pkt);
1857 	ARG_UNUSED(clone_pkt);
1858 }
1859 #endif
1860 
1861 static void clone_pkt_attributes(struct net_pkt *pkt, struct net_pkt *clone_pkt)
1862 {
1863 	net_pkt_set_family(clone_pkt, net_pkt_family(pkt));
1864 	net_pkt_set_context(clone_pkt, net_pkt_context(pkt));
1865 	net_pkt_set_ip_hdr_len(clone_pkt, net_pkt_ip_hdr_len(pkt));
1866 	net_pkt_set_ip_dscp(clone_pkt, net_pkt_ip_dscp(pkt));
1867 	net_pkt_set_ip_ecn(clone_pkt, net_pkt_ip_ecn(pkt));
1868 	net_pkt_set_vlan_tag(clone_pkt, net_pkt_vlan_tag(pkt));
1869 	net_pkt_set_timestamp(clone_pkt, net_pkt_timestamp(pkt));
1870 	net_pkt_set_priority(clone_pkt, net_pkt_priority(pkt));
1871 	net_pkt_set_orig_iface(clone_pkt, net_pkt_orig_iface(pkt));
1872 	net_pkt_set_captured(clone_pkt, net_pkt_is_captured(pkt));
1873 	net_pkt_set_eof(clone_pkt, net_pkt_eof(pkt));
1874 	net_pkt_set_ptp(clone_pkt, net_pkt_is_ptp(pkt));
1875 	net_pkt_set_tx_timestamping(clone_pkt, net_pkt_is_tx_timestamping(pkt));
1876 	net_pkt_set_rx_timestamping(clone_pkt, net_pkt_is_rx_timestamping(pkt));
1877 	net_pkt_set_forwarding(clone_pkt, net_pkt_forwarding(pkt));
1878 	net_pkt_set_chksum_done(clone_pkt, net_pkt_is_chksum_done(pkt));
1879 	net_pkt_set_ip_reassembled(pkt, net_pkt_is_ip_reassembled(pkt));
1880 
1881 	net_pkt_set_l2_bridged(clone_pkt, net_pkt_is_l2_bridged(pkt));
1882 	net_pkt_set_l2_processed(clone_pkt, net_pkt_is_l2_processed(pkt));
1883 	net_pkt_set_ll_proto_type(clone_pkt, net_pkt_ll_proto_type(pkt));
1884 
1885 	if (pkt->buffer && clone_pkt->buffer) {
1886 		memcpy(net_pkt_lladdr_src(clone_pkt), net_pkt_lladdr_src(pkt),
1887 		       sizeof(struct net_linkaddr));
1888 		memcpy(net_pkt_lladdr_dst(clone_pkt), net_pkt_lladdr_dst(pkt),
1889 		       sizeof(struct net_linkaddr));
1890 		/* The link header pointers are usable as-is if we
1891 		 * shallow-copied the buffer even if they point
1892 		 * into the fragment memory of the buffer,
1893 		 * otherwise we have to set the ll address pointer
1894 		 * relative to the new buffer to avoid dangling
1895 		 * pointers into the source packet.
1896 		 */
1897 		if (pkt->buffer != clone_pkt->buffer) {
1898 			clone_pkt_lladdr(pkt, clone_pkt, net_pkt_lladdr_src(clone_pkt));
1899 			clone_pkt_lladdr(pkt, clone_pkt, net_pkt_lladdr_dst(clone_pkt));
1900 		}
1901 	}
1902 
1903 	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
1904 		net_pkt_set_ipv4_ttl(clone_pkt, net_pkt_ipv4_ttl(pkt));
1905 		net_pkt_set_ipv4_opts_len(clone_pkt,
1906 					  net_pkt_ipv4_opts_len(pkt));
1907 	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
1908 		   net_pkt_family(pkt) == AF_INET6) {
1909 		net_pkt_set_ipv6_hop_limit(clone_pkt,
1910 					   net_pkt_ipv6_hop_limit(pkt));
1911 		net_pkt_set_ipv6_ext_len(clone_pkt, net_pkt_ipv6_ext_len(pkt));
1912 		net_pkt_set_ipv6_ext_opt_len(clone_pkt,
1913 					     net_pkt_ipv6_ext_opt_len(pkt));
1914 		net_pkt_set_ipv6_hdr_prev(clone_pkt,
1915 					  net_pkt_ipv6_hdr_prev(pkt));
1916 		net_pkt_set_ipv6_next_hdr(clone_pkt,
1917 					  net_pkt_ipv6_next_hdr(pkt));
1918 	}
1919 
1920 	clone_pkt_cb(pkt, clone_pkt);
1921 }
1922 
1923 static struct net_pkt *net_pkt_clone_internal(struct net_pkt *pkt,
1924 					      struct k_mem_slab *slab,
1925 					      k_timeout_t timeout)
1926 {
1927 	size_t cursor_offset = net_pkt_get_current_offset(pkt);
1928 	bool overwrite = net_pkt_is_being_overwritten(pkt);
1929 	struct net_pkt_cursor backup;
1930 	struct net_pkt *clone_pkt;
1931 
1932 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
1933 	clone_pkt = pkt_alloc_with_buffer(slab, net_pkt_iface(pkt),
1934 					  net_pkt_get_len(pkt),
1935 					  AF_UNSPEC, 0, timeout,
1936 					  __func__, __LINE__);
1937 #else
1938 	clone_pkt = pkt_alloc_with_buffer(slab, net_pkt_iface(pkt),
1939 					  net_pkt_get_len(pkt),
1940 					  AF_UNSPEC, 0, timeout);
1941 #endif
1942 	if (!clone_pkt) {
1943 		return NULL;
1944 	}
1945 
1946 	net_pkt_set_overwrite(pkt, true);
1947 	net_pkt_cursor_backup(pkt, &backup);
1948 	net_pkt_cursor_init(pkt);
1949 
1950 	if (net_pkt_copy(clone_pkt, pkt, net_pkt_get_len(pkt))) {
1951 		net_pkt_unref(clone_pkt);
1952 		net_pkt_cursor_restore(pkt, &backup);
1953 		net_pkt_set_overwrite(pkt, overwrite);
1954 		return NULL;
1955 	}
1956 	net_pkt_set_overwrite(clone_pkt, true);
1957 
1958 	clone_pkt_attributes(pkt, clone_pkt);
1959 
1960 	net_pkt_cursor_init(clone_pkt);
1961 
1962 	if (cursor_offset) {
1963 		net_pkt_skip(clone_pkt, cursor_offset);
1964 	}
1965 	net_pkt_set_overwrite(clone_pkt, overwrite);
1966 
1967 	net_pkt_cursor_restore(pkt, &backup);
1968 	net_pkt_set_overwrite(pkt, overwrite);
1969 
1970 	NET_DBG("Cloned %p to %p", pkt, clone_pkt);
1971 
1972 	return clone_pkt;
1973 }
1974 
1975 struct net_pkt *net_pkt_clone(struct net_pkt *pkt, k_timeout_t timeout)
1976 {
1977 	return net_pkt_clone_internal(pkt, pkt->slab, timeout);
1978 }
1979 
1980 struct net_pkt *net_pkt_rx_clone(struct net_pkt *pkt, k_timeout_t timeout)
1981 {
1982 	return net_pkt_clone_internal(pkt, &rx_pkts, timeout);
1983 }
1984 
1985 struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, k_timeout_t timeout)
1986 {
1987 	struct net_pkt *clone_pkt;
1988 	struct net_buf *buf;
1989 
1990 	clone_pkt = net_pkt_alloc(timeout);
1991 	if (!clone_pkt) {
1992 		return NULL;
1993 	}
1994 
1995 	net_pkt_set_iface(clone_pkt, net_pkt_iface(pkt));
1996 	clone_pkt->buffer = pkt->buffer;
1997 	buf = pkt->buffer;
1998 
1999 	net_pkt_frag_ref(buf);
2000 
2001 	clone_pkt_attributes(pkt, clone_pkt);
2002 
2003 	net_pkt_cursor_restore(clone_pkt, &pkt->cursor);
2004 
2005 	NET_DBG("Shallow cloned %p to %p", pkt, clone_pkt);
2006 
2007 	return clone_pkt;
2008 }
2009 
2010 size_t net_pkt_remaining_data(struct net_pkt *pkt)
2011 {
2012 	struct net_buf *buf;
2013 	size_t data_length;
2014 
2015 	if (!pkt || !pkt->cursor.buf || !pkt->cursor.pos) {
2016 		return 0;
2017 	}
2018 
2019 	buf = pkt->cursor.buf;
2020 	data_length = buf->len - (pkt->cursor.pos - buf->data);
2021 
2022 	buf = buf->frags;
2023 	while (buf) {
2024 		data_length += buf->len;
2025 		buf = buf->frags;
2026 	}
2027 
2028 	return data_length;
2029 }
2030 
2031 int net_pkt_update_length(struct net_pkt *pkt, size_t length)
2032 {
2033 	struct net_buf *buf;
2034 
2035 	for (buf = pkt->buffer; buf; buf = buf->frags) {
2036 		if (buf->len < length) {
2037 			length -= buf->len;
2038 		} else {
2039 			buf->len = length;
2040 			length = 0;
2041 		}
2042 	}
2043 
2044 	return !length ? 0 : -EINVAL;
2045 }
2046 
2047 int net_pkt_pull(struct net_pkt *pkt, size_t length)
2048 {
2049 	struct net_pkt_cursor *c_op = &pkt->cursor;
2050 
2051 	while (length) {
2052 		size_t left, rem;
2053 
2054 		pkt_cursor_advance(pkt, false);
2055 
2056 		if (!c_op->buf) {
2057 			break;
2058 		}
2059 
2060 		left = c_op->buf->len - (c_op->pos - c_op->buf->data);
2061 		if (!left) {
2062 			break;
2063 		}
2064 
2065 		rem = left;
2066 		if (rem > length) {
2067 			rem = length;
2068 		}
2069 
2070 		c_op->buf->len -= rem;
2071 		left -= rem;
2072 		if (left) {
2073 			memmove(c_op->pos, c_op->pos+rem, left);
2074 		} else {
2075 			struct net_buf *buf = pkt->buffer;
2076 
2077 			if (buf) {
2078 				pkt->buffer = buf->frags;
2079 				buf->frags = NULL;
2080 				net_buf_unref(buf);
2081 			}
2082 
2083 			net_pkt_cursor_init(pkt);
2084 		}
2085 
2086 		length -= rem;
2087 	}
2088 
2089 	net_pkt_cursor_init(pkt);
2090 
2091 	if (length) {
2092 		NET_DBG("Still some length to go %zu", length);
2093 		return -ENOBUFS;
2094 	}
2095 
2096 	return 0;
2097 }
2098 
2099 uint16_t net_pkt_get_current_offset(struct net_pkt *pkt)
2100 {
2101 	struct net_buf *buf = pkt->buffer;
2102 	uint16_t offset;
2103 
2104 	if (!pkt->cursor.buf || !pkt->cursor.pos) {
2105 		return 0;
2106 	}
2107 
2108 	offset = 0U;
2109 
2110 	while (buf != pkt->cursor.buf) {
2111 		offset += buf->len;
2112 		buf = buf->frags;
2113 	}
2114 
2115 	offset += pkt->cursor.pos - buf->data;
2116 
2117 	return offset;
2118 }
2119 
2120 bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size)
2121 {
2122 	size_t len = net_pkt_get_contiguous_len(pkt);
2123 
2124 	return len >= size;
2125 }
2126 
2127 size_t net_pkt_get_contiguous_len(struct net_pkt *pkt)
2128 {
2129 	pkt_cursor_advance(pkt, !net_pkt_is_being_overwritten(pkt));
2130 
2131 	if (pkt->cursor.buf && pkt->cursor.pos) {
2132 		size_t len;
2133 
2134 		len = net_pkt_is_being_overwritten(pkt) ?
2135 			pkt->cursor.buf->len : net_buf_max_len(pkt->cursor.buf);
2136 		len -= pkt->cursor.pos - pkt->cursor.buf->data;
2137 
2138 		return len;
2139 	}
2140 
2141 	return 0;
2142 }
2143 
2144 void *net_pkt_get_data(struct net_pkt *pkt,
2145 		       struct net_pkt_data_access *access)
2146 {
2147 	if (IS_ENABLED(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)) {
2148 		if (!net_pkt_is_contiguous(pkt, access->size)) {
2149 			return NULL;
2150 		}
2151 
2152 		return pkt->cursor.pos;
2153 	} else {
2154 		if (net_pkt_is_contiguous(pkt, access->size)) {
2155 			access->data = pkt->cursor.pos;
2156 		} else if (net_pkt_is_being_overwritten(pkt)) {
2157 			struct net_pkt_cursor backup;
2158 
2159 			if (!access->data) {
2160 				NET_ERR("Uncontiguous data"
2161 					" cannot be linearized");
2162 				return NULL;
2163 			}
2164 
2165 			net_pkt_cursor_backup(pkt, &backup);
2166 
2167 			if (net_pkt_read(pkt, access->data, access->size)) {
2168 				net_pkt_cursor_restore(pkt, &backup);
2169 				return NULL;
2170 			}
2171 
2172 			net_pkt_cursor_restore(pkt, &backup);
2173 		}
2174 
2175 		return access->data;
2176 	}
2177 
2178 	return NULL;
2179 }
2180 
2181 int net_pkt_set_data(struct net_pkt *pkt,
2182 		     struct net_pkt_data_access *access)
2183 {
2184 	if (IS_ENABLED(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)) {
2185 		return net_pkt_skip(pkt, access->size);
2186 	}
2187 
2188 	return net_pkt_write(pkt, access->data, access->size);
2189 }
2190 
2191 void net_pkt_init(void)
2192 {
2193 #if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
2194 	NET_DBG("Allocating %u RX (%zu bytes), %u TX (%zu bytes), "
2195 		"%d RX data (%u bytes) and %d TX data (%u bytes) buffers",
2196 		k_mem_slab_num_free_get(&rx_pkts),
2197 		(size_t)(k_mem_slab_num_free_get(&rx_pkts) *
2198 			 sizeof(struct net_pkt)),
2199 		k_mem_slab_num_free_get(&tx_pkts),
2200 		(size_t)(k_mem_slab_num_free_get(&tx_pkts) *
2201 			 sizeof(struct net_pkt)),
2202 		get_frees(&rx_bufs), get_size(&rx_bufs),
2203 		get_frees(&tx_bufs), get_size(&tx_bufs));
2204 #endif
2205 }
2206