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