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