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