uipc_mbuf.c revision 1.82 1 /* $NetBSD: uipc_mbuf.c,v 1.82 2004/05/25 04:30:32 atatat 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.82 2004/05/25 04:30:32 atatat Exp $");
73
74 #include "opt_mbuftrace.h"
75
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/proc.h>
79 #include <sys/malloc.h>
80 #define MBTYPES
81 #include <sys/mbuf.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84 #include <sys/domain.h>
85 #include <sys/protosw.h>
86 #include <sys/pool.h>
87 #include <sys/socket.h>
88 #include <sys/sysctl.h>
89
90 #include <net/if.h>
91
92 #include <uvm/uvm.h>
93
94
95 struct pool mbpool; /* mbuf pool */
96 struct pool mclpool; /* mbuf cluster pool */
97
98 struct pool_cache mbpool_cache;
99 struct pool_cache mclpool_cache;
100
101 struct mbstat mbstat;
102 int max_linkhdr;
103 int max_protohdr;
104 int max_hdr;
105 int max_datalen;
106
107 static int mb_ctor(void *, void *, int);
108
109 void *mclpool_alloc(struct pool *, int);
110 void mclpool_release(struct pool *, void *);
111
112 struct pool_allocator mclpool_allocator = {
113 mclpool_alloc, mclpool_release, 0,
114 };
115
116 static struct mbuf *m_copym0(struct mbuf *, int, int, int, int);
117
118 const char mclpool_warnmsg[] =
119 "WARNING: mclpool limit reached; increase NMBCLUSTERS";
120
121 MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
122
123 #ifdef MBUFTRACE
124 struct mownerhead mowners = LIST_HEAD_INITIALIZER(mowners);
125 struct mowner unknown_mowners[] = {
126 { "unknown", "free" },
127 { "unknown", "data" },
128 { "unknown", "header" },
129 { "unknown", "soname" },
130 { "unknown", "soopts" },
131 { "unknown", "ftable" },
132 { "unknown", "control" },
133 { "unknown", "oobdata" },
134 };
135 struct mowner revoked_mowner = { "revoked", "" };
136 #endif
137
138 /*
139 * Initialize the mbuf allocator.
140 */
141 void
142 mbinit(void)
143 {
144
145 KASSERT(sizeof(struct _m_ext) <= MHLEN);
146 KASSERT(sizeof(struct mbuf) == MSIZE);
147
148 pool_init(&mbpool, msize, 0, 0, 0, "mbpl", NULL);
149 pool_init(&mclpool, mclbytes, 0, 0, 0, "mclpl", &mclpool_allocator);
150
151 pool_set_drain_hook(&mbpool, m_reclaim, NULL);
152 pool_set_drain_hook(&mclpool, m_reclaim, NULL);
153
154 pool_cache_init(&mbpool_cache, &mbpool, mb_ctor, NULL, NULL);
155 pool_cache_init(&mclpool_cache, &mclpool, NULL, NULL, NULL);
156
157 /*
158 * Set the hard limit on the mclpool to the number of
159 * mbuf clusters the kernel is to support. Log the limit
160 * reached message max once a minute.
161 */
162 pool_sethardlimit(&mclpool, nmbclusters, mclpool_warnmsg, 60);
163
164 /*
165 * Set a low water mark for both mbufs and clusters. This should
166 * help ensure that they can be allocated in a memory starvation
167 * situation. This is important for e.g. diskless systems which
168 * must allocate mbufs in order for the pagedaemon to clean pages.
169 */
170 pool_setlowat(&mbpool, mblowat);
171 pool_setlowat(&mclpool, mcllowat);
172
173 #ifdef MBUFTRACE
174 {
175 /*
176 * Attach the unknown mowners.
177 */
178 int i;
179 MOWNER_ATTACH(&revoked_mowner);
180 for (i = sizeof(unknown_mowners)/sizeof(unknown_mowners[0]);
181 i-- > 0; )
182 MOWNER_ATTACH(&unknown_mowners[i]);
183 }
184 #endif
185 }
186
187 /*
188 * sysctl helper routine for the kern.mbuf subtree. nmbclusters may
189 * or may not be writable, and mblowat and mcllowat need range
190 * checking and pool tweaking after being reset.
191 */
192 static int
193 sysctl_kern_mbuf(SYSCTLFN_ARGS)
194 {
195 int error, newval;
196 struct sysctlnode node;
197
198 node = *rnode;
199 node.sysctl_data = &newval;
200 switch (rnode->sysctl_num) {
201 case MBUF_NMBCLUSTERS:
202 if (mb_map != NULL) {
203 node.sysctl_flags &= ~CTLFLAG_READWRITE;
204 node.sysctl_flags |= CTLFLAG_READONLY;
205 }
206 /* FALLTHROUGH */
207 case MBUF_MBLOWAT:
208 case MBUF_MCLLOWAT:
209 newval = *(int*)rnode->sysctl_data;
210 break;
211 default:
212 return (EOPNOTSUPP);
213 }
214
215 error = sysctl_lookup(SYSCTLFN_CALL(&node));
216 if (error || newp == NULL)
217 return (error);
218 if (newval < 0)
219 return (EINVAL);
220
221 switch (node.sysctl_num) {
222 case MBUF_NMBCLUSTERS:
223 if (newval < nmbclusters)
224 return (EINVAL);
225 nmbclusters = newval;
226 pool_sethardlimit(&mclpool, nmbclusters, mclpool_warnmsg, 60);
227 break;
228 case MBUF_MBLOWAT:
229 mblowat = newval;
230 pool_setlowat(&mbpool, mblowat);
231 break;
232 case MBUF_MCLLOWAT:
233 mcllowat = newval;
234 pool_setlowat(&mclpool, mcllowat);
235 break;
236 }
237
238 return (0);
239 }
240
241 #ifdef MBUFTRACE
242 static int
243 sysctl_kern_mbuf_mowners(SYSCTLFN_ARGS)
244 {
245 struct mowner *mo;
246 size_t len = 0;
247 int error = 0;
248
249 if (namelen != 0)
250 return (EINVAL);
251 if (newp != NULL)
252 return (EPERM);
253
254 LIST_FOREACH(mo, &mowners, mo_link) {
255 if (oldp != NULL) {
256 if (*oldlenp - len < sizeof(*mo)) {
257 error = ENOMEM;
258 break;
259 }
260 error = copyout(mo, (caddr_t) oldp + len,
261 sizeof(*mo));
262 if (error)
263 break;
264 }
265 len += sizeof(*mo);
266 }
267
268 if (error == 0)
269 *oldlenp = len;
270
271 return (error);
272 }
273 #endif /* MBUFTRACE */
274
275 SYSCTL_SETUP(sysctl_kern_mbuf_setup, "sysctl kern.mbuf subtree setup")
276 {
277
278 sysctl_createv(clog, 0, NULL, NULL,
279 CTLFLAG_PERMANENT,
280 CTLTYPE_NODE, "kern", NULL,
281 NULL, 0, NULL, 0,
282 CTL_KERN, CTL_EOL);
283 sysctl_createv(clog, 0, NULL, NULL,
284 CTLFLAG_PERMANENT,
285 CTLTYPE_NODE, "mbuf",
286 SYSCTL_DESCR("mbuf control variables"),
287 NULL, 0, NULL, 0,
288 CTL_KERN, KERN_MBUF, CTL_EOL);
289
290 sysctl_createv(clog, 0, NULL, NULL,
291 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
292 CTLTYPE_INT, "msize",
293 SYSCTL_DESCR("mbuf base size"),
294 NULL, msize, NULL, 0,
295 CTL_KERN, KERN_MBUF, MBUF_MSIZE, CTL_EOL);
296 sysctl_createv(clog, 0, NULL, NULL,
297 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
298 CTLTYPE_INT, "mclbytes",
299 SYSCTL_DESCR("mbuf cluster size"),
300 NULL, mclbytes, NULL, 0,
301 CTL_KERN, KERN_MBUF, MBUF_MCLBYTES, CTL_EOL);
302 sysctl_createv(clog, 0, NULL, NULL,
303 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
304 CTLTYPE_INT, "nmbclusters",
305 SYSCTL_DESCR("Limit on the number of mbuf clusters"),
306 sysctl_kern_mbuf, 0, &nmbclusters, 0,
307 CTL_KERN, KERN_MBUF, MBUF_NMBCLUSTERS, CTL_EOL);
308 sysctl_createv(clog, 0, NULL, NULL,
309 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
310 CTLTYPE_INT, "mblowat",
311 SYSCTL_DESCR("mbuf low water mark"),
312 sysctl_kern_mbuf, 0, &mblowat, 0,
313 CTL_KERN, KERN_MBUF, MBUF_MBLOWAT, CTL_EOL);
314 sysctl_createv(clog, 0, NULL, NULL,
315 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
316 CTLTYPE_INT, "mcllowat",
317 SYSCTL_DESCR("mbuf cluster low water mark"),
318 sysctl_kern_mbuf, 0, &mcllowat, 0,
319 CTL_KERN, KERN_MBUF, MBUF_MCLLOWAT, CTL_EOL);
320 sysctl_createv(clog, 0, NULL, NULL,
321 CTLFLAG_PERMANENT,
322 CTLTYPE_STRUCT, "stats",
323 SYSCTL_DESCR("mbuf allocation statistics"),
324 NULL, 0, &mbstat, sizeof(mbstat),
325 CTL_KERN, KERN_MBUF, MBUF_STATS, CTL_EOL);
326 #ifdef MBUFTRACE
327 sysctl_createv(clog, 0, NULL, NULL,
328 CTLFLAG_PERMANENT,
329 CTLTYPE_STRUCT, "mowners",
330 SYSCTL_DESCR("Information about mbuf owners"),
331 sysctl_kern_mbuf_mowners, 0, NULL, 0,
332 CTL_KERN, KERN_MBUF, MBUF_MOWNERS, CTL_EOL);
333 #endif /* MBUFTRACE */
334 }
335
336 void *
337 mclpool_alloc(struct pool *pp, int flags)
338 {
339 boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE;
340
341 return ((void *)uvm_km_alloc_poolpage1(mb_map, NULL, waitok));
342 }
343
344 void
345 mclpool_release(struct pool *pp, void *v)
346 {
347
348 uvm_km_free_poolpage1(mb_map, (vaddr_t)v);
349 }
350
351 /*ARGSUSED*/
352 static int
353 mb_ctor(void *arg, void *object, int flags)
354 {
355 struct mbuf *m = object;
356
357 #ifdef POOL_VTOPHYS
358 m->m_paddr = POOL_VTOPHYS(m);
359 #else
360 m->m_paddr = M_PADDR_INVALID;
361 #endif
362 return (0);
363 }
364
365 void
366 m_reclaim(void *arg, int flags)
367 {
368 struct domain *dp;
369 const struct protosw *pr;
370 struct ifnet *ifp;
371 int s = splvm();
372
373 for (dp = domains; dp; dp = dp->dom_next)
374 for (pr = dp->dom_protosw;
375 pr < dp->dom_protoswNPROTOSW; pr++)
376 if (pr->pr_drain)
377 (*pr->pr_drain)();
378 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
379 if (ifp->if_drain)
380 (*ifp->if_drain)(ifp);
381 splx(s);
382 mbstat.m_drain++;
383 }
384
385 /*
386 * Space allocation routines.
387 * These are also available as macros
388 * for critical paths.
389 */
390 struct mbuf *
391 m_get(int nowait, int type)
392 {
393 struct mbuf *m;
394
395 MGET(m, nowait, type);
396 return (m);
397 }
398
399 struct mbuf *
400 m_gethdr(int nowait, int type)
401 {
402 struct mbuf *m;
403
404 MGETHDR(m, nowait, type);
405 return (m);
406 }
407
408 struct mbuf *
409 m_getclr(int nowait, int type)
410 {
411 struct mbuf *m;
412
413 MGET(m, nowait, type);
414 if (m == 0)
415 return (NULL);
416 memset(mtod(m, caddr_t), 0, MLEN);
417 return (m);
418 }
419
420 void
421 m_clget(struct mbuf *m, int nowait)
422 {
423
424 MCLGET(m, nowait);
425 }
426
427 struct mbuf *
428 m_free(struct mbuf *m)
429 {
430 struct mbuf *n;
431
432 MFREE(m, n);
433 return (n);
434 }
435
436 void
437 m_freem(struct mbuf *m)
438 {
439 struct mbuf *n;
440
441 if (m == NULL)
442 return;
443 do {
444 MFREE(m, n);
445 m = n;
446 } while (m);
447 }
448
449 #ifdef MBUFTRACE
450 void
451 m_claim(struct mbuf *m, struct mowner *mo)
452 {
453
454 for (; m != NULL; m = m->m_next)
455 MCLAIM(m, mo);
456 }
457 #endif
458
459 /*
460 * Mbuffer utility routines.
461 */
462
463 /*
464 * Lesser-used path for M_PREPEND:
465 * allocate new mbuf to prepend to chain,
466 * copy junk along.
467 */
468 struct mbuf *
469 m_prepend(struct mbuf *m, int len, int how)
470 {
471 struct mbuf *mn;
472
473 MGET(mn, how, m->m_type);
474 if (mn == (struct mbuf *)NULL) {
475 m_freem(m);
476 return ((struct mbuf *)NULL);
477 }
478 if (m->m_flags & M_PKTHDR) {
479 M_COPY_PKTHDR(mn, m);
480 m_tag_delete_chain(m, NULL);
481 m->m_flags &= ~M_PKTHDR;
482 } else {
483 MCLAIM(mn, m->m_owner);
484 }
485 mn->m_next = m;
486 m = mn;
487 if (len < MHLEN)
488 MH_ALIGN(m, len);
489 m->m_len = len;
490 return (m);
491 }
492
493 /*
494 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
495 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
496 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
497 */
498 int MCFail;
499
500 struct mbuf *
501 m_copym(struct mbuf *m, int off0, int len, int wait)
502 {
503
504 return m_copym0(m, off0, len, wait, 0); /* shallow copy on M_EXT */
505 }
506
507 struct mbuf *
508 m_dup(struct mbuf *m, int off0, int len, int wait)
509 {
510
511 return m_copym0(m, off0, len, wait, 1); /* deep copy */
512 }
513
514 static struct mbuf *
515 m_copym0(struct mbuf *m, int off0, int len, int wait, int deep)
516 {
517 struct mbuf *n, **np;
518 int off = off0;
519 struct mbuf *top;
520 int copyhdr = 0;
521
522 if (off < 0 || len < 0)
523 panic("m_copym: off %d, len %d", off, len);
524 if (off == 0 && m->m_flags & M_PKTHDR)
525 copyhdr = 1;
526 while (off > 0) {
527 if (m == 0)
528 panic("m_copym: m == 0");
529 if (off < m->m_len)
530 break;
531 off -= m->m_len;
532 m = m->m_next;
533 }
534 np = ⊤
535 top = 0;
536 while (len > 0) {
537 if (m == 0) {
538 if (len != M_COPYALL)
539 panic("m_copym: m == 0 and not COPYALL");
540 break;
541 }
542 MGET(n, wait, m->m_type);
543 *np = n;
544 if (n == 0)
545 goto nospace;
546 MCLAIM(n, m->m_owner);
547 if (copyhdr) {
548 M_COPY_PKTHDR(n, m);
549 if (len == M_COPYALL)
550 n->m_pkthdr.len -= off0;
551 else
552 n->m_pkthdr.len = len;
553 copyhdr = 0;
554 }
555 n->m_len = min(len, m->m_len - off);
556 if (m->m_flags & M_EXT) {
557 if (!deep) {
558 n->m_data = m->m_data + off;
559 n->m_ext = m->m_ext;
560 MCLADDREFERENCE(m, n);
561 } else {
562 /*
563 * we are unsure about the way m was allocated.
564 * copy into multiple MCLBYTES cluster mbufs.
565 */
566 MCLGET(n, wait);
567 n->m_len = 0;
568 n->m_len = M_TRAILINGSPACE(n);
569 n->m_len = min(n->m_len, len);
570 n->m_len = min(n->m_len, m->m_len - off);
571 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off,
572 (unsigned)n->m_len);
573 }
574 } else
575 memcpy(mtod(n, caddr_t), mtod(m, caddr_t)+off,
576 (unsigned)n->m_len);
577 if (len != M_COPYALL)
578 len -= n->m_len;
579 off += n->m_len;
580 #ifdef DIAGNOSTIC
581 if (off > m->m_len)
582 panic("m_copym0 overrun");
583 #endif
584 if (off == m->m_len) {
585 m = m->m_next;
586 off = 0;
587 }
588 np = &n->m_next;
589 }
590 if (top == 0)
591 MCFail++;
592 return (top);
593 nospace:
594 m_freem(top);
595 MCFail++;
596 return (NULL);
597 }
598
599 /*
600 * Copy an entire packet, including header (which must be present).
601 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
602 */
603 struct mbuf *
604 m_copypacket(struct mbuf *m, int how)
605 {
606 struct mbuf *top, *n, *o;
607
608 MGET(n, how, m->m_type);
609 top = n;
610 if (!n)
611 goto nospace;
612
613 MCLAIM(n, m->m_owner);
614 M_COPY_PKTHDR(n, m);
615 n->m_len = m->m_len;
616 if (m->m_flags & M_EXT) {
617 n->m_data = m->m_data;
618 n->m_ext = m->m_ext;
619 MCLADDREFERENCE(m, n);
620 } else {
621 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
622 }
623
624 m = m->m_next;
625 while (m) {
626 MGET(o, how, m->m_type);
627 if (!o)
628 goto nospace;
629
630 MCLAIM(o, m->m_owner);
631 n->m_next = o;
632 n = n->m_next;
633
634 n->m_len = m->m_len;
635 if (m->m_flags & M_EXT) {
636 n->m_data = m->m_data;
637 n->m_ext = m->m_ext;
638 MCLADDREFERENCE(m, n);
639 } else {
640 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
641 }
642
643 m = m->m_next;
644 }
645 return top;
646 nospace:
647 m_freem(top);
648 MCFail++;
649 return NULL;
650 }
651
652 /*
653 * Copy data from an mbuf chain starting "off" bytes from the beginning,
654 * continuing for "len" bytes, into the indicated buffer.
655 */
656 void
657 m_copydata(struct mbuf *m, int off, int len, caddr_t cp)
658 {
659 unsigned count;
660
661 if (off < 0 || len < 0)
662 panic("m_copydata");
663 while (off > 0) {
664 if (m == 0)
665 panic("m_copydata");
666 if (off < m->m_len)
667 break;
668 off -= m->m_len;
669 m = m->m_next;
670 }
671 while (len > 0) {
672 if (m == 0)
673 panic("m_copydata");
674 count = min(m->m_len - off, len);
675 memcpy(cp, mtod(m, caddr_t) + off, count);
676 len -= count;
677 cp += count;
678 off = 0;
679 m = m->m_next;
680 }
681 }
682
683 /*
684 * Concatenate mbuf chain n to m.
685 * n might be copied into m (when n->m_len is small), therefore data portion of
686 * n could be copied into an mbuf of different mbuf type.
687 * Therefore both chains should be of the same type (e.g. MT_DATA).
688 * Any m_pkthdr is not updated.
689 */
690 void
691 m_cat(struct mbuf *m, struct mbuf *n)
692 {
693
694 while (m->m_next)
695 m = m->m_next;
696 while (n) {
697 if (M_READONLY(m) || n->m_len > M_TRAILINGSPACE(m)) {
698 /* just join the two chains */
699 m->m_next = n;
700 return;
701 }
702 KASSERT(n->m_len == 0 || m->m_type == n->m_type);
703 /* splat the data from one into the other */
704 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
705 (u_int)n->m_len);
706 m->m_len += n->m_len;
707 n = m_free(n);
708 }
709 }
710
711 void
712 m_adj(struct mbuf *mp, int req_len)
713 {
714 int len = req_len;
715 struct mbuf *m;
716 int count;
717
718 if ((m = mp) == NULL)
719 return;
720 if (len >= 0) {
721 /*
722 * Trim from head.
723 */
724 while (m != NULL && len > 0) {
725 if (m->m_len <= len) {
726 len -= m->m_len;
727 m->m_len = 0;
728 m = m->m_next;
729 } else {
730 m->m_len -= len;
731 m->m_data += len;
732 len = 0;
733 }
734 }
735 m = mp;
736 if (mp->m_flags & M_PKTHDR)
737 m->m_pkthdr.len -= (req_len - len);
738 } else {
739 /*
740 * Trim from tail. Scan the mbuf chain,
741 * calculating its length and finding the last mbuf.
742 * If the adjustment only affects this mbuf, then just
743 * adjust and return. Otherwise, rescan and truncate
744 * after the remaining size.
745 */
746 len = -len;
747 count = 0;
748 for (;;) {
749 count += m->m_len;
750 if (m->m_next == (struct mbuf *)0)
751 break;
752 m = m->m_next;
753 }
754 if (m->m_len >= len) {
755 m->m_len -= len;
756 if (mp->m_flags & M_PKTHDR)
757 mp->m_pkthdr.len -= len;
758 return;
759 }
760 count -= len;
761 if (count < 0)
762 count = 0;
763 /*
764 * Correct length for chain is "count".
765 * Find the mbuf with last data, adjust its length,
766 * and toss data from remaining mbufs on chain.
767 */
768 m = mp;
769 if (m->m_flags & M_PKTHDR)
770 m->m_pkthdr.len = count;
771 for (; m; m = m->m_next) {
772 if (m->m_len >= count) {
773 m->m_len = count;
774 break;
775 }
776 count -= m->m_len;
777 }
778 while (m->m_next)
779 (m = m->m_next) ->m_len = 0;
780 }
781 }
782
783 /*
784 * Rearange an mbuf chain so that len bytes are contiguous
785 * and in the data area of an mbuf (so that mtod and dtom
786 * will work for a structure of size len). Returns the resulting
787 * mbuf chain on success, frees it and returns null on failure.
788 * If there is room, it will add up to max_protohdr-len extra bytes to the
789 * contiguous region in an attempt to avoid being called next time.
790 */
791 int MPFail;
792
793 struct mbuf *
794 m_pullup(struct mbuf *n, int len)
795 {
796 struct mbuf *m;
797 int count;
798 int space;
799
800 /*
801 * If first mbuf has no cluster, and has room for len bytes
802 * without shifting current data, pullup into it,
803 * otherwise allocate a new mbuf to prepend to the chain.
804 */
805 if ((n->m_flags & M_EXT) == 0 &&
806 n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
807 if (n->m_len >= len)
808 return (n);
809 m = n;
810 n = n->m_next;
811 len -= m->m_len;
812 } else {
813 if (len > MHLEN)
814 goto bad;
815 MGET(m, M_DONTWAIT, n->m_type);
816 if (m == 0)
817 goto bad;
818 MCLAIM(m, n->m_owner);
819 m->m_len = 0;
820 if (n->m_flags & M_PKTHDR) {
821 M_COPY_PKTHDR(m, n);
822 m_tag_delete_chain(n, NULL);
823 n->m_flags &= ~M_PKTHDR;
824 }
825 }
826 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
827 do {
828 count = min(min(max(len, max_protohdr), space), n->m_len);
829 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
830 (unsigned)count);
831 len -= count;
832 m->m_len += count;
833 n->m_len -= count;
834 space -= count;
835 if (n->m_len)
836 n->m_data += count;
837 else
838 n = m_free(n);
839 } while (len > 0 && n);
840 if (len > 0) {
841 (void) m_free(m);
842 goto bad;
843 }
844 m->m_next = n;
845 return (m);
846 bad:
847 m_freem(n);
848 MPFail++;
849 return (NULL);
850 }
851
852 /*
853 * Like m_pullup(), except a new mbuf is always allocated, and we allow
854 * the amount of empty space before the data in the new mbuf to be specified
855 * (in the event that the caller expects to prepend later).
856 */
857 int MSFail;
858
859 struct mbuf *
860 m_copyup(struct mbuf *n, int len, int dstoff)
861 {
862 struct mbuf *m;
863 int count, space;
864
865 if (len > (MHLEN - dstoff))
866 goto bad;
867 MGET(m, M_DONTWAIT, n->m_type);
868 if (m == NULL)
869 goto bad;
870 MCLAIM(m, n->m_owner);
871 m->m_len = 0;
872 if (n->m_flags & M_PKTHDR) {
873 M_COPY_PKTHDR(m, n);
874 m_tag_delete_chain(m, NULL);
875 n->m_flags &= ~M_PKTHDR;
876 }
877 m->m_data += dstoff;
878 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
879 do {
880 count = min(min(max(len, max_protohdr), space), n->m_len);
881 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
882 (unsigned)count);
883 len -= count;
884 m->m_len += count;
885 n->m_len -= count;
886 space -= count;
887 if (n->m_len)
888 n->m_data += count;
889 else
890 n = m_free(n);
891 } while (len > 0 && n);
892 if (len > 0) {
893 (void) m_free(m);
894 goto bad;
895 }
896 m->m_next = n;
897 return (m);
898 bad:
899 m_freem(n);
900 MSFail++;
901 return (NULL);
902 }
903
904 /*
905 * Partition an mbuf chain in two pieces, returning the tail --
906 * all but the first len0 bytes. In case of failure, it returns NULL and
907 * attempts to restore the chain to its original state.
908 */
909 struct mbuf *
910 m_split(struct mbuf *m0, int len0, int wait)
911 {
912 struct mbuf *m, *n;
913 unsigned len = len0, remain, len_save;
914
915 for (m = m0; m && len > m->m_len; m = m->m_next)
916 len -= m->m_len;
917 if (m == 0)
918 return (NULL);
919 remain = m->m_len - len;
920 if (m0->m_flags & M_PKTHDR) {
921 MGETHDR(n, wait, m0->m_type);
922 if (n == 0)
923 return (NULL);
924 MCLAIM(m, m0->m_owner);
925 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
926 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
927 len_save = m0->m_pkthdr.len;
928 m0->m_pkthdr.len = len0;
929 if (m->m_flags & M_EXT)
930 goto extpacket;
931 if (remain > MHLEN) {
932 /* m can't be the lead packet */
933 MH_ALIGN(n, 0);
934 n->m_next = m_split(m, len, wait);
935 if (n->m_next == 0) {
936 (void) m_free(n);
937 m0->m_pkthdr.len = len_save;
938 return (NULL);
939 } else
940 return (n);
941 } else
942 MH_ALIGN(n, remain);
943 } else if (remain == 0) {
944 n = m->m_next;
945 m->m_next = 0;
946 return (n);
947 } else {
948 MGET(n, wait, m->m_type);
949 if (n == 0)
950 return (NULL);
951 MCLAIM(n, m->m_owner);
952 M_ALIGN(n, remain);
953 }
954 extpacket:
955 if (m->m_flags & M_EXT) {
956 n->m_ext = m->m_ext;
957 MCLADDREFERENCE(m, n);
958 n->m_data = m->m_data + len;
959 } else {
960 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain);
961 }
962 n->m_len = remain;
963 m->m_len = len;
964 n->m_next = m->m_next;
965 m->m_next = 0;
966 return (n);
967 }
968 /*
969 * Routine to copy from device local memory into mbufs.
970 */
971 struct mbuf *
972 m_devget(char *buf, int totlen, int off0, struct ifnet *ifp,
973 void (*copy)(const void *from, void *to, size_t len))
974 {
975 struct mbuf *m;
976 struct mbuf *top = 0, **mp = ⊤
977 int off = off0, len;
978 char *cp;
979 char *epkt;
980
981 cp = buf;
982 epkt = cp + totlen;
983 if (off) {
984 /*
985 * If 'off' is non-zero, packet is trailer-encapsulated,
986 * so we have to skip the type and length fields.
987 */
988 cp += off + 2 * sizeof(u_int16_t);
989 totlen -= 2 * sizeof(u_int16_t);
990 }
991 MGETHDR(m, M_DONTWAIT, MT_DATA);
992 if (m == 0)
993 return (NULL);
994 m->m_pkthdr.rcvif = ifp;
995 m->m_pkthdr.len = totlen;
996 m->m_len = MHLEN;
997
998 while (totlen > 0) {
999 if (top) {
1000 MGET(m, M_DONTWAIT, MT_DATA);
1001 if (m == 0) {
1002 m_freem(top);
1003 return (NULL);
1004 }
1005 m->m_len = MLEN;
1006 }
1007 len = min(totlen, epkt - cp);
1008 if (len >= MINCLSIZE) {
1009 MCLGET(m, M_DONTWAIT);
1010 if ((m->m_flags & M_EXT) == 0) {
1011 m_free(m);
1012 m_freem(top);
1013 return (NULL);
1014 }
1015 m->m_len = len = min(len, MCLBYTES);
1016 } else {
1017 /*
1018 * Place initial small packet/header at end of mbuf.
1019 */
1020 if (len < m->m_len) {
1021 if (top == 0 && len + max_linkhdr <= m->m_len)
1022 m->m_data += max_linkhdr;
1023 m->m_len = len;
1024 } else
1025 len = m->m_len;
1026 }
1027 if (copy)
1028 copy(cp, mtod(m, caddr_t), (size_t)len);
1029 else
1030 memcpy(mtod(m, caddr_t), cp, (size_t)len);
1031 cp += len;
1032 *mp = m;
1033 mp = &m->m_next;
1034 totlen -= len;
1035 if (cp == epkt)
1036 cp = buf;
1037 }
1038 return (top);
1039 }
1040
1041 /*
1042 * Copy data from a buffer back into the indicated mbuf chain,
1043 * starting "off" bytes from the beginning, extending the mbuf
1044 * chain if necessary.
1045 */
1046 void
1047 m_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
1048 {
1049 int mlen;
1050 struct mbuf *m = m0, *n;
1051 int totlen = 0;
1052
1053 if (m0 == 0)
1054 return;
1055 while (off > (mlen = m->m_len)) {
1056 off -= mlen;
1057 totlen += mlen;
1058 if (m->m_next == 0) {
1059 n = m_getclr(M_DONTWAIT, m->m_type);
1060 if (n == 0)
1061 goto out;
1062 n->m_len = min(MLEN, len + off);
1063 m->m_next = n;
1064 }
1065 m = m->m_next;
1066 }
1067 while (len > 0) {
1068 mlen = min (m->m_len - off, len);
1069 memcpy(mtod(m, caddr_t) + off, cp, (unsigned)mlen);
1070 cp += mlen;
1071 len -= mlen;
1072 mlen += off;
1073 off = 0;
1074 totlen += mlen;
1075 if (len == 0)
1076 break;
1077 if (m->m_next == 0) {
1078 n = m_get(M_DONTWAIT, m->m_type);
1079 if (n == 0)
1080 break;
1081 n->m_len = min(MLEN, len);
1082 m->m_next = n;
1083 }
1084 m = m->m_next;
1085 }
1086 out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1087 m->m_pkthdr.len = totlen;
1088 }
1089
1090 /*
1091 * Apply function f to the data in an mbuf chain starting "off" bytes from the
1092 * beginning, continuing for "len" bytes.
1093 */
1094 int
1095 m_apply(struct mbuf *m, int off, int len,
1096 int (*f)(void *, caddr_t, unsigned int), void *arg)
1097 {
1098 unsigned int count;
1099 int rval;
1100
1101 KASSERT(len >= 0);
1102 KASSERT(off >= 0);
1103
1104 while (off > 0) {
1105 KASSERT(m != NULL);
1106 if (off < m->m_len)
1107 break;
1108 off -= m->m_len;
1109 m = m->m_next;
1110 }
1111 while (len > 0) {
1112 KASSERT(m != NULL);
1113 count = min(m->m_len - off, len);
1114
1115 rval = (*f)(arg, mtod(m, caddr_t) + off, count);
1116 if (rval)
1117 return (rval);
1118
1119 len -= count;
1120 off = 0;
1121 m = m->m_next;
1122 }
1123
1124 return (0);
1125 }
1126
1127 /*
1128 * Return a pointer to mbuf/offset of location in mbuf chain.
1129 */
1130 struct mbuf *
1131 m_getptr(struct mbuf *m, int loc, int *off)
1132 {
1133
1134 while (loc >= 0) {
1135 /* Normal end of search */
1136 if (m->m_len > loc) {
1137 *off = loc;
1138 return (m);
1139 } else {
1140 loc -= m->m_len;
1141
1142 if (m->m_next == NULL) {
1143 if (loc == 0) {
1144 /* Point at the end of valid data */
1145 *off = m->m_len;
1146 return (m);
1147 } else
1148 return (NULL);
1149 } else
1150 m = m->m_next;
1151 }
1152 }
1153
1154 return (NULL);
1155 }
1156