uipc_mbuf.c revision 1.83 1 /* $NetBSD: uipc_mbuf.c,v 1.83 2004/06/24 04:15:50 jonathan 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.83 2004/06/24 04:15:50 jonathan 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 /*
451 * Walk a chain of mbufs, claiming ownership of each mbuf in the chain.
452 */
453 void
454 m_claimm(struct mbuf *m, struct mowner *mo)
455 {
456
457 for (; m != NULL; m = m->m_next)
458 MCLAIM(m, mo);
459 }
460 #endif
461
462 /*
463 * Mbuffer utility routines.
464 */
465
466 /*
467 * Lesser-used path for M_PREPEND:
468 * allocate new mbuf to prepend to chain,
469 * copy junk along.
470 */
471 struct mbuf *
472 m_prepend(struct mbuf *m, int len, int how)
473 {
474 struct mbuf *mn;
475
476 MGET(mn, how, m->m_type);
477 if (mn == (struct mbuf *)NULL) {
478 m_freem(m);
479 return ((struct mbuf *)NULL);
480 }
481 if (m->m_flags & M_PKTHDR) {
482 M_COPY_PKTHDR(mn, m);
483 m_tag_delete_chain(m, NULL);
484 m->m_flags &= ~M_PKTHDR;
485 } else {
486 MCLAIM(mn, m->m_owner);
487 }
488 mn->m_next = m;
489 m = mn;
490 if (len < MHLEN)
491 MH_ALIGN(m, len);
492 m->m_len = len;
493 return (m);
494 }
495
496 /*
497 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
498 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
499 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
500 */
501 int MCFail;
502
503 struct mbuf *
504 m_copym(struct mbuf *m, int off0, int len, int wait)
505 {
506
507 return m_copym0(m, off0, len, wait, 0); /* shallow copy on M_EXT */
508 }
509
510 struct mbuf *
511 m_dup(struct mbuf *m, int off0, int len, int wait)
512 {
513
514 return m_copym0(m, off0, len, wait, 1); /* deep copy */
515 }
516
517 static struct mbuf *
518 m_copym0(struct mbuf *m, int off0, int len, int wait, int deep)
519 {
520 struct mbuf *n, **np;
521 int off = off0;
522 struct mbuf *top;
523 int copyhdr = 0;
524
525 if (off < 0 || len < 0)
526 panic("m_copym: off %d, len %d", off, len);
527 if (off == 0 && m->m_flags & M_PKTHDR)
528 copyhdr = 1;
529 while (off > 0) {
530 if (m == 0)
531 panic("m_copym: m == 0");
532 if (off < m->m_len)
533 break;
534 off -= m->m_len;
535 m = m->m_next;
536 }
537 np = ⊤
538 top = 0;
539 while (len > 0) {
540 if (m == 0) {
541 if (len != M_COPYALL)
542 panic("m_copym: m == 0 and not COPYALL");
543 break;
544 }
545 MGET(n, wait, m->m_type);
546 *np = n;
547 if (n == 0)
548 goto nospace;
549 MCLAIM(n, m->m_owner);
550 if (copyhdr) {
551 M_COPY_PKTHDR(n, m);
552 if (len == M_COPYALL)
553 n->m_pkthdr.len -= off0;
554 else
555 n->m_pkthdr.len = len;
556 copyhdr = 0;
557 }
558 n->m_len = min(len, m->m_len - off);
559 if (m->m_flags & M_EXT) {
560 if (!deep) {
561 n->m_data = m->m_data + off;
562 n->m_ext = m->m_ext;
563 MCLADDREFERENCE(m, n);
564 } else {
565 /*
566 * we are unsure about the way m was allocated.
567 * copy into multiple MCLBYTES cluster mbufs.
568 */
569 MCLGET(n, wait);
570 n->m_len = 0;
571 n->m_len = M_TRAILINGSPACE(n);
572 n->m_len = min(n->m_len, len);
573 n->m_len = min(n->m_len, m->m_len - off);
574 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off,
575 (unsigned)n->m_len);
576 }
577 } else
578 memcpy(mtod(n, caddr_t), mtod(m, caddr_t)+off,
579 (unsigned)n->m_len);
580 if (len != M_COPYALL)
581 len -= n->m_len;
582 off += n->m_len;
583 #ifdef DIAGNOSTIC
584 if (off > m->m_len)
585 panic("m_copym0 overrun");
586 #endif
587 if (off == m->m_len) {
588 m = m->m_next;
589 off = 0;
590 }
591 np = &n->m_next;
592 }
593 if (top == 0)
594 MCFail++;
595 return (top);
596 nospace:
597 m_freem(top);
598 MCFail++;
599 return (NULL);
600 }
601
602 /*
603 * Copy an entire packet, including header (which must be present).
604 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
605 */
606 struct mbuf *
607 m_copypacket(struct mbuf *m, int how)
608 {
609 struct mbuf *top, *n, *o;
610
611 MGET(n, how, m->m_type);
612 top = n;
613 if (!n)
614 goto nospace;
615
616 MCLAIM(n, m->m_owner);
617 M_COPY_PKTHDR(n, m);
618 n->m_len = m->m_len;
619 if (m->m_flags & M_EXT) {
620 n->m_data = m->m_data;
621 n->m_ext = m->m_ext;
622 MCLADDREFERENCE(m, n);
623 } else {
624 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
625 }
626
627 m = m->m_next;
628 while (m) {
629 MGET(o, how, m->m_type);
630 if (!o)
631 goto nospace;
632
633 MCLAIM(o, m->m_owner);
634 n->m_next = o;
635 n = n->m_next;
636
637 n->m_len = m->m_len;
638 if (m->m_flags & M_EXT) {
639 n->m_data = m->m_data;
640 n->m_ext = m->m_ext;
641 MCLADDREFERENCE(m, n);
642 } else {
643 memcpy(mtod(n, char *), mtod(m, char *), n->m_len);
644 }
645
646 m = m->m_next;
647 }
648 return top;
649 nospace:
650 m_freem(top);
651 MCFail++;
652 return NULL;
653 }
654
655 /*
656 * Copy data from an mbuf chain starting "off" bytes from the beginning,
657 * continuing for "len" bytes, into the indicated buffer.
658 */
659 void
660 m_copydata(struct mbuf *m, int off, int len, caddr_t cp)
661 {
662 unsigned count;
663
664 if (off < 0 || len < 0)
665 panic("m_copydata");
666 while (off > 0) {
667 if (m == 0)
668 panic("m_copydata");
669 if (off < m->m_len)
670 break;
671 off -= m->m_len;
672 m = m->m_next;
673 }
674 while (len > 0) {
675 if (m == 0)
676 panic("m_copydata");
677 count = min(m->m_len - off, len);
678 memcpy(cp, mtod(m, caddr_t) + off, count);
679 len -= count;
680 cp += count;
681 off = 0;
682 m = m->m_next;
683 }
684 }
685
686 /*
687 * Concatenate mbuf chain n to m.
688 * n might be copied into m (when n->m_len is small), therefore data portion of
689 * n could be copied into an mbuf of different mbuf type.
690 * Therefore both chains should be of the same type (e.g. MT_DATA).
691 * Any m_pkthdr is not updated.
692 */
693 void
694 m_cat(struct mbuf *m, struct mbuf *n)
695 {
696
697 while (m->m_next)
698 m = m->m_next;
699 while (n) {
700 if (M_READONLY(m) || n->m_len > M_TRAILINGSPACE(m)) {
701 /* just join the two chains */
702 m->m_next = n;
703 return;
704 }
705 KASSERT(n->m_len == 0 || m->m_type == n->m_type);
706 /* splat the data from one into the other */
707 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
708 (u_int)n->m_len);
709 m->m_len += n->m_len;
710 n = m_free(n);
711 }
712 }
713
714 void
715 m_adj(struct mbuf *mp, int req_len)
716 {
717 int len = req_len;
718 struct mbuf *m;
719 int count;
720
721 if ((m = mp) == NULL)
722 return;
723 if (len >= 0) {
724 /*
725 * Trim from head.
726 */
727 while (m != NULL && len > 0) {
728 if (m->m_len <= len) {
729 len -= m->m_len;
730 m->m_len = 0;
731 m = m->m_next;
732 } else {
733 m->m_len -= len;
734 m->m_data += len;
735 len = 0;
736 }
737 }
738 m = mp;
739 if (mp->m_flags & M_PKTHDR)
740 m->m_pkthdr.len -= (req_len - len);
741 } else {
742 /*
743 * Trim from tail. Scan the mbuf chain,
744 * calculating its length and finding the last mbuf.
745 * If the adjustment only affects this mbuf, then just
746 * adjust and return. Otherwise, rescan and truncate
747 * after the remaining size.
748 */
749 len = -len;
750 count = 0;
751 for (;;) {
752 count += m->m_len;
753 if (m->m_next == (struct mbuf *)0)
754 break;
755 m = m->m_next;
756 }
757 if (m->m_len >= len) {
758 m->m_len -= len;
759 if (mp->m_flags & M_PKTHDR)
760 mp->m_pkthdr.len -= len;
761 return;
762 }
763 count -= len;
764 if (count < 0)
765 count = 0;
766 /*
767 * Correct length for chain is "count".
768 * Find the mbuf with last data, adjust its length,
769 * and toss data from remaining mbufs on chain.
770 */
771 m = mp;
772 if (m->m_flags & M_PKTHDR)
773 m->m_pkthdr.len = count;
774 for (; m; m = m->m_next) {
775 if (m->m_len >= count) {
776 m->m_len = count;
777 break;
778 }
779 count -= m->m_len;
780 }
781 while (m->m_next)
782 (m = m->m_next) ->m_len = 0;
783 }
784 }
785
786 /*
787 * Rearange an mbuf chain so that len bytes are contiguous
788 * and in the data area of an mbuf (so that mtod and dtom
789 * will work for a structure of size len). Returns the resulting
790 * mbuf chain on success, frees it and returns null on failure.
791 * If there is room, it will add up to max_protohdr-len extra bytes to the
792 * contiguous region in an attempt to avoid being called next time.
793 */
794 int MPFail;
795
796 struct mbuf *
797 m_pullup(struct mbuf *n, int len)
798 {
799 struct mbuf *m;
800 int count;
801 int space;
802
803 /*
804 * If first mbuf has no cluster, and has room for len bytes
805 * without shifting current data, pullup into it,
806 * otherwise allocate a new mbuf to prepend to the chain.
807 */
808 if ((n->m_flags & M_EXT) == 0 &&
809 n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
810 if (n->m_len >= len)
811 return (n);
812 m = n;
813 n = n->m_next;
814 len -= m->m_len;
815 } else {
816 if (len > MHLEN)
817 goto bad;
818 MGET(m, M_DONTWAIT, n->m_type);
819 if (m == 0)
820 goto bad;
821 MCLAIM(m, n->m_owner);
822 m->m_len = 0;
823 if (n->m_flags & M_PKTHDR) {
824 M_COPY_PKTHDR(m, n);
825 m_tag_delete_chain(n, NULL);
826 n->m_flags &= ~M_PKTHDR;
827 }
828 }
829 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
830 do {
831 count = min(min(max(len, max_protohdr), space), n->m_len);
832 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
833 (unsigned)count);
834 len -= count;
835 m->m_len += count;
836 n->m_len -= count;
837 space -= count;
838 if (n->m_len)
839 n->m_data += count;
840 else
841 n = m_free(n);
842 } while (len > 0 && n);
843 if (len > 0) {
844 (void) m_free(m);
845 goto bad;
846 }
847 m->m_next = n;
848 return (m);
849 bad:
850 m_freem(n);
851 MPFail++;
852 return (NULL);
853 }
854
855 /*
856 * Like m_pullup(), except a new mbuf is always allocated, and we allow
857 * the amount of empty space before the data in the new mbuf to be specified
858 * (in the event that the caller expects to prepend later).
859 */
860 int MSFail;
861
862 struct mbuf *
863 m_copyup(struct mbuf *n, int len, int dstoff)
864 {
865 struct mbuf *m;
866 int count, space;
867
868 if (len > (MHLEN - dstoff))
869 goto bad;
870 MGET(m, M_DONTWAIT, n->m_type);
871 if (m == NULL)
872 goto bad;
873 MCLAIM(m, n->m_owner);
874 m->m_len = 0;
875 if (n->m_flags & M_PKTHDR) {
876 M_COPY_PKTHDR(m, n);
877 m_tag_delete_chain(m, NULL);
878 n->m_flags &= ~M_PKTHDR;
879 }
880 m->m_data += dstoff;
881 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
882 do {
883 count = min(min(max(len, max_protohdr), space), n->m_len);
884 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
885 (unsigned)count);
886 len -= count;
887 m->m_len += count;
888 n->m_len -= count;
889 space -= count;
890 if (n->m_len)
891 n->m_data += count;
892 else
893 n = m_free(n);
894 } while (len > 0 && n);
895 if (len > 0) {
896 (void) m_free(m);
897 goto bad;
898 }
899 m->m_next = n;
900 return (m);
901 bad:
902 m_freem(n);
903 MSFail++;
904 return (NULL);
905 }
906
907 /*
908 * Partition an mbuf chain in two pieces, returning the tail --
909 * all but the first len0 bytes. In case of failure, it returns NULL and
910 * attempts to restore the chain to its original state.
911 */
912 struct mbuf *
913 m_split(struct mbuf *m0, int len0, int wait)
914 {
915 struct mbuf *m, *n;
916 unsigned len = len0, remain, len_save;
917
918 for (m = m0; m && len > m->m_len; m = m->m_next)
919 len -= m->m_len;
920 if (m == 0)
921 return (NULL);
922 remain = m->m_len - len;
923 if (m0->m_flags & M_PKTHDR) {
924 MGETHDR(n, wait, m0->m_type);
925 if (n == 0)
926 return (NULL);
927 MCLAIM(m, m0->m_owner);
928 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
929 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
930 len_save = m0->m_pkthdr.len;
931 m0->m_pkthdr.len = len0;
932 if (m->m_flags & M_EXT)
933 goto extpacket;
934 if (remain > MHLEN) {
935 /* m can't be the lead packet */
936 MH_ALIGN(n, 0);
937 n->m_next = m_split(m, len, wait);
938 if (n->m_next == 0) {
939 (void) m_free(n);
940 m0->m_pkthdr.len = len_save;
941 return (NULL);
942 } else
943 return (n);
944 } else
945 MH_ALIGN(n, remain);
946 } else if (remain == 0) {
947 n = m->m_next;
948 m->m_next = 0;
949 return (n);
950 } else {
951 MGET(n, wait, m->m_type);
952 if (n == 0)
953 return (NULL);
954 MCLAIM(n, m->m_owner);
955 M_ALIGN(n, remain);
956 }
957 extpacket:
958 if (m->m_flags & M_EXT) {
959 n->m_ext = m->m_ext;
960 MCLADDREFERENCE(m, n);
961 n->m_data = m->m_data + len;
962 } else {
963 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain);
964 }
965 n->m_len = remain;
966 m->m_len = len;
967 n->m_next = m->m_next;
968 m->m_next = 0;
969 return (n);
970 }
971 /*
972 * Routine to copy from device local memory into mbufs.
973 */
974 struct mbuf *
975 m_devget(char *buf, int totlen, int off0, struct ifnet *ifp,
976 void (*copy)(const void *from, void *to, size_t len))
977 {
978 struct mbuf *m;
979 struct mbuf *top = 0, **mp = ⊤
980 int off = off0, len;
981 char *cp;
982 char *epkt;
983
984 cp = buf;
985 epkt = cp + totlen;
986 if (off) {
987 /*
988 * If 'off' is non-zero, packet is trailer-encapsulated,
989 * so we have to skip the type and length fields.
990 */
991 cp += off + 2 * sizeof(u_int16_t);
992 totlen -= 2 * sizeof(u_int16_t);
993 }
994 MGETHDR(m, M_DONTWAIT, MT_DATA);
995 if (m == 0)
996 return (NULL);
997 m->m_pkthdr.rcvif = ifp;
998 m->m_pkthdr.len = totlen;
999 m->m_len = MHLEN;
1000
1001 while (totlen > 0) {
1002 if (top) {
1003 MGET(m, M_DONTWAIT, MT_DATA);
1004 if (m == 0) {
1005 m_freem(top);
1006 return (NULL);
1007 }
1008 m->m_len = MLEN;
1009 }
1010 len = min(totlen, epkt - cp);
1011 if (len >= MINCLSIZE) {
1012 MCLGET(m, M_DONTWAIT);
1013 if ((m->m_flags & M_EXT) == 0) {
1014 m_free(m);
1015 m_freem(top);
1016 return (NULL);
1017 }
1018 m->m_len = len = min(len, MCLBYTES);
1019 } else {
1020 /*
1021 * Place initial small packet/header at end of mbuf.
1022 */
1023 if (len < m->m_len) {
1024 if (top == 0 && len + max_linkhdr <= m->m_len)
1025 m->m_data += max_linkhdr;
1026 m->m_len = len;
1027 } else
1028 len = m->m_len;
1029 }
1030 if (copy)
1031 copy(cp, mtod(m, caddr_t), (size_t)len);
1032 else
1033 memcpy(mtod(m, caddr_t), cp, (size_t)len);
1034 cp += len;
1035 *mp = m;
1036 mp = &m->m_next;
1037 totlen -= len;
1038 if (cp == epkt)
1039 cp = buf;
1040 }
1041 return (top);
1042 }
1043
1044 /*
1045 * Copy data from a buffer back into the indicated mbuf chain,
1046 * starting "off" bytes from the beginning, extending the mbuf
1047 * chain if necessary.
1048 */
1049 void
1050 m_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
1051 {
1052 int mlen;
1053 struct mbuf *m = m0, *n;
1054 int totlen = 0;
1055
1056 if (m0 == 0)
1057 return;
1058 while (off > (mlen = m->m_len)) {
1059 off -= mlen;
1060 totlen += mlen;
1061 if (m->m_next == 0) {
1062 n = m_getclr(M_DONTWAIT, m->m_type);
1063 if (n == 0)
1064 goto out;
1065 n->m_len = min(MLEN, len + off);
1066 m->m_next = n;
1067 }
1068 m = m->m_next;
1069 }
1070 while (len > 0) {
1071 mlen = min (m->m_len - off, len);
1072 memcpy(mtod(m, caddr_t) + off, cp, (unsigned)mlen);
1073 cp += mlen;
1074 len -= mlen;
1075 mlen += off;
1076 off = 0;
1077 totlen += mlen;
1078 if (len == 0)
1079 break;
1080 if (m->m_next == 0) {
1081 n = m_get(M_DONTWAIT, m->m_type);
1082 if (n == 0)
1083 break;
1084 n->m_len = min(MLEN, len);
1085 m->m_next = n;
1086 }
1087 m = m->m_next;
1088 }
1089 out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1090 m->m_pkthdr.len = totlen;
1091 }
1092
1093 /*
1094 * Apply function f to the data in an mbuf chain starting "off" bytes from the
1095 * beginning, continuing for "len" bytes.
1096 */
1097 int
1098 m_apply(struct mbuf *m, int off, int len,
1099 int (*f)(void *, caddr_t, unsigned int), void *arg)
1100 {
1101 unsigned int count;
1102 int rval;
1103
1104 KASSERT(len >= 0);
1105 KASSERT(off >= 0);
1106
1107 while (off > 0) {
1108 KASSERT(m != NULL);
1109 if (off < m->m_len)
1110 break;
1111 off -= m->m_len;
1112 m = m->m_next;
1113 }
1114 while (len > 0) {
1115 KASSERT(m != NULL);
1116 count = min(m->m_len - off, len);
1117
1118 rval = (*f)(arg, mtod(m, caddr_t) + off, count);
1119 if (rval)
1120 return (rval);
1121
1122 len -= count;
1123 off = 0;
1124 m = m->m_next;
1125 }
1126
1127 return (0);
1128 }
1129
1130 /*
1131 * Return a pointer to mbuf/offset of location in mbuf chain.
1132 */
1133 struct mbuf *
1134 m_getptr(struct mbuf *m, int loc, int *off)
1135 {
1136
1137 while (loc >= 0) {
1138 /* Normal end of search */
1139 if (m->m_len > loc) {
1140 *off = loc;
1141 return (m);
1142 } else {
1143 loc -= m->m_len;
1144
1145 if (m->m_next == NULL) {
1146 if (loc == 0) {
1147 /* Point at the end of valid data */
1148 *off = m->m_len;
1149 return (m);
1150 } else
1151 return (NULL);
1152 } else
1153 m = m->m_next;
1154 }
1155 }
1156
1157 return (NULL);
1158 }
1159