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 *
m_getm2(struct mbuf * m,int len,int how,short type,int flags)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
m_extadd(struct mbuf * mb,caddr_t buf,u_int size,void (* freef)(struct mbuf *,void *,void *),void * arg1,void * arg2,int flags,int type)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
m_freem(struct mbuf * mb)151 m_freem(struct mbuf *mb)
152 {
153 while (mb != NULL)
154 mb = m_free(mb);
155 }
156