xref: /freebsd/sys/compat/linuxkpi/common/include/linux/skbuff.h (revision a0ca4af9455b844c5e094fc1b09b1390ffa979fc)
1 /*-
2  * Copyright (c) 2020-2023 The FreeBSD Foundation
3  * Copyright (c) 2021-2023 Bjoern A. Zeeb
4  *
5  * This software was developed by Björn Zeeb under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * NOTE: this socket buffer compatibility code is highly EXPERIMENTAL.
32  *       Do not rely on the internals of this implementation.  They are highly
33  *       likely to change as we will improve the integration to FreeBSD mbufs.
34  */
35 
36 #ifndef	_LINUXKPI_LINUX_SKBUFF_H
37 #define	_LINUXKPI_LINUX_SKBUFF_H
38 
39 #include <linux/kernel.h>
40 #include <linux/page.h>
41 #include <linux/dma-mapping.h>
42 #include <linux/netdev_features.h>
43 #include <linux/list.h>
44 #include <linux/gfp.h>
45 #include <linux/compiler.h>
46 #include <linux/spinlock.h>
47 #include <linux/ktime.h>
48 
49 /* #define	SKB_DEBUG */
50 #ifdef SKB_DEBUG
51 #define	DSKB_TODO	0x01
52 #define	DSKB_IMPROVE	0x02
53 #define	DSKB_TRACE	0x10
54 #define	DSKB_TRACEX	0x20
55 extern int linuxkpi_debug_skb;
56 
57 #define	SKB_TODO()							\
58     if (linuxkpi_debug_skb & DSKB_TODO)					\
59 	printf("SKB_TODO %s:%d\n", __func__, __LINE__)
60 #define	SKB_IMPROVE(...)						\
61     if (linuxkpi_debug_skb & DSKB_IMPROVE)				\
62 	printf("SKB_IMPROVE %s:%d\n", __func__, __LINE__)
63 #define	SKB_TRACE(_s)							\
64     if (linuxkpi_debug_skb & DSKB_TRACE)				\
65 	printf("SKB_TRACE %s:%d %p\n", __func__, __LINE__, _s)
66 #define	SKB_TRACE2(_s, _p)						\
67     if (linuxkpi_debug_skb & DSKB_TRACE)				\
68 	printf("SKB_TRACE %s:%d %p, %p\n", __func__, __LINE__, _s, _p)
69 #define	SKB_TRACE_FMT(_s, _fmt, ...)					\
70    if (linuxkpi_debug_skb & DSKB_TRACE)					\
71 	printf("SKB_TRACE %s:%d %p " _fmt "\n", __func__, __LINE__, _s,	\
72 	    __VA_ARGS__)
73 #else
74 #define	SKB_TODO()		do { } while(0)
75 #define	SKB_IMPROVE(...)	do { } while(0)
76 #define	SKB_TRACE(_s)		do { } while(0)
77 #define	SKB_TRACE2(_s, _p)	do { } while(0)
78 #define	SKB_TRACE_FMT(_s, ...)	do { } while(0)
79 #endif
80 
81 enum sk_buff_pkt_type {
82 	PACKET_BROADCAST,
83 	PACKET_MULTICAST,
84 	PACKET_OTHERHOST,
85 };
86 
87 struct skb_shared_hwtstamps {
88 	ktime_t			hwtstamp;
89 };
90 
91 #define	NET_SKB_PAD		max(CACHE_LINE_SIZE, 32)
92 #define	SKB_DATA_ALIGN(_x)	roundup2(_x, CACHE_LINE_SIZE)
93 
94 struct sk_buff_head {
95 		/* XXX TODO */
96 	union {
97 		struct {
98 			struct sk_buff		*next;
99 			struct sk_buff		*prev;
100 		};
101 		struct sk_buff_head_l {
102 			struct sk_buff		*next;
103 			struct sk_buff		*prev;
104 		} list;
105 	};
106 	size_t			qlen;
107 	spinlock_t		lock;
108 };
109 
110 enum sk_checksum_flags {
111 	CHECKSUM_NONE			= 0x00,
112 	CHECKSUM_UNNECESSARY		= 0x01,
113 	CHECKSUM_PARTIAL		= 0x02,
114 	CHECKSUM_COMPLETE		= 0x04,
115 };
116 
117 struct skb_frag {
118 		/* XXX TODO */
119 	struct page		*page;		/* XXX-BZ These three are a wild guess so far! */
120 	off_t			offset;
121 	size_t			size;
122 };
123 typedef	struct skb_frag	skb_frag_t;
124 
125 enum skb_shared_info_gso_type {
126 	SKB_GSO_TCPV4,
127 	SKB_GSO_TCPV6,
128 };
129 
130 struct skb_shared_info {
131 	enum skb_shared_info_gso_type	gso_type;
132 	uint16_t			gso_size;
133 	uint16_t			nr_frags;
134 	struct sk_buff			*frag_list;
135 	skb_frag_t			frags[64];	/* XXX TODO, 16xpage? */
136 };
137 
138 struct sk_buff {
139 	/* XXX TODO */
140 	union {
141 		/* struct sk_buff_head */
142 		struct {
143 			struct sk_buff		*next;
144 			struct sk_buff		*prev;
145 		};
146 		struct list_head	list;
147 	};
148 	uint32_t		_alloc_len;	/* Length of alloc data-buf. XXX-BZ give up for truesize? */
149 	uint32_t		len;		/* ? */
150 	uint32_t		data_len;	/* ? If we have frags? */
151 	uint32_t		truesize;	/* The total size of all buffers, incl. frags. */
152 	uint16_t		mac_len;	/* Link-layer header length. */
153 	__sum16			csum;
154 	uint16_t		l3hdroff;	/* network header offset from *head */
155 	uint16_t		l4hdroff;	/* transport header offset from *head */
156 	uint32_t		priority;
157 	uint16_t		qmap;		/* queue mapping */
158 	uint16_t		_flags;		/* Internal flags. */
159 #define	_SKB_FLAGS_SKBEXTFRAG	0x0001
160 	enum sk_buff_pkt_type	pkt_type;
161 	uint16_t		mac_header;	/* offset of mac_header */
162 
163 	/* "Scratch" area for layers to store metadata. */
164 	/* ??? I see sizeof() operations so probably an array. */
165 	uint8_t			cb[64] __aligned(CACHE_LINE_SIZE);
166 
167 	struct net_device	*dev;
168 	void			*sk;		/* XXX net/sock.h? */
169 
170 	int		csum_offset, csum_start, ip_summed, protocol;
171 
172 	uint8_t			*head;			/* Head of buffer. */
173 	uint8_t			*data;			/* Head of data. */
174 	uint8_t			*tail;			/* End of data. */
175 	uint8_t			*end;			/* End of buffer. */
176 
177 	struct skb_shared_info	*shinfo;
178 
179 	/* FreeBSD specific bandaid (see linuxkpi_kfree_skb). */
180 	void			*m;
181 	void(*m_free_func)(void *);
182 
183 	/* Force padding to CACHE_LINE_SIZE. */
184 	uint8_t			__scratch[0] __aligned(CACHE_LINE_SIZE);
185 };
186 
187 /* -------------------------------------------------------------------------- */
188 
189 struct sk_buff *linuxkpi_alloc_skb(size_t, gfp_t);
190 struct sk_buff *linuxkpi_dev_alloc_skb(size_t, gfp_t);
191 struct sk_buff *linuxkpi_build_skb(void *, size_t);
192 void linuxkpi_kfree_skb(struct sk_buff *);
193 
194 struct sk_buff *linuxkpi_skb_copy(struct sk_buff *, gfp_t);
195 
196 /* -------------------------------------------------------------------------- */
197 
198 static inline struct sk_buff *
199 alloc_skb(size_t size, gfp_t gfp)
200 {
201 	struct sk_buff *skb;
202 
203 	skb = linuxkpi_alloc_skb(size, gfp);
204 	SKB_TRACE(skb);
205 	return (skb);
206 }
207 
208 static inline struct sk_buff *
209 __dev_alloc_skb(size_t len, gfp_t gfp)
210 {
211 	struct sk_buff *skb;
212 
213 	skb = linuxkpi_dev_alloc_skb(len, gfp);
214 	SKB_IMPROVE();
215 	SKB_TRACE(skb);
216 	return (skb);
217 }
218 
219 static inline struct sk_buff *
220 dev_alloc_skb(size_t len)
221 {
222 	struct sk_buff *skb;
223 
224 	skb = __dev_alloc_skb(len, GFP_NOWAIT);
225 	SKB_IMPROVE();
226 	SKB_TRACE(skb);
227 	return (skb);
228 }
229 
230 static inline void
231 kfree_skb(struct sk_buff *skb)
232 {
233 	SKB_TRACE(skb);
234 	linuxkpi_kfree_skb(skb);
235 }
236 
237 static inline void
238 dev_kfree_skb(struct sk_buff *skb)
239 {
240 	SKB_TRACE(skb);
241 	kfree_skb(skb);
242 }
243 
244 static inline void
245 dev_kfree_skb_any(struct sk_buff *skb)
246 {
247 	SKB_TRACE(skb);
248 	dev_kfree_skb(skb);
249 }
250 
251 static inline void
252 dev_kfree_skb_irq(struct sk_buff *skb)
253 {
254 	SKB_TRACE(skb);
255 	SKB_IMPROVE("Do we have to defer this?");
256 	dev_kfree_skb(skb);
257 }
258 
259 static inline struct sk_buff *
260 build_skb(void *data, unsigned int fragsz)
261 {
262 	struct sk_buff *skb;
263 
264 	skb = linuxkpi_build_skb(data, fragsz);
265 	SKB_TRACE(skb);
266 	return (skb);
267 }
268 
269 /* -------------------------------------------------------------------------- */
270 
271 /* XXX BZ review this one for terminal condition as Linux "queues" are special. */
272 #define	skb_list_walk_safe(_q, skb, tmp)				\
273 	for ((skb) = (_q)->next; (skb) != NULL && ((tmp) = (skb)->next); (skb) = (tmp))
274 
275 /* Add headroom; cannot do once there is data in there. */
276 static inline void
277 skb_reserve(struct sk_buff *skb, size_t len)
278 {
279 	SKB_TRACE(skb);
280 #if 0
281 	/* Apparently it is allowed to call skb_reserve multiple times in a row. */
282 	KASSERT(skb->data == skb->head, ("%s: skb %p not empty head %p data %p "
283 	    "tail %p\n", __func__, skb, skb->head, skb->data, skb->tail));
284 #else
285 	KASSERT(skb->len == 0 && skb->data == skb->tail, ("%s: skb %p not "
286 	    "empty head %p data %p tail %p len %u\n", __func__, skb,
287 	    skb->head, skb->data, skb->tail, skb->len));
288 #endif
289 	skb->data += len;
290 	skb->tail += len;
291 }
292 
293 /*
294  * Remove headroom; return new data pointer; basically make space at the
295  * front to copy data in (manually).
296  */
297 static inline void *
298 __skb_push(struct sk_buff *skb, size_t len)
299 {
300 	SKB_TRACE(skb);
301 	KASSERT(((skb->data - len) >= skb->head), ("%s: skb %p (data %p - "
302 	    "len %zu) < head %p\n", __func__, skb, skb->data, len, skb->data));
303 	skb->len  += len;
304 	skb->data -= len;
305 	return (skb->data);
306 }
307 
308 static inline void *
309 skb_push(struct sk_buff *skb, size_t len)
310 {
311 
312 	SKB_TRACE(skb);
313 	return (__skb_push(skb, len));
314 }
315 
316 /*
317  * Length of the data on the skb (without any frags)???
318  */
319 static inline size_t
320 skb_headlen(struct sk_buff *skb)
321 {
322 
323 	SKB_TRACE(skb);
324 	return (skb->len - skb->data_len);
325 }
326 
327 
328 /* Return the end of data (tail pointer). */
329 static inline uint8_t *
330 skb_tail_pointer(struct sk_buff *skb)
331 {
332 
333 	SKB_TRACE(skb);
334 	return (skb->tail);
335 }
336 
337 /* Return number of bytes available at end of buffer. */
338 static inline unsigned int
339 skb_tailroom(struct sk_buff *skb)
340 {
341 
342 	SKB_TRACE(skb);
343 	KASSERT((skb->end - skb->tail) >= 0, ("%s: skb %p tailroom < 0, "
344 	    "end %p tail %p\n", __func__, skb, skb->end, skb->tail));
345 	return (skb->end - skb->tail);
346 }
347 
348 /* Return numer of bytes available at the beginning of buffer. */
349 static inline unsigned int
350 skb_headroom(struct sk_buff *skb)
351 {
352 	SKB_TRACE(skb);
353 	KASSERT((skb->data - skb->head) >= 0, ("%s: skb %p headroom < 0, "
354 	    "data %p head %p\n", __func__, skb, skb->data, skb->head));
355 	return (skb->data - skb->head);
356 }
357 
358 
359 /*
360  * Remove tailroom; return the old tail pointer; basically make space at
361  * the end to copy data in (manually).  See also skb_put_data() below.
362  */
363 static inline void *
364 __skb_put(struct sk_buff *skb, size_t len)
365 {
366 	void *s;
367 
368 	SKB_TRACE(skb);
369 	KASSERT(((skb->tail + len) <= skb->end), ("%s: skb %p (tail %p + "
370 	    "len %zu) > end %p, head %p data %p len %u\n", __func__,
371 	    skb, skb->tail, len, skb->end, skb->head, skb->data, skb->len));
372 
373 	s = skb_tail_pointer(skb);
374 	if (len == 0)
375 		return (s);
376 	skb->tail += len;
377 	skb->len += len;
378 #ifdef SKB_DEBUG
379 	if (linuxkpi_debug_skb & DSKB_TRACEX)
380 	printf("%s: skb %p (%u) head %p data %p tail %p end %p, s %p len %zu\n",
381 	    __func__, skb, skb->len, skb->head, skb->data, skb->tail, skb->end,
382 	    s, len);
383 #endif
384 	return (s);
385 }
386 
387 static inline void *
388 skb_put(struct sk_buff *skb, size_t len)
389 {
390 
391 	SKB_TRACE(skb);
392 	return (__skb_put(skb, len));
393 }
394 
395 /* skb_put() + copying data in. */
396 static inline void *
397 skb_put_data(struct sk_buff *skb, const void *buf, size_t len)
398 {
399 	void *s;
400 
401 	SKB_TRACE2(skb, buf);
402 	s = skb_put(skb, len);
403 	if (len == 0)
404 		return (s);
405 	memcpy(s, buf, len);
406 	return (s);
407 }
408 
409 /* skb_put() + filling with zeros. */
410 static inline void *
411 skb_put_zero(struct sk_buff *skb, size_t len)
412 {
413 	void *s;
414 
415 	SKB_TRACE(skb);
416 	s = skb_put(skb, len);
417 	memset(s, '\0', len);
418 	return (s);
419 }
420 
421 /*
422  * Remove len bytes from beginning of data.
423  *
424  * XXX-BZ ath10k checks for !NULL conditions so I assume this doesn't panic;
425  * we return the advanced data pointer so we don't have to keep a temp, correct?
426  */
427 static inline void *
428 skb_pull(struct sk_buff *skb, size_t len)
429 {
430 
431 	SKB_TRACE(skb);
432 #if 0	/* Apparently this doesn't barf... */
433 	KASSERT(skb->len >= len, ("%s: skb %p skb->len %u < len %u, data %p\n",
434 	    __func__, skb, skb->len, len, skb->data));
435 #endif
436 	if (skb->len < len)
437 		return (NULL);
438 	skb->len -= len;
439 	skb->data += len;
440 	return (skb->data);
441 }
442 
443 /* Reduce skb data to given length or do nothing if smaller already. */
444 static inline void
445 __skb_trim(struct sk_buff *skb, unsigned int len)
446 {
447 
448 	SKB_TRACE(skb);
449 	if (skb->len < len)
450 		return;
451 
452 	skb->len = len;
453 	skb->tail = skb->data + skb->len;
454 }
455 
456 static inline void
457 skb_trim(struct sk_buff *skb, unsigned int len)
458 {
459 
460 	return (__skb_trim(skb, len));
461 }
462 
463 static inline struct skb_shared_info *
464 skb_shinfo(struct sk_buff *skb)
465 {
466 
467 	SKB_TRACE(skb);
468 	return (skb->shinfo);
469 }
470 
471 static inline void
472 skb_add_rx_frag(struct sk_buff *skb, int fragno, struct page *page,
473     off_t offset, size_t size, unsigned int truesize)
474 {
475 	struct skb_shared_info *shinfo;
476 
477 	SKB_TRACE(skb);
478 #ifdef SKB_DEBUG
479 	if (linuxkpi_debug_skb & DSKB_TRACEX)
480 	printf("%s: skb %p head %p data %p tail %p end %p len %u fragno %d "
481 	    "page %#jx offset %ju size %zu truesize %u\n", __func__,
482 	    skb, skb->head, skb->data, skb->tail, skb->end, skb->len, fragno,
483 	    (uintmax_t)(uintptr_t)linux_page_address(page), (uintmax_t)offset,
484 	    size, truesize);
485 #endif
486 
487 	shinfo = skb_shinfo(skb);
488 	KASSERT(fragno >= 0 && fragno < nitems(shinfo->frags), ("%s: skb %p "
489 	    "fragno %d too big\n", __func__, skb, fragno));
490 	shinfo->frags[fragno].page = page;
491 	shinfo->frags[fragno].offset = offset;
492 	shinfo->frags[fragno].size = size;
493 	shinfo->nr_frags = fragno + 1;
494         skb->len += size;
495 	skb->data_len += size;
496         skb->truesize += truesize;
497 
498 	/* XXX TODO EXTEND truesize? */
499 }
500 
501 /* -------------------------------------------------------------------------- */
502 
503 /* XXX BZ review this one for terminal condition as Linux "queues" are special. */
504 #define	skb_queue_walk(_q, skb)						\
505 	for ((skb) = (_q)->next; (skb) != (struct sk_buff *)(_q);	\
506 	    (skb) = (skb)->next)
507 
508 #define	skb_queue_walk_safe(_q, skb, tmp)				\
509 	for ((skb) = (_q)->next, (tmp) = (skb)->next;			\
510 	    (skb) != (struct sk_buff *)(_q); (skb) = (tmp), (tmp) = (skb)->next)
511 
512 static inline bool
513 skb_queue_empty(struct sk_buff_head *q)
514 {
515 
516 	SKB_TRACE(q);
517 	return (q->qlen == 0);
518 }
519 
520 static inline void
521 __skb_queue_head_init(struct sk_buff_head *q)
522 {
523 	SKB_TRACE(q);
524 	q->prev = q->next = (struct sk_buff *)q;
525 	q->qlen = 0;
526 }
527 
528 static inline void
529 skb_queue_head_init(struct sk_buff_head *q)
530 {
531 	SKB_TRACE(q);
532 	return (__skb_queue_head_init(q));
533 }
534 
535 static inline void
536 __skb_insert(struct sk_buff *new, struct sk_buff *prev, struct sk_buff *next,
537     struct sk_buff_head *q)
538 {
539 
540 	SKB_TRACE_FMT(new, "prev %p next %p q %p", prev, next, q);
541 	new->prev = prev;
542 	new->next = next;
543 	((struct sk_buff_head_l *)next)->prev = new;
544 	((struct sk_buff_head_l *)prev)->next = new;
545 	q->qlen++;
546 }
547 
548 static inline void
549 __skb_queue_after(struct sk_buff_head *q, struct sk_buff *skb,
550     struct sk_buff *new)
551 {
552 
553 	SKB_TRACE_FMT(q, "skb %p new %p", skb, new);
554 	__skb_insert(new, skb, ((struct sk_buff_head_l *)skb)->next, q);
555 }
556 
557 static inline void
558 __skb_queue_before(struct sk_buff_head *q, struct sk_buff *skb,
559     struct sk_buff *new)
560 {
561 
562 	SKB_TRACE_FMT(q, "skb %p new %p", skb, new);
563 	__skb_insert(new, skb->prev, skb, q);
564 }
565 
566 static inline void
567 __skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new)
568 {
569 
570 	SKB_TRACE2(q, new);
571 	__skb_queue_before(q, (struct sk_buff *)q, new);
572 }
573 
574 static inline void
575 skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new)
576 {
577 	SKB_TRACE2(q, new);
578 	return (__skb_queue_tail(q, new));
579 }
580 
581 static inline struct sk_buff *
582 skb_peek(struct sk_buff_head *q)
583 {
584 	struct sk_buff *skb;
585 
586 	skb = q->next;
587 	SKB_TRACE2(q, skb);
588 	if (skb == (struct sk_buff *)q)
589 		return (NULL);
590 	return (skb);
591 }
592 
593 static inline struct sk_buff *
594 skb_peek_tail(struct sk_buff_head *q)
595 {
596 	struct sk_buff *skb;
597 
598 	skb = q->prev;
599 	SKB_TRACE2(q, skb);
600 	if (skb == (struct sk_buff *)q)
601 		return (NULL);
602 	return (skb);
603 }
604 
605 static inline void
606 __skb_unlink(struct sk_buff *skb, struct sk_buff_head *head)
607 {
608 	SKB_TRACE2(skb, head);
609 	struct sk_buff *p, *n;;
610 
611 	head->qlen--;
612 	p = skb->prev;
613 	n = skb->next;
614 	p->next = n;
615 	n->prev = p;
616 	skb->prev = skb->next = NULL;
617 }
618 
619 static inline void
620 skb_unlink(struct sk_buff *skb, struct sk_buff_head *head)
621 {
622 	SKB_TRACE2(skb, head);
623 	return (__skb_unlink(skb, head));
624 }
625 
626 static inline struct sk_buff *
627 __skb_dequeue(struct sk_buff_head *q)
628 {
629 	struct sk_buff *skb;
630 
631 	SKB_TRACE(q);
632 	skb = q->next;
633 	if (skb == (struct sk_buff *)q)
634 		return (NULL);
635 	if (skb != NULL)
636 		__skb_unlink(skb, q);
637 	SKB_TRACE(skb);
638 	return (skb);
639 }
640 
641 static inline struct sk_buff *
642 skb_dequeue(struct sk_buff_head *q)
643 {
644 	SKB_TRACE(q);
645 	return (__skb_dequeue(q));
646 }
647 
648 static inline struct sk_buff *
649 skb_dequeue_tail(struct sk_buff_head *q)
650 {
651 	struct sk_buff *skb;
652 
653 	skb = skb_peek_tail(q);
654 	if (skb != NULL)
655 		__skb_unlink(skb, q);
656 
657 	SKB_TRACE2(q, skb);
658 	return (skb);
659 }
660 
661 static inline void
662 __skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb)
663 {
664 
665 	SKB_TRACE2(q, skb);
666 	__skb_queue_after(q, (struct sk_buff *)q, skb);
667 }
668 
669 static inline void
670 skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb)
671 {
672 
673 	SKB_TRACE2(q, skb);
674 	__skb_queue_after(q, (struct sk_buff *)q, skb);
675 }
676 
677 static inline uint32_t
678 skb_queue_len(struct sk_buff_head *head)
679 {
680 
681 	SKB_TRACE(head);
682 	return (head->qlen);
683 }
684 
685 static inline uint32_t
686 skb_queue_len_lockless(const struct sk_buff_head *head)
687 {
688 
689 	SKB_TRACE(head);
690 	return (READ_ONCE(head->qlen));
691 }
692 
693 static inline void
694 __skb_queue_purge(struct sk_buff_head *q)
695 {
696 	struct sk_buff *skb;
697 
698 	SKB_TRACE(q);
699         while ((skb = __skb_dequeue(q)) != NULL)
700 		kfree_skb(skb);
701 }
702 
703 static inline void
704 skb_queue_purge(struct sk_buff_head *q)
705 {
706 	SKB_TRACE(q);
707 	return (__skb_queue_purge(q));
708 }
709 
710 static inline struct sk_buff *
711 skb_queue_prev(struct sk_buff_head *q, struct sk_buff *skb)
712 {
713 
714 	SKB_TRACE2(q, skb);
715 	/* XXX what is the q argument good for? */
716 	return (skb->prev);
717 }
718 
719 /* -------------------------------------------------------------------------- */
720 
721 static inline struct sk_buff *
722 skb_copy(struct sk_buff *skb, gfp_t gfp)
723 {
724 	struct sk_buff *new;
725 
726 	new = linuxkpi_skb_copy(skb, gfp);
727 	SKB_TRACE2(skb, new);
728 	return (new);
729 }
730 
731 static inline void
732 consume_skb(struct sk_buff *skb)
733 {
734 	SKB_TRACE(skb);
735 	SKB_TODO();
736 }
737 
738 static inline uint16_t
739 skb_checksum(struct sk_buff *skb, int offs, size_t len, int x)
740 {
741 	SKB_TRACE(skb);
742 	SKB_TODO();
743 	return (0xffff);
744 }
745 
746 static inline int
747 skb_checksum_start_offset(struct sk_buff *skb)
748 {
749 	SKB_TRACE(skb);
750 	SKB_TODO();
751 	return (-1);
752 }
753 
754 static inline dma_addr_t
755 skb_frag_dma_map(struct device *dev, const skb_frag_t *frag, int x,
756     size_t fragsz, enum dma_data_direction dir)
757 {
758 	SKB_TRACE2(frag, dev);
759 	SKB_TODO();
760 	return (-1);
761 }
762 
763 static inline size_t
764 skb_frag_size(const skb_frag_t *frag)
765 {
766 	SKB_TRACE(frag);
767 	SKB_TODO();
768 	return (-1);
769 }
770 
771 #define	skb_walk_frags(_skb, _frag)					\
772 	for ((_frag) = (_skb); false; (_frag)++)
773 
774 static inline void
775 skb_checksum_help(struct sk_buff *skb)
776 {
777 	SKB_TRACE(skb);
778 	SKB_TODO();
779 }
780 
781 static inline bool
782 skb_ensure_writable(struct sk_buff *skb, size_t off)
783 {
784 	SKB_TRACE(skb);
785 	SKB_TODO();
786 	return (false);
787 }
788 
789 static inline void *
790 skb_frag_address(const skb_frag_t *frag)
791 {
792 	SKB_TRACE(frag);
793 	SKB_TODO();
794 	return (NULL);
795 }
796 
797 static inline void
798 skb_free_frag(void *frag)
799 {
800 
801 	page_frag_free(frag);
802 }
803 
804 static inline struct sk_buff *
805 skb_gso_segment(struct sk_buff *skb, netdev_features_t netdev_flags)
806 {
807 	SKB_TRACE(skb);
808 	SKB_TODO();
809 	return (NULL);
810 }
811 
812 static inline bool
813 skb_is_gso(struct sk_buff *skb)
814 {
815 	SKB_TRACE(skb);
816 	SKB_IMPROVE("Really a TODO but get it away from logging");
817 	return (false);
818 }
819 
820 static inline void
821 skb_mark_not_on_list(struct sk_buff *skb)
822 {
823 	SKB_TRACE(skb);
824 	SKB_TODO();
825 }
826 
827 static inline void
828 ___skb_queue_splice(const struct sk_buff_head *from,
829     struct sk_buff *p, struct sk_buff *n)
830 {
831 	struct sk_buff *b, *e;
832 
833 	b = from->next;
834 	e = from->prev;
835 
836 	b->prev = p;
837 	((struct sk_buff_head_l *)p)->next = b;
838 	e->next = n;
839 	((struct sk_buff_head_l *)n)->prev = e;
840 }
841 
842 static inline void
843 skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to)
844 {
845 
846 	SKB_TRACE2(from, to);
847 
848 	if (skb_queue_empty(from))
849 		return;
850 
851 	___skb_queue_splice(from, (struct sk_buff *)to, to->next);
852 	to->qlen += from->qlen;
853 	__skb_queue_head_init(from);
854 }
855 
856 static inline void
857 skb_queue_splice_tail_init(struct sk_buff_head *from, struct sk_buff_head *to)
858 {
859 
860 	SKB_TRACE2(from, to);
861 
862 	if (skb_queue_empty(from))
863 		return;
864 
865 	___skb_queue_splice(from, to->prev, (struct sk_buff *)to);
866 	to->qlen += from->qlen;
867 	__skb_queue_head_init(from);
868 }
869 
870 static inline void
871 skb_reset_transport_header(struct sk_buff *skb)
872 {
873 
874 	SKB_TRACE(skb);
875 	skb->l4hdroff = skb->data - skb->head;
876 }
877 
878 static inline uint8_t *
879 skb_transport_header(struct sk_buff *skb)
880 {
881 
882 	SKB_TRACE(skb);
883         return (skb->head + skb->l4hdroff);
884 }
885 
886 static inline uint8_t *
887 skb_network_header(struct sk_buff *skb)
888 {
889 
890 	SKB_TRACE(skb);
891         return (skb->head + skb->l3hdroff);
892 }
893 
894 static inline bool
895 skb_is_nonlinear(struct sk_buff *skb)
896 {
897 	SKB_TRACE(skb);
898 	return ((skb->data_len > 0) ? true : false);
899 }
900 
901 static inline int
902 __skb_linearize(struct sk_buff *skb)
903 {
904 	SKB_TRACE(skb);
905 	SKB_TODO();
906 	return (ENXIO);
907 }
908 
909 static inline int
910 skb_linearize(struct sk_buff *skb)
911 {
912 
913 	return (skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0);
914 }
915 
916 static inline int
917 pskb_expand_head(struct sk_buff *skb, int x, int len, gfp_t gfp)
918 {
919 	SKB_TRACE(skb);
920 	SKB_TODO();
921 	return (-ENXIO);
922 }
923 
924 /* Not really seen this one but need it as symmetric accessor function. */
925 static inline void
926 skb_set_queue_mapping(struct sk_buff *skb, uint16_t qmap)
927 {
928 
929 	SKB_TRACE_FMT(skb, "qmap %u", qmap);
930 	skb->qmap = qmap;
931 }
932 
933 static inline uint16_t
934 skb_get_queue_mapping(struct sk_buff *skb)
935 {
936 
937 	SKB_TRACE_FMT(skb, "qmap %u", skb->qmap);
938 	return (skb->qmap);
939 }
940 
941 static inline bool
942 skb_header_cloned(struct sk_buff *skb)
943 {
944 	SKB_TRACE(skb);
945 	SKB_TODO();
946 	return (false);
947 }
948 
949 static inline uint8_t *
950 skb_mac_header(const struct sk_buff *skb)
951 {
952 	SKB_TRACE(skb);
953 	return (skb->head + skb->mac_header);
954 }
955 
956 static inline void
957 skb_reset_mac_header(struct sk_buff *skb)
958 {
959 	SKB_TRACE(skb);
960 	skb->mac_header = skb->data - skb->head;
961 }
962 
963 static inline void
964 skb_set_mac_header(struct sk_buff *skb, const size_t len)
965 {
966 	SKB_TRACE(skb);
967 	skb_reset_mac_header(skb);
968 	skb->mac_header += len;
969 }
970 
971 static inline struct skb_shared_hwtstamps *
972 skb_hwtstamps(struct sk_buff *skb)
973 {
974 	SKB_TRACE(skb);
975 	SKB_TODO();
976 	return (NULL);
977 }
978 
979 static inline void
980 skb_orphan(struct sk_buff *skb)
981 {
982 	SKB_TRACE(skb);
983 	SKB_TODO();
984 }
985 
986 static inline __sum16
987 csum_unfold(__sum16 sum)
988 {
989 	SKB_TODO();
990 	return (sum);
991 }
992 
993 static __inline void
994 skb_postpush_rcsum(struct sk_buff *skb, const void *data, size_t len)
995 {
996 	SKB_TODO();
997 }
998 
999 static inline void
1000 skb_reset_tail_pointer(struct sk_buff *skb)
1001 {
1002 
1003 	SKB_TRACE(skb);
1004 #ifdef SKB_DOING_OFFSETS_US_NOT
1005 	skb->tail = (uint8_t *)(uintptr_t)(skb->data - skb->head);
1006 #endif
1007 	skb->tail = skb->data;
1008 	SKB_TRACE(skb);
1009 }
1010 
1011 static inline struct sk_buff *
1012 skb_get(struct sk_buff *skb)
1013 {
1014 
1015 	SKB_TODO();	/* XXX refcnt? as in get/put_device? */
1016 	return (skb);
1017 }
1018 
1019 static inline struct sk_buff *
1020 skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
1021 {
1022 
1023 	SKB_TODO();
1024 	return (NULL);
1025 }
1026 
1027 static inline void
1028 skb_copy_from_linear_data(const struct sk_buff *skb, void *dst, size_t len)
1029 {
1030 
1031 	SKB_TRACE(skb);
1032 	/* Let us just hope the destination has len space ... */
1033 	memcpy(dst, skb->data, len);
1034 }
1035 
1036 static inline int
1037 skb_pad(struct sk_buff *skb, int pad)
1038 {
1039 
1040 	SKB_TRACE(skb);
1041 	SKB_TODO();
1042 	return (-1);
1043 }
1044 
1045 static inline void
1046 skb_list_del_init(struct sk_buff *skb)
1047 {
1048 
1049 	SKB_TRACE(skb);
1050 	SKB_TODO();
1051 }
1052 
1053 static inline void
1054 napi_consume_skb(struct sk_buff *skb, int budget)
1055 {
1056 
1057 	SKB_TRACE(skb);
1058 	SKB_TODO();
1059 }
1060 
1061 static inline struct sk_buff *
1062 napi_build_skb(void *data, size_t len)
1063 {
1064 
1065 	SKB_TODO();
1066 	return (NULL);
1067 }
1068 
1069 static inline uint32_t
1070 skb_get_hash(struct sk_buff *skb)
1071 {
1072 	SKB_TRACE(skb);
1073 	SKB_TODO();
1074 	return (0);
1075 }
1076 
1077 static inline void
1078 skb_mark_for_recycle(struct sk_buff *skb)
1079 {
1080 	SKB_TRACE(skb);
1081 	SKB_TODO();
1082 }
1083 
1084 static inline int
1085 skb_cow_head(struct sk_buff *skb, unsigned int headroom)
1086 {
1087 	SKB_TRACE(skb);
1088 	SKB_TODO();
1089 	return (-1);
1090 }
1091 
1092 #define	SKB_WITH_OVERHEAD(_s)						\
1093 	(_s) - ALIGN(sizeof(struct skb_shared_info), CACHE_LINE_SIZE)
1094 
1095 #endif	/* _LINUXKPI_LINUX_SKBUFF_H */
1096