xref: /freebsd/sys/compat/linuxkpi/common/src/linux_skbuff.c (revision 49ed6e979c3b327ae466a559884802d901aa5792)
1*49ed6e97SBjoern A. Zeeb /*-
2*49ed6e97SBjoern A. Zeeb  * Copyright (c) 2020-2021 The FreeBSD Foundation
3*49ed6e97SBjoern A. Zeeb  * Copyright (c) 2021 Bjoern A. Zeeb
4*49ed6e97SBjoern A. Zeeb  *
5*49ed6e97SBjoern A. Zeeb  * This software was developed by Björn Zeeb under sponsorship from
6*49ed6e97SBjoern A. Zeeb  * the FreeBSD Foundation.
7*49ed6e97SBjoern A. Zeeb  *
8*49ed6e97SBjoern A. Zeeb  * Redistribution and use in source and binary forms, with or without
9*49ed6e97SBjoern A. Zeeb  * modification, are permitted provided that the following conditions
10*49ed6e97SBjoern A. Zeeb  * are met:
11*49ed6e97SBjoern A. Zeeb  * 1. Redistributions of source code must retain the above copyright
12*49ed6e97SBjoern A. Zeeb  *    notice, this list of conditions and the following disclaimer.
13*49ed6e97SBjoern A. Zeeb  * 2. Redistributions in binary form must reproduce the above copyright
14*49ed6e97SBjoern A. Zeeb  *    notice, this list of conditions and the following disclaimer in the
15*49ed6e97SBjoern A. Zeeb  *    documentation and/or other materials provided with the distribution.
16*49ed6e97SBjoern A. Zeeb  *
17*49ed6e97SBjoern A. Zeeb  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*49ed6e97SBjoern A. Zeeb  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*49ed6e97SBjoern A. Zeeb  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*49ed6e97SBjoern A. Zeeb  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*49ed6e97SBjoern A. Zeeb  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*49ed6e97SBjoern A. Zeeb  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*49ed6e97SBjoern A. Zeeb  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*49ed6e97SBjoern A. Zeeb  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*49ed6e97SBjoern A. Zeeb  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*49ed6e97SBjoern A. Zeeb  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*49ed6e97SBjoern A. Zeeb  * SUCH DAMAGE.
28*49ed6e97SBjoern A. Zeeb  *
29*49ed6e97SBjoern A. Zeeb  * $FreeBSD$
30*49ed6e97SBjoern A. Zeeb  */
31*49ed6e97SBjoern A. Zeeb 
32*49ed6e97SBjoern A. Zeeb /*
33*49ed6e97SBjoern A. Zeeb  * NOTE: this socket buffer compatibility code is highly EXPERIMENTAL.
34*49ed6e97SBjoern A. Zeeb  *       Do not rely on the internals of this implementation.  They are highly
35*49ed6e97SBjoern A. Zeeb  *       likely to change as we will improve the integration to FreeBSD mbufs.
36*49ed6e97SBjoern A. Zeeb  */
37*49ed6e97SBjoern A. Zeeb 
38*49ed6e97SBjoern A. Zeeb #include <sys/cdefs.h>
39*49ed6e97SBjoern A. Zeeb __FBSDID("$FreeBSD$");
40*49ed6e97SBjoern A. Zeeb 
41*49ed6e97SBjoern A. Zeeb #include <sys/param.h>
42*49ed6e97SBjoern A. Zeeb #include <sys/types.h>
43*49ed6e97SBjoern A. Zeeb #include <sys/kernel.h>
44*49ed6e97SBjoern A. Zeeb #include <sys/malloc.h>
45*49ed6e97SBjoern A. Zeeb 
46*49ed6e97SBjoern A. Zeeb #include <linux/skbuff.h>
47*49ed6e97SBjoern A. Zeeb #include <linux/slab.h>
48*49ed6e97SBjoern A. Zeeb 
49*49ed6e97SBjoern A. Zeeb static MALLOC_DEFINE(M_LKPISKB, "lkpiskb", "Linux KPI skbuff compat");
50*49ed6e97SBjoern A. Zeeb 
51*49ed6e97SBjoern A. Zeeb struct sk_buff *
52*49ed6e97SBjoern A. Zeeb linuxkpi_alloc_skb(size_t size, gfp_t gfp)
53*49ed6e97SBjoern A. Zeeb {
54*49ed6e97SBjoern A. Zeeb 	struct sk_buff *skb;
55*49ed6e97SBjoern A. Zeeb 	size_t len;
56*49ed6e97SBjoern A. Zeeb 
57*49ed6e97SBjoern A. Zeeb 	len = sizeof(*skb) + size + sizeof(struct skb_shared_info);
58*49ed6e97SBjoern A. Zeeb 	/*
59*49ed6e97SBjoern A. Zeeb 	 * Using or own type here not backing my kmalloc.
60*49ed6e97SBjoern A. Zeeb 	 * We assume no one calls kfree directly on the skb.
61*49ed6e97SBjoern A. Zeeb 	 */
62*49ed6e97SBjoern A. Zeeb 	skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO);
63*49ed6e97SBjoern A. Zeeb 	if (skb == NULL)
64*49ed6e97SBjoern A. Zeeb 		return (skb);
65*49ed6e97SBjoern A. Zeeb 	skb->_alloc_len = size;
66*49ed6e97SBjoern A. Zeeb 	skb->truesize = size;
67*49ed6e97SBjoern A. Zeeb 
68*49ed6e97SBjoern A. Zeeb 	skb->head = skb->data = skb->tail = (uint8_t *)(skb+1);
69*49ed6e97SBjoern A. Zeeb 	skb->end = skb->head + size;
70*49ed6e97SBjoern A. Zeeb 
71*49ed6e97SBjoern A. Zeeb 	skb->shinfo = (struct skb_shared_info *)(skb->end);
72*49ed6e97SBjoern A. Zeeb 
73*49ed6e97SBjoern A. Zeeb 	SKB_TRACE_FMT(skb, "data %p size %zu", skb->data, size);
74*49ed6e97SBjoern A. Zeeb 	return (skb);
75*49ed6e97SBjoern A. Zeeb }
76*49ed6e97SBjoern A. Zeeb 
77*49ed6e97SBjoern A. Zeeb void
78*49ed6e97SBjoern A. Zeeb linuxkpi_kfree_skb(struct sk_buff *skb)
79*49ed6e97SBjoern A. Zeeb {
80*49ed6e97SBjoern A. Zeeb 	struct skb_shared_info *shinfo;
81*49ed6e97SBjoern A. Zeeb 	uint16_t fragno;
82*49ed6e97SBjoern A. Zeeb 
83*49ed6e97SBjoern A. Zeeb 	SKB_TRACE(skb);
84*49ed6e97SBjoern A. Zeeb 	if (skb == NULL)
85*49ed6e97SBjoern A. Zeeb 		return;
86*49ed6e97SBjoern A. Zeeb 
87*49ed6e97SBjoern A. Zeeb 	/*
88*49ed6e97SBjoern A. Zeeb 	 * XXX TODO this will go away once we have skb backed by mbuf.
89*49ed6e97SBjoern A. Zeeb 	 * currently we allow the mbuf to stay around and use a private
90*49ed6e97SBjoern A. Zeeb 	 * free function to allow secondary resources to be freed along.
91*49ed6e97SBjoern A. Zeeb 	 */
92*49ed6e97SBjoern A. Zeeb 	if (skb->m != NULL) {
93*49ed6e97SBjoern A. Zeeb 		void *m;
94*49ed6e97SBjoern A. Zeeb 
95*49ed6e97SBjoern A. Zeeb 		m = skb->m;
96*49ed6e97SBjoern A. Zeeb 		skb->m = NULL;
97*49ed6e97SBjoern A. Zeeb 
98*49ed6e97SBjoern A. Zeeb 		KASSERT(skb->m_free_func != NULL, ("%s: skb %p has m %p but no "
99*49ed6e97SBjoern A. Zeeb 		    "m_free_func %p\n", __func__, skb, m, skb->m_free_func));
100*49ed6e97SBjoern A. Zeeb 		skb->m_free_func(m);
101*49ed6e97SBjoern A. Zeeb 	}
102*49ed6e97SBjoern A. Zeeb 	KASSERT(skb->m == NULL,
103*49ed6e97SBjoern A. Zeeb 	    ("%s: skb %p m %p != NULL\n", __func__, skb, skb->m));
104*49ed6e97SBjoern A. Zeeb 
105*49ed6e97SBjoern A. Zeeb 	shinfo = skb->shinfo;
106*49ed6e97SBjoern A. Zeeb 	for (fragno = 0; fragno < nitems(shinfo->frags); fragno++) {
107*49ed6e97SBjoern A. Zeeb 
108*49ed6e97SBjoern A. Zeeb 		if (shinfo->frags[fragno].page != NULL)
109*49ed6e97SBjoern A. Zeeb 			__free_page(shinfo->frags[fragno].page);
110*49ed6e97SBjoern A. Zeeb 	}
111*49ed6e97SBjoern A. Zeeb 
112*49ed6e97SBjoern A. Zeeb 	free(skb, M_LKPISKB);
113*49ed6e97SBjoern A. Zeeb }
114