1 /*! NOTE: Most kern_mbuf functions are implemented by our mbuf.c; however, 2 * a certain few non-allocation-related ones which we can copy wholesale 3 * from FreeBSD live here. */ 4 /*- 5 * Copyright (c) 2004, 2005, 6 * Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved. 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 unmodified, this list of conditions and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #include <sys/mbuf.h> 33 34 /* 35 * Allocate a given length worth of mbufs and/or clusters (whatever fits 36 * best) and return a pointer to the top of the allocated chain. If an 37 * existing mbuf chain is provided, then we will append the new chain 38 * to the existing one but still return the top of the newly allocated 39 * chain. 40 */ 41 struct mbuf * 42 m_getm2(struct mbuf *m, int len, int how, short type, int flags) 43 { 44 struct mbuf *mb, *nm = NULL, *mtail = NULL; 45 46 KASSERT(len >= 0, ("%s: len is < 0", __func__)); 47 48 /* Validate flags. */ 49 flags &= (M_PKTHDR | M_EOR); 50 51 /* Packet header mbuf must be first in chain. */ 52 if ((flags & M_PKTHDR) && m != NULL) 53 flags &= ~M_PKTHDR; 54 55 /* Loop and append maximum sized mbufs to the chain tail. */ 56 while (len > 0) { 57 if (len > MCLBYTES) 58 mb = m_getjcl(how, type, (flags & M_PKTHDR), 59 MJUMPAGESIZE); 60 else if (len >= MINCLSIZE) 61 mb = m_getcl(how, type, (flags & M_PKTHDR)); 62 else if (flags & M_PKTHDR) 63 mb = m_gethdr(how, type); 64 else 65 mb = m_get(how, type); 66 67 /* Fail the whole operation if one mbuf can't be allocated. */ 68 if (mb == NULL) { 69 if (nm != NULL) 70 m_freem(nm); 71 return (NULL); 72 } 73 74 /* Book keeping. */ 75 len -= M_SIZE(mb); 76 if (mtail != NULL) 77 mtail->m_next = mb; 78 else 79 nm = mb; 80 mtail = mb; 81 flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */ 82 } 83 if (flags & M_EOR) 84 mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */ 85 86 /* If mbuf was supplied, append new chain to the end of it. */ 87 if (m != NULL) { 88 for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next) 89 ; 90 mtail->m_next = nm; 91 mtail->m_flags &= ~M_EOR; 92 } else 93 m = nm; 94 95 return (m); 96 } 97 98 /*- 99 * Configure a provided mbuf to refer to the provided external storage 100 * buffer and setup a reference count for said buffer. 101 * 102 * Arguments: 103 * mb The existing mbuf to which to attach the provided buffer. 104 * buf The address of the provided external storage buffer. 105 * size The size of the provided buffer. 106 * freef A pointer to a routine that is responsible for freeing the 107 * provided external storage buffer. 108 * args A pointer to an argument structure (of any type) to be passed 109 * to the provided freef routine (may be NULL). 110 * flags Any other flags to be passed to the provided mbuf. 111 * type The type that the external storage buffer should be 112 * labeled with. 113 * 114 * Returns: 115 * Nothing. 116 */ 117 void 118 m_extadd(struct mbuf *mb, caddr_t buf, u_int size, 119 void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2, 120 int flags, int type) 121 { 122 123 KASSERT(type != EXT_CLUSTER, ("%s: EXT_CLUSTER not allowed", __func__)); 124 125 mb->m_flags |= (M_EXT | flags); 126 mb->m_ext.ext_buf = buf; 127 mb->m_data = mb->m_ext.ext_buf; 128 mb->m_ext.ext_size = size; 129 #ifndef __HAIKU__ 130 mb->m_ext.ext_free = freef; 131 mb->m_ext.ext_arg1 = arg1; 132 mb->m_ext.ext_arg2 = arg2; 133 #else 134 if (freef != NULL) 135 panic("m_ext.ext_free not yet implemented"); 136 #endif 137 mb->m_ext.ext_type = type; 138 139 if (type != EXT_EXTREF) { 140 mb->m_ext.ext_count = 1; 141 mb->m_ext.ext_flags = EXT_FLAG_EMBREF; 142 } else 143 mb->m_ext.ext_flags = 0; 144 } 145 146 /* 147 * Free an entire chain of mbufs and associated external buffers, if 148 * applicable. 149 */ 150 void 151 m_freem(struct mbuf *mb) 152 { 153 while (mb != NULL) 154 mb = m_free(mb); 155 } 156