uipc_mbuf.c revision 1.100.2.17 1 /* $NetBSD: uipc_mbuf.c,v 1.100.2.17 2007/11/15 13:59:39 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1982, 1986, 1988, 1991, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 *
68 * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95
69 */
70
71 #include <sys/cdefs.h>
72 __KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.100.2.17 2007/11/15 13:59:39 yamt Exp $");
73
74 #include "opt_mbuftrace.h"
75 #include "opt_ddb.h"
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/proc.h>
80 #include <sys/malloc.h>
81 #define MBTYPES
82 #include <sys/mbuf.h>
83 #include <sys/kernel.h>
84 #include <sys/syslog.h>
85 #include <sys/domain.h>
86 #include <sys/protosw.h>
87 #include <sys/pool.h>
88 #include <sys/socket.h>
89 #include <sys/sysctl.h>
90
91 #include <net/if.h>
92
93 #include <uvm/uvm.h>
94
95 pool_cache_t mb_cache; /* mbuf cache */
96 pool_cache_t mcl_cache; /* mbuf cluster cache */
97
98 struct mbstat mbstat;
99 int max_linkhdr;
100 int max_protohdr;
101 int max_hdr;
102 int max_datalen;
103
104 static int mb_ctor(void *, void *, int);
105
106 static void *mclpool_alloc(struct pool *, int);
107 static void mclpool_release(struct pool *, void *);
108
109 static struct pool_allocator mclpool_allocator = {
110 .pa_alloc = mclpool_alloc,
111 .pa_free = mclpool_release,
112 };
113
114 static struct mbuf *m_copym0(struct mbuf *, int, int, int, int);
115 static struct mbuf *m_split0(struct mbuf *, int, int, int);
116 static int m_copyback0(struct mbuf **, int, int, const void *, int, int);
117
118 /* flags for m_copyback0 */
119 #define M_COPYBACK0_COPYBACK 0x0001 /* copyback from cp */
120 #define M_COPYBACK0_PRESERVE 0x0002 /* preserve original data */
121 #define M_COPYBACK0_COW 0x0004 /* do copy-on-write */
122 #define M_COPYBACK0_EXTEND 0x0008 /* extend chain */
123
124 static const char mclpool_warnmsg[] =
125 "WARNING: mclpool limit reached; increase NMBCLUSTERS";
126
127 MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
128
129 #ifdef MBUFTRACE
130 struct mownerhead mowners = LIST_HEAD_INITIALIZER(mowners);
131 struct mowner unknown_mowners[] = {
132 MOWNER_INIT("unknown", "free"),
133 MOWNER_INIT("unknown", "data"),
134 MOWNER_INIT("unknown", "header"),
135 MOWNER_INIT("unknown", "soname"),
136 MOWNER_INIT("unknown", "soopts"),
137 MOWNER_INIT("unknown", "ftable"),
138 MOWNER_INIT("unknown", "control"),
139 MOWNER_INIT("unknown", "oobdata"),
140 };
141 struct mowner revoked_mowner = MOWNER_INIT("revoked", "");
142 #endif
143
144 #define MEXT_LOCK(m) mutex_enter(&(m)->m_ext.ext_lock)
145 #define MEXT_UNLOCK(m) mutex_exit(&(m)->m_ext.ext_lock)
146 #define MEXT_ISEMBEDDED(m) ((m)->m_ext_ref == (m))
147
148 static inline void
149 mcl_inc_reference(struct mbuf *m)
150 {
151
152 MEXT_LOCK(m);
153 m->m_ext.ext_refcnt++;
154 MEXT_UNLOCK(m);
155 }
156
157 static inline bool
158 mcl_dec_and_test_reference(struct mbuf *m)
159 {
160 bool gotzero;
161
162 MEXT_LOCK(m);
163 KASSERT(m->m_ext.ext_refcnt > 0);
164 m->m_ext.ext_refcnt--;
165 gotzero = (m->m_ext.ext_refcnt == 0);
166 MEXT_UNLOCK(m);
167
168 return gotzero;
169 }
170
171 #define MCLADDREFERENCE(o, n) \
172 do { \
173 KASSERT(((o)->m_flags & M_EXT) != 0); \
174 KASSERT(((n)->m_flags & M_EXT) == 0); \
175 KASSERT((o)->m_ext.ext_refcnt >= 1); \
176 (n)->m_flags |= ((o)->m_flags & M_EXTCOPYFLAGS); \
177 mcl_inc_reference((o)); \
178 (n)->m_ext_ref = (o)->m_ext_ref; \
179 _MOWNERREF((n), (n)->m_flags); \
180 MCLREFDEBUGN((n), __FILE__, __LINE__); \
181 } while (/* CONSTCOND */ 0)
182
183 /*
184 * Initialize the mbuf allocator.
185 */
186 void
187 mbinit(void)
188 {
189
190 KASSERT(sizeof(struct _m_ext) <= MHLEN);
191 KASSERT(sizeof(struct mbuf) == MSIZE);
192
193 mclpool_allocator.pa_backingmap = mb_map;
194
195 mb_cache = pool_cache_init(msize, 0, 0, 0, "mbpl",
196 NULL, IPL_VM, mb_ctor, NULL, NULL);
197 KASSERT(mb_cache != NULL);
198
199 mcl_cache = pool_cache_init(mclbytes, 0, 0, 0, "mclpl",
200 &mclpool_allocator, IPL_VM, NULL, NULL, NULL);
201 KASSERT(mcl_cache != NULL);
202
203 pool_cache_set_drain_hook(mb_cache, m_reclaim, NULL);
204 pool_cache_set_drain_hook(mcl_cache, m_reclaim, NULL);
205
206 /*
207 * Set the hard limit on the mclpool to the number of
208 * mbuf clusters the kernel is to support. Log the limit
209 * reached message max once a minute.
210 */
211 pool_cache_sethardlimit(mcl_cache, nmbclusters, mclpool_warnmsg, 60);
212
213 /*
214 * Set a low water mark for both mbufs and clusters. This should
215 * help ensure that they can be allocated in a memory starvation
216 * situation. This is important for e.g. diskless systems which
217 * must allocate mbufs in order for the pagedaemon to clean pages.
218 */
219 pool_cache_setlowat(mb_cache, mblowat);
220 pool_cache_setlowat(mcl_cache, mcllowat);
221
222 #ifdef MBUFTRACE
223 {
224 /*
225 * Attach the unknown mowners.
226 */
227 int i;
228 MOWNER_ATTACH(&revoked_mowner);
229 for (i = sizeof(unknown_mowners)/sizeof(unknown_mowners[0]);
230 i-- > 0; )
231 MOWNER_ATTACH(&unknown_mowners[i]);
232 }
233 #endif
234 }
235
236 /*
237 * sysctl helper routine for the kern.mbuf subtree. nmbclusters may
238 * or may not be writable, and mblowat and mcllowat need range
239 * checking and pool tweaking after being reset.
240 */
241 static int
242 sysctl_kern_mbuf(SYSCTLFN_ARGS)
243 {
244 int error, newval;
245 struct sysctlnode node;
246
247 node = *rnode;
248 node.sysctl_data = &newval;
249 switch (rnode->sysctl_num) {
250 case MBUF_NMBCLUSTERS:
251 if (mb_map != NULL) {
252 node.sysctl_flags &= ~CTLFLAG_READWRITE;
253 node.sysctl_flags |= CTLFLAG_READONLY;
254 }
255 /* FALLTHROUGH */
256 case MBUF_MBLOWAT:
257 case MBUF_MCLLOWAT:
258 newval = *(int*)rnode->sysctl_data;
259 break;
260 default:
261 return (EOPNOTSUPP);
262 }
263
264 error = sysctl_lookup(SYSCTLFN_CALL(&node));
265 if (error || newp == NULL)
266 return (error);
267 if (newval < 0)
268 return (EINVAL);
269
270 switch (node.sysctl_num) {
271 case MBUF_NMBCLUSTERS:
272 if (newval < nmbclusters)
273 return (EINVAL);
274 nmbclusters = newval;
275 pool_cache_sethardlimit(mcl_cache, nmbclusters,
276 mclpool_warnmsg, 60);
277 break;
278 case MBUF_MBLOWAT:
279 mblowat = newval;
280 pool_cache_setlowat(mb_cache, mblowat);
281 break;
282 case MBUF_MCLLOWAT:
283 mcllowat = newval;
284 pool_cache_setlowat(mcl_cache, mcllowat);
285 break;
286 }
287
288 return (0);
289 }
290
291 #ifdef MBUFTRACE
292 static int
293 sysctl_kern_mbuf_mowners(SYSCTLFN_ARGS)
294 {
295 struct mowner *mo;
296 size_t len = 0;
297 int error = 0;
298
299 if (namelen != 0)
300 return (EINVAL);
301 if (newp != NULL)
302 return (EPERM);
303
304 LIST_FOREACH(mo, &mowners, mo_link) {
305 if (oldp != NULL) {
306 if (*oldlenp - len < sizeof(*mo)) {
307 error = ENOMEM;
308 break;
309 }
310 error = copyout(mo, (char *)oldp + len, sizeof(*mo));
311 if (error)
312 break;
313 }
314 len += sizeof(*mo);
315 }
316
317 if (error == 0)
318 *oldlenp = len;
319
320 return (error);
321 }
322 #endif /* MBUFTRACE */
323
324 SYSCTL_SETUP(sysctl_kern_mbuf_setup, "sysctl kern.mbuf subtree setup")
325 {
326
327 sysctl_createv(clog, 0, NULL, NULL,
328 CTLFLAG_PERMANENT,
329 CTLTYPE_NODE, "kern", NULL,
330 NULL, 0, NULL, 0,
331 CTL_KERN, CTL_EOL);
332 sysctl_createv(clog, 0, NULL, NULL,
333 CTLFLAG_PERMANENT,
334 CTLTYPE_NODE, "mbuf",
335 SYSCTL_DESCR("mbuf control variables"),
336 NULL, 0, NULL, 0,
337 CTL_KERN, KERN_MBUF, CTL_EOL);
338
339 sysctl_createv(clog, 0, NULL, NULL,
340 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
341 CTLTYPE_INT, "msize",
342 SYSCTL_DESCR("mbuf base size"),
343 NULL, msize, NULL, 0,
344 CTL_KERN, KERN_MBUF, MBUF_MSIZE, CTL_EOL);
345 sysctl_createv(clog, 0, NULL, NULL,
346 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
347 CTLTYPE_INT, "mclbytes",
348 SYSCTL_DESCR("mbuf cluster size"),
349 NULL, mclbytes, NULL, 0,
350 CTL_KERN, KERN_MBUF, MBUF_MCLBYTES, CTL_EOL);
351 sysctl_createv(clog, 0, NULL, NULL,
352 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
353 CTLTYPE_INT, "nmbclusters",
354 SYSCTL_DESCR("Limit on the number of mbuf clusters"),
355 sysctl_kern_mbuf, 0, &nmbclusters, 0,
356 CTL_KERN, KERN_MBUF, MBUF_NMBCLUSTERS, CTL_EOL);
357 sysctl_createv(clog, 0, NULL, NULL,
358 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
359 CTLTYPE_INT, "mblowat",
360 SYSCTL_DESCR("mbuf low water mark"),
361 sysctl_kern_mbuf, 0, &mblowat, 0,
362 CTL_KERN, KERN_MBUF, MBUF_MBLOWAT, CTL_EOL);
363 sysctl_createv(clog, 0, NULL, NULL,
364 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
365 CTLTYPE_INT, "mcllowat",
366 SYSCTL_DESCR("mbuf cluster low water mark"),
367 sysctl_kern_mbuf, 0, &mcllowat, 0,
368 CTL_KERN, KERN_MBUF, MBUF_MCLLOWAT, CTL_EOL);
369 sysctl_createv(clog, 0, NULL, NULL,
370 CTLFLAG_PERMANENT,
371 CTLTYPE_STRUCT, "stats",
372 SYSCTL_DESCR("mbuf allocation statistics"),
373 NULL, 0, &mbstat, sizeof(mbstat),
374 CTL_KERN, KERN_MBUF, MBUF_STATS, CTL_EOL);
375 #ifdef MBUFTRACE
376 sysctl_createv(clog, 0, NULL, NULL,
377 CTLFLAG_PERMANENT,
378 CTLTYPE_STRUCT, "mowners",
379 SYSCTL_DESCR("Information about mbuf owners"),
380 sysctl_kern_mbuf_mowners, 0, NULL, 0,
381 CTL_KERN, KERN_MBUF, MBUF_MOWNERS, CTL_EOL);
382 #endif /* MBUFTRACE */
383 }
384
385 static void *
386 mclpool_alloc(struct pool *pp, int flags)
387 {
388 bool waitok = (flags & PR_WAITOK) ? true : false;
389
390 return ((void *)uvm_km_alloc_poolpage(mb_map, waitok));
391 }
392
393 static void
394 mclpool_release(struct pool *pp, void *v)
395 {
396
397 uvm_km_free_poolpage(mb_map, (vaddr_t)v);
398 }
399
400 /*ARGSUSED*/
401 static int
402 mb_ctor(void *arg, void *object, int flags)
403 {
404 struct mbuf *m = object;
405
406 #ifdef POOL_VTOPHYS
407 m->m_paddr = POOL_VTOPHYS(m);
408 #else
409 m->m_paddr = M_PADDR_INVALID;
410 #endif
411 return (0);
412 }
413
414 void
415 m_reclaim(void *arg, int flags)
416 {
417 struct domain *dp;
418 const struct protosw *pr;
419 struct ifnet *ifp;
420 int s;
421
422 KERNEL_LOCK(1, NULL);
423 s = splvm();
424 DOMAIN_FOREACH(dp) {
425 for (pr = dp->dom_protosw;
426 pr < dp->dom_protoswNPROTOSW; pr++)
427 if (pr->pr_drain)
428 (*pr->pr_drain)();
429 }
430 IFNET_FOREACH(ifp) {
431 if (ifp->if_drain)
432 (*ifp->if_drain)(ifp);
433 }
434 splx(s);
435 mbstat.m_drain++;
436 KERNEL_UNLOCK_ONE(NULL);
437 }
438
439 /*
440 * Space allocation routines.
441 * These are also available as macros
442 * for critical paths.
443 */
444 struct mbuf *
445 m_get(int nowait, int type)
446 {
447 struct mbuf *m;
448
449 MGET(m, nowait, type);
450 return (m);
451 }
452
453 struct mbuf *
454 m_gethdr(int nowait, int type)
455 {
456 struct mbuf *m;
457
458 MGETHDR(m, nowait, type);
459 return (m);
460 }
461
462 struct mbuf *
463 m_getclr(int nowait, int type)
464 {
465 struct mbuf *m;
466
467 MGET(m, nowait, type);
468 if (m == 0)
469 return (NULL);
470 memset(mtod(m, void *), 0, MLEN);
471 return (m);
472 }
473
474 void
475 m_clget(struct mbuf *m, int nowait)
476 {
477
478 MCLGET(m, nowait);
479 }
480
481 struct mbuf *
482 m_free(struct mbuf *m)
483 {
484 struct mbuf *n;
485
486 MFREE(m, n);
487 return (n);
488 }
489
490 void
491 m_freem(struct mbuf *m)
492 {
493 struct mbuf *n;
494
495 if (m == NULL)
496 return;
497 do {
498 MFREE(m, n);
499 m = n;
500 } while (m);
501 }
502
503 #ifdef MBUFTRACE
504 /*
505 * Walk a chain of mbufs, claiming ownership of each mbuf in the chain.
506 */
507 void
508 m_claimm(struct mbuf *m, struct mowner *mo)
509 {
510
511 for (; m != NULL; m = m->m_next)
512 MCLAIM(m, mo);
513 }
514 #endif
515
516 /*
517 * Mbuffer utility routines.
518 */
519
520 /*
521 * Lesser-used path for M_PREPEND:
522 * allocate new mbuf to prepend to chain,
523 * copy junk along.
524 */
525 struct mbuf *
526 m_prepend(struct mbuf *m, int len, int how)
527 {
528 struct mbuf *mn;
529
530 MGET(mn, how, m->m_type);
531 if (mn == (struct mbuf *)NULL) {
532 m_freem(m);
533 return ((struct mbuf *)NULL);
534 }
535 if (m->m_flags & M_PKTHDR) {
536 M_MOVE_PKTHDR(mn, m);
537 } else {
538 MCLAIM(mn, m->m_owner);
539 }
540 mn->m_next = m;
541 m = mn;
542 if (len < MHLEN)
543 MH_ALIGN(m, len);
544 m->m_len = len;
545 return (m);
546 }
547
548 /*
549 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
550 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
551 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
552 */
553 int MCFail;
554
555 struct mbuf *
556 m_copym(struct mbuf *m, int off0, int len, int wait)
557 {
558
559 return m_copym0(m, off0, len, wait, 0); /* shallow copy on M_EXT */
560 }
561
562 struct mbuf *
563 m_dup(struct mbuf *m, int off0, int len, int wait)
564 {
565
566 return m_copym0(m, off0, len, wait, 1); /* deep copy */
567 }
568
569 static struct mbuf *
570 m_copym0(struct mbuf *m, int off0, int len, int wait, int deep)
571 {
572 struct mbuf *n, **np;
573 int off = off0;
574 struct mbuf *top;
575 int copyhdr = 0;
576
577 if (off < 0 || len < 0)
578 panic("m_copym: off %d, len %d", off, len);
579 if (off == 0 && m->m_flags & M_PKTHDR)
580 copyhdr = 1;
581 while (off > 0) {
582 if (m == 0)
583 panic("m_copym: m == 0, off %d", off);
584 if (off < m->m_len)
585 break;
586 off -= m->m_len;
587 m = m->m_next;
588 }
589 np = ⊤
590 top = 0;
591 while (len > 0) {
592 if (m == 0) {
593 if (len != M_COPYALL)
594 panic("m_copym: m == 0, len %d [!COPYALL]",
595 len);
596 break;
597 }
598 MGET(n, wait, m->m_type);
599 *np = n;
600 if (n == 0)
601 goto nospace;
602 MCLAIM(n, m->m_owner);
603 if (copyhdr) {
604 M_COPY_PKTHDR(n, m);
605 if (len == M_COPYALL)
606 n->m_pkthdr.len -= off0;
607 else
608 n->m_pkthdr.len = len;
609 copyhdr = 0;
610 }
611 n->m_len = min(len, m->m_len - off);
612 if (m->m_flags & M_EXT) {
613 if (!deep) {
614 n->m_data = m->m_data + off;
615 MCLADDREFERENCE(m, n);
616 } else {
617 /*
618 * we are unsure about the way m was allocated.
619 * copy into multiple MCLBYTES cluster mbufs.
620 */
621 MCLGET(n, wait);
622 n->m_len = 0;
623 n->m_len = M_TRAILINGSPACE(n);
624 n->m_len = min(n->m_len, len);
625 n->m_len = min(n->m_len, m->m_len - off);
626 memcpy(mtod(n, void *), mtod(m, char *) + off,
627 (unsigned)n->m_len);
628 }
629 } else
630 memcpy(mtod(n, void *), mtod(m, char *) + off,
631 (unsigned)n->m_len);
632 if (len != M_COPYALL)
633 len -= n->m_len;
634 off += n->m_len;
635 #ifdef DIAGNOSTIC
636 if (off > m->m_len)
637 panic("m_copym0 overrun");
638 #endif
639 if (off == m->m_len) {
640 m = m->m_next;
641 off = 0;
642 }
643 np = &n->m_next;
644 }
645 if (top == 0)
646 MCFail++;
647 return (top);
648 nospace:
649 m_freem(top);
650 MCFail++;
651 return (NULL);
652 }
653
654 /*
655 * Copy an entire packet, including header (which must be present).
656 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
657 */
658 struct mbuf *
659 m_copypacket(struct mbuf *m, int how)
660 {
661 struct mbuf *top, *n, *o;
662
663 MGET(n, how, m->m_type);
664 top = n;
665 if (!n)
666 goto nospace;
667
668 MCLAIM(n, m->m_owner);
669 M_COPY_PKTHDR(n, m);
670 n->m_len = m->m_len;
671 if (m->m_flags & M_EXT) {
672 n->m_data = m->m_data;
673 MCLADDREFERENCE(m, n);
674 } else {
675 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
676 }
677
678 m = m->m_next;
679 while (m) {
680 MGET(o, how, m->m_type);
681 if (!o)
682 goto nospace;
683
684 MCLAIM(o, m->m_owner);
685 n->m_next = o;
686 n = n->m_next;
687
688 n->m_len = m->m_len;
689 if (m->m_flags & M_EXT) {
690 n->m_data = m->m_data;
691 MCLADDREFERENCE(m, n);
692 } else {
693 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
694 }
695
696 m = m->m_next;
697 }
698 return top;
699 nospace:
700 m_freem(top);
701 MCFail++;
702 return NULL;
703 }
704
705 /*
706 * Copy data from an mbuf chain starting "off" bytes from the beginning,
707 * continuing for "len" bytes, into the indicated buffer.
708 */
709 void
710 m_copydata(struct mbuf *m, int off, int len, void *vp)
711 {
712 unsigned count;
713 void * cp = vp;
714
715 if (off < 0 || len < 0)
716 panic("m_copydata: off %d, len %d", off, len);
717 while (off > 0) {
718 if (m == NULL)
719 panic("m_copydata: m == NULL, off %d", off);
720 if (off < m->m_len)
721 break;
722 off -= m->m_len;
723 m = m->m_next;
724 }
725 while (len > 0) {
726 if (m == NULL)
727 panic("m_copydata: m == NULL, len %d", len);
728 count = min(m->m_len - off, len);
729 memcpy(cp, mtod(m, char *) + off, count);
730 len -= count;
731 cp = (char *)cp + count;
732 off = 0;
733 m = m->m_next;
734 }
735 }
736
737 /*
738 * Concatenate mbuf chain n to m.
739 * n might be copied into m (when n->m_len is small), therefore data portion of
740 * n could be copied into an mbuf of different mbuf type.
741 * Any m_pkthdr is not updated.
742 */
743 void
744 m_cat(struct mbuf *m, struct mbuf *n)
745 {
746
747 while (m->m_next)
748 m = m->m_next;
749 while (n) {
750 if (M_READONLY(m) || n->m_len > M_TRAILINGSPACE(m)) {
751 /* just join the two chains */
752 m->m_next = n;
753 return;
754 }
755 /* splat the data from one into the other */
756 memcpy(mtod(m, char *) + m->m_len, mtod(n, void *),
757 (u_int)n->m_len);
758 m->m_len += n->m_len;
759 n = m_free(n);
760 }
761 }
762
763 void
764 m_adj(struct mbuf *mp, int req_len)
765 {
766 int len = req_len;
767 struct mbuf *m;
768 int count;
769
770 if ((m = mp) == NULL)
771 return;
772 if (len >= 0) {
773 /*
774 * Trim from head.
775 */
776 while (m != NULL && len > 0) {
777 if (m->m_len <= len) {
778 len -= m->m_len;
779 m->m_len = 0;
780 m = m->m_next;
781 } else {
782 m->m_len -= len;
783 m->m_data += len;
784 len = 0;
785 }
786 }
787 m = mp;
788 if (mp->m_flags & M_PKTHDR)
789 m->m_pkthdr.len -= (req_len - len);
790 } else {
791 /*
792 * Trim from tail. Scan the mbuf chain,
793 * calculating its length and finding the last mbuf.
794 * If the adjustment only affects this mbuf, then just
795 * adjust and return. Otherwise, rescan and truncate
796 * after the remaining size.
797 */
798 len = -len;
799 count = 0;
800 for (;;) {
801 count += m->m_len;
802 if (m->m_next == (struct mbuf *)0)
803 break;
804 m = m->m_next;
805 }
806 if (m->m_len >= len) {
807 m->m_len -= len;
808 if (mp->m_flags & M_PKTHDR)
809 mp->m_pkthdr.len -= len;
810 return;
811 }
812 count -= len;
813 if (count < 0)
814 count = 0;
815 /*
816 * Correct length for chain is "count".
817 * Find the mbuf with last data, adjust its length,
818 * and toss data from remaining mbufs on chain.
819 */
820 m = mp;
821 if (m->m_flags & M_PKTHDR)
822 m->m_pkthdr.len = count;
823 for (; m; m = m->m_next) {
824 if (m->m_len >= count) {
825 m->m_len = count;
826 break;
827 }
828 count -= m->m_len;
829 }
830 if (m)
831 while (m->m_next)
832 (m = m->m_next)->m_len = 0;
833 }
834 }
835
836 /*
837 * Rearrange an mbuf chain so that len bytes are contiguous
838 * and in the data area of an mbuf (so that mtod and dtom
839 * will work for a structure of size len). Returns the resulting
840 * mbuf chain on success, frees it and returns null on failure.
841 * If there is room, it will add up to max_protohdr-len extra bytes to the
842 * contiguous region in an attempt to avoid being called next time.
843 */
844 int MPFail;
845
846 struct mbuf *
847 m_pullup(struct mbuf *n, int len)
848 {
849 struct mbuf *m;
850 int count;
851 int space;
852
853 /*
854 * If first mbuf has no cluster, and has room for len bytes
855 * without shifting current data, pullup into it,
856 * otherwise allocate a new mbuf to prepend to the chain.
857 */
858 if ((n->m_flags & M_EXT) == 0 &&
859 n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
860 if (n->m_len >= len)
861 return (n);
862 m = n;
863 n = n->m_next;
864 len -= m->m_len;
865 } else {
866 if (len > MHLEN)
867 goto bad;
868 MGET(m, M_DONTWAIT, n->m_type);
869 if (m == 0)
870 goto bad;
871 MCLAIM(m, n->m_owner);
872 m->m_len = 0;
873 if (n->m_flags & M_PKTHDR) {
874 M_MOVE_PKTHDR(m, n);
875 }
876 }
877 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
878 do {
879 count = min(min(max(len, max_protohdr), space), n->m_len);
880 memcpy(mtod(m, char *) + m->m_len, mtod(n, void *),
881 (unsigned)count);
882 len -= count;
883 m->m_len += count;
884 n->m_len -= count;
885 space -= count;
886 if (n->m_len)
887 n->m_data += count;
888 else
889 n = m_free(n);
890 } while (len > 0 && n);
891 if (len > 0) {
892 (void) m_free(m);
893 goto bad;
894 }
895 m->m_next = n;
896 return (m);
897 bad:
898 m_freem(n);
899 MPFail++;
900 return (NULL);
901 }
902
903 /*
904 * Like m_pullup(), except a new mbuf is always allocated, and we allow
905 * the amount of empty space before the data in the new mbuf to be specified
906 * (in the event that the caller expects to prepend later).
907 */
908 int MSFail;
909
910 struct mbuf *
911 m_copyup(struct mbuf *n, int len, int dstoff)
912 {
913 struct mbuf *m;
914 int count, space;
915
916 if (len > (MHLEN - dstoff))
917 goto bad;
918 MGET(m, M_DONTWAIT, n->m_type);
919 if (m == NULL)
920 goto bad;
921 MCLAIM(m, n->m_owner);
922 m->m_len = 0;
923 if (n->m_flags & M_PKTHDR) {
924 M_MOVE_PKTHDR(m, n);
925 }
926 m->m_data += dstoff;
927 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
928 do {
929 count = min(min(max(len, max_protohdr), space), n->m_len);
930 memcpy(mtod(m, char *) + m->m_len, mtod(n, void *),
931 (unsigned)count);
932 len -= count;
933 m->m_len += count;
934 n->m_len -= count;
935 space -= count;
936 if (n->m_len)
937 n->m_data += count;
938 else
939 n = m_free(n);
940 } while (len > 0 && n);
941 if (len > 0) {
942 (void) m_free(m);
943 goto bad;
944 }
945 m->m_next = n;
946 return (m);
947 bad:
948 m_freem(n);
949 MSFail++;
950 return (NULL);
951 }
952
953 /*
954 * Partition an mbuf chain in two pieces, returning the tail --
955 * all but the first len0 bytes. In case of failure, it returns NULL and
956 * attempts to restore the chain to its original state.
957 */
958 struct mbuf *
959 m_split(struct mbuf *m0, int len0, int wait)
960 {
961
962 return m_split0(m0, len0, wait, 1);
963 }
964
965 static struct mbuf *
966 m_split0(struct mbuf *m0, int len0, int wait, int copyhdr)
967 {
968 struct mbuf *m, *n;
969 unsigned len = len0, remain, len_save;
970
971 for (m = m0; m && len > m->m_len; m = m->m_next)
972 len -= m->m_len;
973 if (m == 0)
974 return (NULL);
975 remain = m->m_len - len;
976 if (copyhdr && (m0->m_flags & M_PKTHDR)) {
977 MGETHDR(n, wait, m0->m_type);
978 if (n == 0)
979 return (NULL);
980 MCLAIM(n, m0->m_owner);
981 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
982 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
983 len_save = m0->m_pkthdr.len;
984 m0->m_pkthdr.len = len0;
985 if (m->m_flags & M_EXT)
986 goto extpacket;
987 if (remain > MHLEN) {
988 /* m can't be the lead packet */
989 MH_ALIGN(n, 0);
990 n->m_next = m_split(m, len, wait);
991 if (n->m_next == 0) {
992 (void) m_free(n);
993 m0->m_pkthdr.len = len_save;
994 return (NULL);
995 } else
996 return (n);
997 } else
998 MH_ALIGN(n, remain);
999 } else if (remain == 0) {
1000 n = m->m_next;
1001 m->m_next = 0;
1002 return (n);
1003 } else {
1004 MGET(n, wait, m->m_type);
1005 if (n == 0)
1006 return (NULL);
1007 MCLAIM(n, m->m_owner);
1008 M_ALIGN(n, remain);
1009 }
1010 extpacket:
1011 if (m->m_flags & M_EXT) {
1012 n->m_data = m->m_data + len;
1013 MCLADDREFERENCE(m, n);
1014 } else {
1015 memcpy(mtod(n, void *), mtod(m, char *) + len, remain);
1016 }
1017 n->m_len = remain;
1018 m->m_len = len;
1019 n->m_next = m->m_next;
1020 m->m_next = 0;
1021 return (n);
1022 }
1023 /*
1024 * Routine to copy from device local memory into mbufs.
1025 */
1026 struct mbuf *
1027 m_devget(char *buf, int totlen, int off0, struct ifnet *ifp,
1028 void (*copy)(const void *from, void *to, size_t len))
1029 {
1030 struct mbuf *m;
1031 struct mbuf *top = 0, **mp = ⊤
1032 int off = off0, len;
1033 char *cp;
1034 char *epkt;
1035
1036 cp = buf;
1037 epkt = cp + totlen;
1038 if (off) {
1039 /*
1040 * If 'off' is non-zero, packet is trailer-encapsulated,
1041 * so we have to skip the type and length fields.
1042 */
1043 cp += off + 2 * sizeof(uint16_t);
1044 totlen -= 2 * sizeof(uint16_t);
1045 }
1046 MGETHDR(m, M_DONTWAIT, MT_DATA);
1047 if (m == 0)
1048 return (NULL);
1049 m->m_pkthdr.rcvif = ifp;
1050 m->m_pkthdr.len = totlen;
1051 m->m_len = MHLEN;
1052
1053 while (totlen > 0) {
1054 if (top) {
1055 MGET(m, M_DONTWAIT, MT_DATA);
1056 if (m == 0) {
1057 m_freem(top);
1058 return (NULL);
1059 }
1060 m->m_len = MLEN;
1061 }
1062 len = min(totlen, epkt - cp);
1063 if (len >= MINCLSIZE) {
1064 MCLGET(m, M_DONTWAIT);
1065 if ((m->m_flags & M_EXT) == 0) {
1066 m_free(m);
1067 m_freem(top);
1068 return (NULL);
1069 }
1070 m->m_len = len = min(len, MCLBYTES);
1071 } else {
1072 /*
1073 * Place initial small packet/header at end of mbuf.
1074 */
1075 if (len < m->m_len) {
1076 if (top == 0 && len + max_linkhdr <= m->m_len)
1077 m->m_data += max_linkhdr;
1078 m->m_len = len;
1079 } else
1080 len = m->m_len;
1081 }
1082 if (copy)
1083 copy(cp, mtod(m, void *), (size_t)len);
1084 else
1085 memcpy(mtod(m, void *), cp, (size_t)len);
1086 cp += len;
1087 *mp = m;
1088 mp = &m->m_next;
1089 totlen -= len;
1090 if (cp == epkt)
1091 cp = buf;
1092 }
1093 return (top);
1094 }
1095
1096 /*
1097 * Copy data from a buffer back into the indicated mbuf chain,
1098 * starting "off" bytes from the beginning, extending the mbuf
1099 * chain if necessary.
1100 */
1101 void
1102 m_copyback(struct mbuf *m0, int off, int len, const void *cp)
1103 {
1104 #if defined(DEBUG)
1105 struct mbuf *origm = m0;
1106 int error;
1107 #endif /* defined(DEBUG) */
1108
1109 if (m0 == NULL)
1110 return;
1111
1112 #if defined(DEBUG)
1113 error =
1114 #endif /* defined(DEBUG) */
1115 m_copyback0(&m0, off, len, cp,
1116 M_COPYBACK0_COPYBACK|M_COPYBACK0_EXTEND, M_DONTWAIT);
1117
1118 #if defined(DEBUG)
1119 if (error != 0 || (m0 != NULL && origm != m0))
1120 panic("m_copyback");
1121 #endif /* defined(DEBUG) */
1122 }
1123
1124 struct mbuf *
1125 m_copyback_cow(struct mbuf *m0, int off, int len, const void *cp, int how)
1126 {
1127 int error;
1128
1129 /* don't support chain expansion */
1130 KDASSERT(off + len <= m_length(m0));
1131
1132 error = m_copyback0(&m0, off, len, cp,
1133 M_COPYBACK0_COPYBACK|M_COPYBACK0_COW, how);
1134 if (error) {
1135 /*
1136 * no way to recover from partial success.
1137 * just free the chain.
1138 */
1139 m_freem(m0);
1140 return NULL;
1141 }
1142 return m0;
1143 }
1144
1145 /*
1146 * m_makewritable: ensure the specified range writable.
1147 */
1148 int
1149 m_makewritable(struct mbuf **mp, int off, int len, int how)
1150 {
1151 int error;
1152 #if defined(DEBUG)
1153 struct mbuf *n;
1154 int origlen, reslen;
1155
1156 origlen = m_length(*mp);
1157 #endif /* defined(DEBUG) */
1158
1159 #if 0 /* M_COPYALL is large enough */
1160 if (len == M_COPYALL)
1161 len = m_length(*mp) - off; /* XXX */
1162 #endif
1163
1164 error = m_copyback0(mp, off, len, NULL,
1165 M_COPYBACK0_PRESERVE|M_COPYBACK0_COW, how);
1166
1167 #if defined(DEBUG)
1168 reslen = 0;
1169 for (n = *mp; n; n = n->m_next)
1170 reslen += n->m_len;
1171 if (origlen != reslen)
1172 panic("m_makewritable: length changed");
1173 if (((*mp)->m_flags & M_PKTHDR) != 0 && reslen != (*mp)->m_pkthdr.len)
1174 panic("m_makewritable: inconsist");
1175 #endif /* defined(DEBUG) */
1176
1177 return error;
1178 }
1179
1180 int
1181 m_copyback0(struct mbuf **mp0, int off, int len, const void *vp, int flags,
1182 int how)
1183 {
1184 int mlen;
1185 struct mbuf *m, *n;
1186 struct mbuf **mp;
1187 int totlen = 0;
1188 const char *cp = vp;
1189
1190 KASSERT(mp0 != NULL);
1191 KASSERT(*mp0 != NULL);
1192 KASSERT((flags & M_COPYBACK0_PRESERVE) == 0 || cp == NULL);
1193 KASSERT((flags & M_COPYBACK0_COPYBACK) == 0 || cp != NULL);
1194
1195 /*
1196 * we don't bother to update "totlen" in the case of M_COPYBACK0_COW,
1197 * assuming that M_COPYBACK0_EXTEND and M_COPYBACK0_COW are exclusive.
1198 */
1199
1200 KASSERT((~flags & (M_COPYBACK0_EXTEND|M_COPYBACK0_COW)) != 0);
1201
1202 mp = mp0;
1203 m = *mp;
1204 while (off > (mlen = m->m_len)) {
1205 off -= mlen;
1206 totlen += mlen;
1207 if (m->m_next == NULL) {
1208 int tspace;
1209 extend:
1210 if ((flags & M_COPYBACK0_EXTEND) == 0)
1211 goto out;
1212
1213 /*
1214 * try to make some space at the end of "m".
1215 */
1216
1217 mlen = m->m_len;
1218 if (off + len >= MINCLSIZE &&
1219 (m->m_flags & M_EXT) == 0 && m->m_len == 0) {
1220 MCLGET(m, how);
1221 }
1222 tspace = M_TRAILINGSPACE(m);
1223 if (tspace > 0) {
1224 tspace = min(tspace, off + len);
1225 KASSERT(tspace > 0);
1226 memset(mtod(m, char *) + m->m_len, 0,
1227 min(off, tspace));
1228 m->m_len += tspace;
1229 off += mlen;
1230 totlen -= mlen;
1231 continue;
1232 }
1233
1234 /*
1235 * need to allocate an mbuf.
1236 */
1237
1238 if (off + len >= MINCLSIZE) {
1239 n = m_getcl(how, m->m_type, 0);
1240 } else {
1241 n = m_get(how, m->m_type);
1242 }
1243 if (n == NULL) {
1244 goto out;
1245 }
1246 n->m_len = 0;
1247 n->m_len = min(M_TRAILINGSPACE(n), off + len);
1248 memset(mtod(n, char *), 0, min(n->m_len, off));
1249 m->m_next = n;
1250 }
1251 mp = &m->m_next;
1252 m = m->m_next;
1253 }
1254 while (len > 0) {
1255 mlen = m->m_len - off;
1256 if (mlen != 0 && M_READONLY(m)) {
1257 char *datap;
1258 int eatlen;
1259
1260 /*
1261 * this mbuf is read-only.
1262 * allocate a new writable mbuf and try again.
1263 */
1264
1265 #if defined(DIAGNOSTIC)
1266 if ((flags & M_COPYBACK0_COW) == 0)
1267 panic("m_copyback0: read-only");
1268 #endif /* defined(DIAGNOSTIC) */
1269
1270 /*
1271 * if we're going to write into the middle of
1272 * a mbuf, split it first.
1273 */
1274 if (off > 0 && len < mlen) {
1275 n = m_split0(m, off, how, 0);
1276 if (n == NULL)
1277 goto enobufs;
1278 m->m_next = n;
1279 mp = &m->m_next;
1280 m = n;
1281 off = 0;
1282 continue;
1283 }
1284
1285 /*
1286 * XXX TODO coalesce into the trailingspace of
1287 * the previous mbuf when possible.
1288 */
1289
1290 /*
1291 * allocate a new mbuf. copy packet header if needed.
1292 */
1293 MGET(n, how, m->m_type);
1294 if (n == NULL)
1295 goto enobufs;
1296 MCLAIM(n, m->m_owner);
1297 if (off == 0 && (m->m_flags & M_PKTHDR) != 0) {
1298 M_MOVE_PKTHDR(n, m);
1299 n->m_len = MHLEN;
1300 } else {
1301 if (len >= MINCLSIZE)
1302 MCLGET(n, M_DONTWAIT);
1303 n->m_len =
1304 (n->m_flags & M_EXT) ? MCLBYTES : MLEN;
1305 }
1306 if (n->m_len > len)
1307 n->m_len = len;
1308
1309 /*
1310 * free the region which has been overwritten.
1311 * copying data from old mbufs if requested.
1312 */
1313 if (flags & M_COPYBACK0_PRESERVE)
1314 datap = mtod(n, char *);
1315 else
1316 datap = NULL;
1317 eatlen = n->m_len;
1318 KDASSERT(off == 0 || eatlen >= mlen);
1319 if (off > 0) {
1320 KDASSERT(len >= mlen);
1321 m->m_len = off;
1322 m->m_next = n;
1323 if (datap) {
1324 m_copydata(m, off, mlen, datap);
1325 datap += mlen;
1326 }
1327 eatlen -= mlen;
1328 mp = &m->m_next;
1329 m = m->m_next;
1330 }
1331 while (m != NULL && M_READONLY(m) &&
1332 n->m_type == m->m_type && eatlen > 0) {
1333 mlen = min(eatlen, m->m_len);
1334 if (datap) {
1335 m_copydata(m, 0, mlen, datap);
1336 datap += mlen;
1337 }
1338 m->m_data += mlen;
1339 m->m_len -= mlen;
1340 eatlen -= mlen;
1341 if (m->m_len == 0)
1342 *mp = m = m_free(m);
1343 }
1344 if (eatlen > 0)
1345 n->m_len -= eatlen;
1346 n->m_next = m;
1347 *mp = m = n;
1348 continue;
1349 }
1350 mlen = min(mlen, len);
1351 if (flags & M_COPYBACK0_COPYBACK) {
1352 memcpy(mtod(m, char *) + off, cp, (unsigned)mlen);
1353 cp += mlen;
1354 }
1355 len -= mlen;
1356 mlen += off;
1357 off = 0;
1358 totlen += mlen;
1359 if (len == 0)
1360 break;
1361 if (m->m_next == NULL) {
1362 goto extend;
1363 }
1364 mp = &m->m_next;
1365 m = m->m_next;
1366 }
1367 out: if (((m = *mp0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) {
1368 KASSERT((flags & M_COPYBACK0_EXTEND) != 0);
1369 m->m_pkthdr.len = totlen;
1370 }
1371
1372 return 0;
1373
1374 enobufs:
1375 return ENOBUFS;
1376 }
1377
1378 void
1379 m_move_pkthdr(struct mbuf *to, struct mbuf *from)
1380 {
1381
1382 KASSERT((to->m_flags & M_EXT) == 0);
1383 KASSERT((to->m_flags & M_PKTHDR) == 0 || m_tag_first(to) == NULL);
1384 KASSERT((from->m_flags & M_PKTHDR) != 0);
1385
1386 to->m_pkthdr = from->m_pkthdr;
1387 to->m_flags = from->m_flags & M_COPYFLAGS;
1388 to->m_data = to->m_pktdat;
1389
1390 from->m_flags &= ~M_PKTHDR;
1391 }
1392
1393 /*
1394 * Apply function f to the data in an mbuf chain starting "off" bytes from the
1395 * beginning, continuing for "len" bytes.
1396 */
1397 int
1398 m_apply(struct mbuf *m, int off, int len,
1399 int (*f)(void *, void *, unsigned int), void *arg)
1400 {
1401 unsigned int count;
1402 int rval;
1403
1404 KASSERT(len >= 0);
1405 KASSERT(off >= 0);
1406
1407 while (off > 0) {
1408 KASSERT(m != NULL);
1409 if (off < m->m_len)
1410 break;
1411 off -= m->m_len;
1412 m = m->m_next;
1413 }
1414 while (len > 0) {
1415 KASSERT(m != NULL);
1416 count = min(m->m_len - off, len);
1417
1418 rval = (*f)(arg, mtod(m, char *) + off, count);
1419 if (rval)
1420 return (rval);
1421
1422 len -= count;
1423 off = 0;
1424 m = m->m_next;
1425 }
1426
1427 return (0);
1428 }
1429
1430 /*
1431 * Return a pointer to mbuf/offset of location in mbuf chain.
1432 */
1433 struct mbuf *
1434 m_getptr(struct mbuf *m, int loc, int *off)
1435 {
1436
1437 while (loc >= 0) {
1438 /* Normal end of search */
1439 if (m->m_len > loc) {
1440 *off = loc;
1441 return (m);
1442 } else {
1443 loc -= m->m_len;
1444
1445 if (m->m_next == NULL) {
1446 if (loc == 0) {
1447 /* Point at the end of valid data */
1448 *off = m->m_len;
1449 return (m);
1450 } else
1451 return (NULL);
1452 } else
1453 m = m->m_next;
1454 }
1455 }
1456
1457 return (NULL);
1458 }
1459
1460 /*
1461 * m_ext_free: release a reference to the mbuf external storage.
1462 *
1463 * => free the mbuf m itsself as well.
1464 * => called at splvm.
1465 */
1466
1467 void
1468 m_ext_free(struct mbuf *m)
1469 {
1470 bool embedded = MEXT_ISEMBEDDED(m);
1471 bool dofree = true;
1472
1473 KASSERT((m->m_flags & M_EXT) != 0);
1474 KASSERT(MEXT_ISEMBEDDED(m->m_ext_ref));
1475 KASSERT((m->m_ext_ref->m_flags & M_EXT) != 0);
1476 KASSERT((m->m_flags & M_EXT_CLUSTER) ==
1477 (m->m_ext_ref->m_flags & M_EXT_CLUSTER));
1478
1479 if (!mcl_dec_and_test_reference(m)) {
1480 if (embedded) {
1481 /*
1482 * other mbuf's m_ext_ref still points to us.
1483 */
1484 dofree = false;
1485 } else {
1486 m->m_ext_ref = m;
1487 }
1488 } else {
1489 /*
1490 * dropping the last reference
1491 */
1492 if (!embedded) {
1493 mcl_inc_reference(m); /* XXX */
1494 m_ext_free(m->m_ext_ref);
1495 m->m_ext_ref = m;
1496 } else if ((m->m_flags & M_EXT_CLUSTER) != 0) {
1497 pool_cache_put_paddr((struct pool_cache *)
1498 m->m_ext.ext_arg,
1499 m->m_ext.ext_buf, m->m_ext.ext_paddr);
1500 } else if (m->m_ext.ext_free) {
1501 mutex_destroy(&m->m_ext.ext_lock);
1502 (*m->m_ext.ext_free)(m,
1503 m->m_ext.ext_buf, m->m_ext.ext_size,
1504 m->m_ext.ext_arg);
1505 /*
1506 * 'm' is already freed by the ext_free callback.
1507 */
1508 dofree = false;
1509 } else {
1510 free(m->m_ext.ext_buf, m->m_ext.ext_type);
1511 }
1512 }
1513 if (dofree) {
1514 if (embedded) {
1515 mutex_destroy(&m->m_ext.ext_lock);
1516 }
1517 pool_cache_put(mb_cache, m);
1518 }
1519 }
1520
1521 #if defined(__HAVE_LAZY_MBUF) || defined(DEBUG)
1522 char *
1523 m_mapin(struct mbuf *m)
1524 {
1525
1526 #if defined(__HAVE_LAZY_MBUF)
1527 KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES|M_EXT_LAZY)) == 0);
1528
1529 MEXT_LOCK(m);
1530 if (m->m_ext.ext_flags & M_EXT_LAZY) {
1531 vaddr_t buf = (vaddr_t)m->m_ext.ext_buf;
1532 vsize_t size = (vsize_t)m->m_ext.ext_size;
1533 vaddr_t va, sva, eva;
1534 int i;
1535
1536 sva = trunc_page(buf);
1537 eva = round_page(buf + size);
1538
1539 for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {
1540 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]),
1541 VM_PROT_READ);
1542 }
1543 pmap_update(pmap_kernel());
1544 m->m_ext.ext_flags &= ~M_EXT_LAZY;
1545 }
1546 MEXT_UNLOCK(m);
1547
1548 m->m_flags &= ~M_EXT_LAZY;
1549 return m->m_data;
1550 #else /* defined(__HAVE_LAZY_MBUF) */
1551 panic("m_mapin");
1552 #endif /* defined(__HAVE_LAZY_MBUF) */
1553 }
1554 #endif /* defined(__HAVE_LAZY_MBUF) || defined(DEBUG) */
1555
1556 #if defined(DDB)
1557 void
1558 m_print(const struct mbuf *m, const char *modif, void (*pr)(const char *, ...))
1559 {
1560 char ch;
1561 bool opt_c = false;
1562 char buf[512];
1563
1564 while ((ch = *(modif++)) != '\0') {
1565 switch (ch) {
1566 case 'c':
1567 opt_c = true;
1568 break;
1569 }
1570 }
1571
1572 nextchain:
1573 (*pr)("MBUF %p\n", m);
1574 bitmask_snprintf((u_int)m->m_flags, M_FLAGS_BITS, buf, sizeof(buf));
1575 (*pr)(" data=%p, len=%d, type=%d, flags=0x%s\n",
1576 m->m_data, m->m_len, m->m_type, buf);
1577 (*pr)(" owner=%p, next=%p, nextpkt=%p\n", m->m_owner, m->m_next,
1578 m->m_nextpkt);
1579 (*pr)(" leadingspace=%u, trailingspace=%u, readonly=%u\n",
1580 (int)M_LEADINGSPACE(m), (int)M_TRAILINGSPACE(m),
1581 (int)M_READONLY(m));
1582 if ((m->m_flags & M_PKTHDR) != 0) {
1583 bitmask_snprintf(m->m_pkthdr.csum_flags, M_CSUM_BITS, buf,
1584 sizeof(buf));
1585 (*pr)(" pktlen=%d, rcvif=%p, csum_flags=0x%s, csum_data=0x%"
1586 PRIx32 ", segsz=%u\n",
1587 m->m_pkthdr.len, m->m_pkthdr.rcvif,
1588 buf, m->m_pkthdr.csum_data, m->m_pkthdr.segsz);
1589 }
1590 if ((m->m_flags & M_EXT)) {
1591 (*pr)(" ext_refcnt=%u, ext_buf=%p, ext_size=%zd, "
1592 "ext_free=%p, ext_arg=%p\n",
1593 m->m_ext.ext_refcnt,
1594 m->m_ext.ext_buf, m->m_ext.ext_size,
1595 m->m_ext.ext_free, m->m_ext.ext_arg);
1596 }
1597 if ((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0) {
1598 vaddr_t sva = (vaddr_t)m->m_ext.ext_buf;
1599 vaddr_t eva = sva + m->m_ext.ext_size;
1600 int n = (round_page(eva) - trunc_page(sva)) >> PAGE_SHIFT;
1601 int i;
1602
1603 (*pr)(" pages:");
1604 for (i = 0; i < n; i ++) {
1605 (*pr)(" %p", m->m_ext.ext_pgs[i]);
1606 }
1607 (*pr)("\n");
1608 }
1609
1610 if (opt_c) {
1611 m = m->m_next;
1612 if (m != NULL) {
1613 goto nextchain;
1614 }
1615 }
1616 }
1617 #endif /* defined(DDB) */
1618