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