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