xref: /freebsd/sys/compat/linuxkpi/common/src/linux_skbuff.c (revision 43a5ec4eb41567cc92586503212743d89686d78f)
1 /*-
2  * Copyright (c) 2020-2021 The FreeBSD Foundation
3  * Copyright (c) 2021 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  * $FreeBSD$
30  */
31 
32 /*
33  * NOTE: this socket buffer compatibility code is highly EXPERIMENTAL.
34  *       Do not rely on the internals of this implementation.  They are highly
35  *       likely to change as we will improve the integration to FreeBSD mbufs.
36  */
37 
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 
46 #include <linux/skbuff.h>
47 #include <linux/slab.h>
48 
49 static MALLOC_DEFINE(M_LKPISKB, "lkpiskb", "Linux KPI skbuff compat");
50 
51 struct sk_buff *
52 linuxkpi_alloc_skb(size_t size, gfp_t gfp)
53 {
54 	struct sk_buff *skb;
55 	size_t len;
56 
57 	len = sizeof(*skb) + size + sizeof(struct skb_shared_info);
58 	/*
59 	 * Using or own type here not backing my kmalloc.
60 	 * We assume no one calls kfree directly on the skb.
61 	 */
62 	skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO);
63 	if (skb == NULL)
64 		return (skb);
65 	skb->_alloc_len = size;
66 	skb->truesize = size;
67 
68 	skb->head = skb->data = skb->tail = (uint8_t *)(skb+1);
69 	skb->end = skb->head + size;
70 
71 	skb->shinfo = (struct skb_shared_info *)(skb->end);
72 
73 	SKB_TRACE_FMT(skb, "data %p size %zu", skb->data, size);
74 	return (skb);
75 }
76 
77 void
78 linuxkpi_kfree_skb(struct sk_buff *skb)
79 {
80 	struct skb_shared_info *shinfo;
81 	uint16_t fragno;
82 
83 	SKB_TRACE(skb);
84 	if (skb == NULL)
85 		return;
86 
87 	/*
88 	 * XXX TODO this will go away once we have skb backed by mbuf.
89 	 * currently we allow the mbuf to stay around and use a private
90 	 * free function to allow secondary resources to be freed along.
91 	 */
92 	if (skb->m != NULL) {
93 		void *m;
94 
95 		m = skb->m;
96 		skb->m = NULL;
97 
98 		KASSERT(skb->m_free_func != NULL, ("%s: skb %p has m %p but no "
99 		    "m_free_func %p\n", __func__, skb, m, skb->m_free_func));
100 		skb->m_free_func(m);
101 	}
102 	KASSERT(skb->m == NULL,
103 	    ("%s: skb %p m %p != NULL\n", __func__, skb, skb->m));
104 
105 	shinfo = skb->shinfo;
106 	for (fragno = 0; fragno < nitems(shinfo->frags); fragno++) {
107 
108 		if (shinfo->frags[fragno].page != NULL)
109 			__free_page(shinfo->frags[fragno].page);
110 	}
111 
112 	free(skb, M_LKPISKB);
113 }
114