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