1 /* $NetBSD: uipc_mbuf.c,v 1.61 2002/09/25 22:21:45 thorpej 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.61 2002/09/25 22:21:45 thorpej 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_extern.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 void *mclpool_alloc __P((struct pool *, int)); 110 void mclpool_release __P((struct pool *, void *)); 111 112 struct pool_allocator mclpool_allocator = { 113 mclpool_alloc, mclpool_release, 0, 114 }; 115 116 static struct mbuf *m_copym0 __P((struct mbuf *, int, int, int, int)); 117 118 const char mclpool_warnmsg[] = 119 "WARNING: mclpool limit reached; increase NMBCLUSTERS"; 120 121 /* 122 * Initialize the mbuf allcator. 123 */ 124 void 125 mbinit() 126 { 127 128 pool_init(&mbpool, msize, 0, 0, 0, "mbpl", NULL); 129 pool_init(&mclpool, mclbytes, 0, 0, 0, "mclpl", &mclpool_allocator); 130 131 pool_set_drain_hook(&mbpool, m_reclaim, NULL); 132 pool_set_drain_hook(&mclpool, m_reclaim, NULL); 133 134 pool_cache_init(&mbpool_cache, &mbpool, NULL, NULL, NULL); 135 pool_cache_init(&mclpool_cache, &mclpool, NULL, NULL, NULL); 136 137 /* 138 * Set the hard limit on the mclpool to the number of 139 * mbuf clusters the kernel is to support. Log the limit 140 * reached message max once a minute. 141 */ 142 pool_sethardlimit(&mclpool, nmbclusters, mclpool_warnmsg, 60); 143 144 /* 145 * Set a low water mark for both mbufs and clusters. This should 146 * help ensure that they can be allocated in a memory starvation 147 * situation. This is important for e.g. diskless systems which 148 * must allocate mbufs in order for the pagedaemon to clean pages. 149 */ 150 pool_setlowat(&mbpool, mblowat); 151 pool_setlowat(&mclpool, mcllowat); 152 } 153 154 int 155 sysctl_dombuf(name, namelen, oldp, oldlenp, newp, newlen) 156 int *name; 157 u_int namelen; 158 void *oldp; 159 size_t *oldlenp; 160 void *newp; 161 size_t newlen; 162 { 163 int error, newval; 164 165 /* All sysctl names at this level are terminal. */ 166 if (namelen != 1) 167 return (ENOTDIR); /* overloaded */ 168 169 switch (name[0]) { 170 case MBUF_MSIZE: 171 return (sysctl_rdint(oldp, oldlenp, newp, msize)); 172 case MBUF_MCLBYTES: 173 return (sysctl_rdint(oldp, oldlenp, newp, mclbytes)); 174 case MBUF_NMBCLUSTERS: 175 /* 176 * If we have direct-mapped pool pages, we can adjust this 177 * number on the fly. If not, we're limited by the size 178 * of mb_map, and cannot change this value. 179 * 180 * Note: we only allow the value to be increased, never 181 * decreased. 182 */ 183 if (mb_map == NULL) { 184 newval = nmbclusters; 185 error = sysctl_int(oldp, oldlenp, newp, newlen, 186 &newval); 187 if (error != 0) 188 return (error); 189 if (newp != NULL) { 190 if (newval >= nmbclusters) { 191 nmbclusters = newval; 192 pool_sethardlimit(&mclpool, 193 nmbclusters, mclpool_warnmsg, 60); 194 } else 195 error = EINVAL; 196 } 197 return (error); 198 } else 199 return (sysctl_rdint(oldp, oldlenp, newp, nmbclusters)); 200 case MBUF_MBLOWAT: 201 case MBUF_MCLLOWAT: 202 /* New value must be >= 0. */ 203 newval = (name[0] == MBUF_MBLOWAT) ? mblowat : mcllowat; 204 error = sysctl_int(oldp, oldlenp, newp, newlen, &newval); 205 if (error != 0) 206 return (error); 207 if (newp != NULL) { 208 if (newval >= 0) { 209 if (name[0] == MBUF_MBLOWAT) { 210 mblowat = newval; 211 pool_setlowat(&mbpool, newval); 212 } else { 213 mcllowat = newval; 214 pool_setlowat(&mclpool, newval); 215 } 216 } else 217 error = EINVAL; 218 } 219 return (error); 220 default: 221 return (EOPNOTSUPP); 222 } 223 /* NOTREACHED */ 224 } 225 226 void * 227 mclpool_alloc(pp, flags) 228 struct pool *pp; 229 int flags; 230 { 231 boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE; 232 233 return ((void *)uvm_km_alloc_poolpage1(mb_map, NULL, waitok)); 234 } 235 236 void 237 mclpool_release(pp, v) 238 struct pool *pp; 239 void *v; 240 { 241 242 uvm_km_free_poolpage1(mb_map, (vaddr_t)v); 243 } 244 245 void 246 m_reclaim(void *arg, int flags) 247 { 248 struct domain *dp; 249 struct protosw *pr; 250 struct ifnet *ifp; 251 int s = splvm(); 252 253 for (dp = domains; dp; dp = dp->dom_next) 254 for (pr = dp->dom_protosw; 255 pr < dp->dom_protoswNPROTOSW; pr++) 256 if (pr->pr_drain) 257 (*pr->pr_drain)(); 258 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) 259 if (ifp->if_drain) 260 (*ifp->if_drain)(ifp); 261 splx(s); 262 mbstat.m_drain++; 263 } 264 265 /* 266 * Space allocation routines. 267 * These are also available as macros 268 * for critical paths. 269 */ 270 struct mbuf * 271 m_get(nowait, type) 272 int nowait, type; 273 { 274 struct mbuf *m; 275 276 MGET(m, nowait, type); 277 return (m); 278 } 279 280 struct mbuf * 281 m_gethdr(nowait, type) 282 int nowait, type; 283 { 284 struct mbuf *m; 285 286 MGETHDR(m, nowait, type); 287 return (m); 288 } 289 290 struct mbuf * 291 m_getclr(nowait, type) 292 int nowait, type; 293 { 294 struct mbuf *m; 295 296 MGET(m, nowait, type); 297 if (m == 0) 298 return (0); 299 memset(mtod(m, caddr_t), 0, MLEN); 300 return (m); 301 } 302 303 struct mbuf * 304 m_free(m) 305 struct mbuf *m; 306 { 307 struct mbuf *n; 308 309 MFREE(m, n); 310 return (n); 311 } 312 313 void 314 m_freem(m) 315 struct mbuf *m; 316 { 317 struct mbuf *n; 318 319 if (m == NULL) 320 return; 321 do { 322 MFREE(m, n); 323 m = n; 324 } while (m); 325 } 326 327 /* 328 * Mbuffer utility routines. 329 */ 330 331 /* 332 * Lesser-used path for M_PREPEND: 333 * allocate new mbuf to prepend to chain, 334 * copy junk along. 335 */ 336 struct mbuf * 337 m_prepend(m, len, how) 338 struct mbuf *m; 339 int len, how; 340 { 341 struct mbuf *mn; 342 343 MGET(mn, how, m->m_type); 344 if (mn == (struct mbuf *)NULL) { 345 m_freem(m); 346 return ((struct mbuf *)NULL); 347 } 348 if (m->m_flags & M_PKTHDR) { 349 M_COPY_PKTHDR(mn, m); 350 m->m_flags &= ~M_PKTHDR; 351 } 352 mn->m_next = m; 353 m = mn; 354 if (len < MHLEN) 355 MH_ALIGN(m, len); 356 m->m_len = len; 357 return (m); 358 } 359 360 /* 361 * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 362 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 363 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 364 */ 365 int MCFail; 366 367 struct mbuf * 368 m_copym(m, off0, len, wait) 369 struct mbuf *m; 370 int off0, wait; 371 int len; 372 { 373 return m_copym0(m, off0, len, wait, 0); /* shallow copy on M_EXT */ 374 } 375 376 struct mbuf * 377 m_dup(m, off0, len, wait) 378 struct mbuf *m; 379 int off0, wait; 380 int len; 381 { 382 return m_copym0(m, off0, len, wait, 1); /* deep copy */ 383 } 384 385 static struct mbuf * 386 m_copym0(m, off0, len, wait, deep) 387 struct mbuf *m; 388 int off0, wait; 389 int len; 390 int deep; /* deep copy */ 391 { 392 struct mbuf *n, **np; 393 int off = off0; 394 struct mbuf *top; 395 int copyhdr = 0; 396 397 if (off < 0 || len < 0) 398 panic("m_copym: off %d, len %d", off, len); 399 if (off == 0 && m->m_flags & M_PKTHDR) 400 copyhdr = 1; 401 while (off > 0) { 402 if (m == 0) 403 panic("m_copym: m == 0"); 404 if (off < m->m_len) 405 break; 406 off -= m->m_len; 407 m = m->m_next; 408 } 409 np = ⊤ 410 top = 0; 411 while (len > 0) { 412 if (m == 0) { 413 if (len != M_COPYALL) 414 panic("m_copym: m == 0 and not COPYALL"); 415 break; 416 } 417 MGET(n, wait, m->m_type); 418 *np = n; 419 if (n == 0) 420 goto nospace; 421 if (copyhdr) { 422 M_COPY_PKTHDR(n, m); 423 if (len == M_COPYALL) 424 n->m_pkthdr.len -= off0; 425 else 426 n->m_pkthdr.len = len; 427 copyhdr = 0; 428 } 429 n->m_len = min(len, m->m_len - off); 430 if (m->m_flags & M_EXT) { 431 if (!deep) { 432 n->m_data = m->m_data + off; 433 n->m_ext = m->m_ext; 434 MCLADDREFERENCE(m, n); 435 } else { 436 /* 437 * we are unsure about the way m was allocated. 438 * copy into multiple MCLBYTES cluster mbufs. 439 */ 440 MCLGET(n, wait); 441 n->m_len = 0; 442 n->m_len = M_TRAILINGSPACE(n); 443 n->m_len = min(n->m_len, len); 444 n->m_len = min(n->m_len, m->m_len - off); 445 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, 446 (unsigned)n->m_len); 447 } 448 } else 449 memcpy(mtod(n, caddr_t), mtod(m, caddr_t)+off, 450 (unsigned)n->m_len); 451 if (len != M_COPYALL) 452 len -= n->m_len; 453 off += n->m_len; 454 #ifdef DIAGNOSTIC 455 if (off > m->m_len) 456 panic("m_copym0 overrun"); 457 #endif 458 if (off == m->m_len) { 459 m = m->m_next; 460 off = 0; 461 } 462 np = &n->m_next; 463 } 464 if (top == 0) 465 MCFail++; 466 return (top); 467 nospace: 468 m_freem(top); 469 MCFail++; 470 return (0); 471 } 472 473 /* 474 * Copy an entire packet, including header (which must be present). 475 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'. 476 */ 477 struct mbuf * 478 m_copypacket(m, how) 479 struct mbuf *m; 480 int how; 481 { 482 struct mbuf *top, *n, *o; 483 484 MGET(n, how, m->m_type); 485 top = n; 486 if (!n) 487 goto nospace; 488 489 M_COPY_PKTHDR(n, m); 490 n->m_len = m->m_len; 491 if (m->m_flags & M_EXT) { 492 n->m_data = m->m_data; 493 n->m_ext = m->m_ext; 494 MCLADDREFERENCE(m, n); 495 } else { 496 memcpy(mtod(n, char *), mtod(m, char *), n->m_len); 497 } 498 499 m = m->m_next; 500 while (m) { 501 MGET(o, how, m->m_type); 502 if (!o) 503 goto nospace; 504 505 n->m_next = o; 506 n = n->m_next; 507 508 n->m_len = m->m_len; 509 if (m->m_flags & M_EXT) { 510 n->m_data = m->m_data; 511 n->m_ext = m->m_ext; 512 MCLADDREFERENCE(m, n); 513 } else { 514 memcpy(mtod(n, char *), mtod(m, char *), n->m_len); 515 } 516 517 m = m->m_next; 518 } 519 return top; 520 nospace: 521 m_freem(top); 522 MCFail++; 523 return 0; 524 } 525 526 /* 527 * Copy data from an mbuf chain starting "off" bytes from the beginning, 528 * continuing for "len" bytes, into the indicated buffer. 529 */ 530 void 531 m_copydata(m, off, len, cp) 532 struct mbuf *m; 533 int off; 534 int len; 535 caddr_t cp; 536 { 537 unsigned count; 538 539 if (off < 0 || len < 0) 540 panic("m_copydata"); 541 while (off > 0) { 542 if (m == 0) 543 panic("m_copydata"); 544 if (off < m->m_len) 545 break; 546 off -= m->m_len; 547 m = m->m_next; 548 } 549 while (len > 0) { 550 if (m == 0) 551 panic("m_copydata"); 552 count = min(m->m_len - off, len); 553 memcpy(cp, mtod(m, caddr_t) + off, count); 554 len -= count; 555 cp += count; 556 off = 0; 557 m = m->m_next; 558 } 559 } 560 561 /* 562 * Concatenate mbuf chain n to m. 563 * Both chains must be of the same type (e.g. MT_DATA). 564 * Any m_pkthdr is not updated. 565 */ 566 void 567 m_cat(m, n) 568 struct mbuf *m, *n; 569 { 570 while (m->m_next) 571 m = m->m_next; 572 while (n) { 573 if (m->m_flags & M_EXT || 574 m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 575 /* just join the two chains */ 576 m->m_next = n; 577 return; 578 } 579 /* splat the data from one into the other */ 580 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 581 (u_int)n->m_len); 582 m->m_len += n->m_len; 583 n = m_free(n); 584 } 585 } 586 587 void 588 m_adj(mp, req_len) 589 struct mbuf *mp; 590 int req_len; 591 { 592 int len = req_len; 593 struct mbuf *m; 594 int count; 595 596 if ((m = mp) == NULL) 597 return; 598 if (len >= 0) { 599 /* 600 * Trim from head. 601 */ 602 while (m != NULL && len > 0) { 603 if (m->m_len <= len) { 604 len -= m->m_len; 605 m->m_len = 0; 606 m = m->m_next; 607 } else { 608 m->m_len -= len; 609 m->m_data += len; 610 len = 0; 611 } 612 } 613 m = mp; 614 if (mp->m_flags & M_PKTHDR) 615 m->m_pkthdr.len -= (req_len - len); 616 } else { 617 /* 618 * Trim from tail. Scan the mbuf chain, 619 * calculating its length and finding the last mbuf. 620 * If the adjustment only affects this mbuf, then just 621 * adjust and return. Otherwise, rescan and truncate 622 * after the remaining size. 623 */ 624 len = -len; 625 count = 0; 626 for (;;) { 627 count += m->m_len; 628 if (m->m_next == (struct mbuf *)0) 629 break; 630 m = m->m_next; 631 } 632 if (m->m_len >= len) { 633 m->m_len -= len; 634 if (mp->m_flags & M_PKTHDR) 635 mp->m_pkthdr.len -= len; 636 return; 637 } 638 count -= len; 639 if (count < 0) 640 count = 0; 641 /* 642 * Correct length for chain is "count". 643 * Find the mbuf with last data, adjust its length, 644 * and toss data from remaining mbufs on chain. 645 */ 646 m = mp; 647 if (m->m_flags & M_PKTHDR) 648 m->m_pkthdr.len = count; 649 for (; m; m = m->m_next) { 650 if (m->m_len >= count) { 651 m->m_len = count; 652 break; 653 } 654 count -= m->m_len; 655 } 656 while (m->m_next) 657 (m = m->m_next) ->m_len = 0; 658 } 659 } 660 661 /* 662 * Rearange an mbuf chain so that len bytes are contiguous 663 * and in the data area of an mbuf (so that mtod and dtom 664 * will work for a structure of size len). Returns the resulting 665 * mbuf chain on success, frees it and returns null on failure. 666 * If there is room, it will add up to max_protohdr-len extra bytes to the 667 * contiguous region in an attempt to avoid being called next time. 668 */ 669 int MPFail; 670 671 struct mbuf * 672 m_pullup(n, len) 673 struct mbuf *n; 674 int len; 675 { 676 struct mbuf *m; 677 int count; 678 int space; 679 680 /* 681 * If first mbuf has no cluster, and has room for len bytes 682 * without shifting current data, pullup into it, 683 * otherwise allocate a new mbuf to prepend to the chain. 684 */ 685 if ((n->m_flags & M_EXT) == 0 && 686 n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 687 if (n->m_len >= len) 688 return (n); 689 m = n; 690 n = n->m_next; 691 len -= m->m_len; 692 } else { 693 if (len > MHLEN) 694 goto bad; 695 MGET(m, M_DONTWAIT, n->m_type); 696 if (m == 0) 697 goto bad; 698 m->m_len = 0; 699 if (n->m_flags & M_PKTHDR) { 700 M_COPY_PKTHDR(m, n); 701 n->m_flags &= ~M_PKTHDR; 702 } 703 } 704 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 705 do { 706 count = min(min(max(len, max_protohdr), space), n->m_len); 707 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 708 (unsigned)count); 709 len -= count; 710 m->m_len += count; 711 n->m_len -= count; 712 space -= count; 713 if (n->m_len) 714 n->m_data += count; 715 else 716 n = m_free(n); 717 } while (len > 0 && n); 718 if (len > 0) { 719 (void) m_free(m); 720 goto bad; 721 } 722 m->m_next = n; 723 return (m); 724 bad: 725 m_freem(n); 726 MPFail++; 727 return (0); 728 } 729 730 /* 731 * Like m_pullup(), except a new mbuf is always allocated, and we allow 732 * the amount of empty space before the data in the new mbuf to be specified 733 * (in the event that the caller expects to prepend later). 734 */ 735 int MSFail; 736 737 struct mbuf * 738 m_copyup(struct mbuf *n, int len, int dstoff) 739 { 740 struct mbuf *m; 741 int count, space; 742 743 if (len > (MHLEN - dstoff)) 744 goto bad; 745 MGET(m, M_DONTWAIT, n->m_type); 746 if (m == NULL) 747 goto bad; 748 m->m_len = 0; 749 if (n->m_flags & M_PKTHDR) { 750 M_COPY_PKTHDR(m, n); 751 n->m_flags &= ~M_PKTHDR; 752 } 753 m->m_data += dstoff; 754 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 755 do { 756 count = min(min(max(len, max_protohdr), space), n->m_len); 757 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 758 (unsigned)count); 759 len -= count; 760 m->m_len += count; 761 n->m_len -= count; 762 space -= count; 763 if (n->m_len) 764 n->m_data += count; 765 else 766 n = m_free(n); 767 } while (len > 0 && n); 768 if (len > 0) { 769 (void) m_free(m); 770 goto bad; 771 } 772 m->m_next = n; 773 return (m); 774 bad: 775 m_freem(n); 776 MSFail++; 777 return (NULL); 778 } 779 780 /* 781 * Partition an mbuf chain in two pieces, returning the tail -- 782 * all but the first len0 bytes. In case of failure, it returns NULL and 783 * attempts to restore the chain to its original state. 784 */ 785 struct mbuf * 786 m_split(m0, len0, wait) 787 struct mbuf *m0; 788 int len0, wait; 789 { 790 struct mbuf *m, *n; 791 unsigned len = len0, remain, len_save; 792 793 for (m = m0; m && len > m->m_len; m = m->m_next) 794 len -= m->m_len; 795 if (m == 0) 796 return (0); 797 remain = m->m_len - len; 798 if (m0->m_flags & M_PKTHDR) { 799 MGETHDR(n, wait, m0->m_type); 800 if (n == 0) 801 return (0); 802 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 803 n->m_pkthdr.len = m0->m_pkthdr.len - len0; 804 len_save = m0->m_pkthdr.len; 805 m0->m_pkthdr.len = len0; 806 if (m->m_flags & M_EXT) 807 goto extpacket; 808 if (remain > MHLEN) { 809 /* m can't be the lead packet */ 810 MH_ALIGN(n, 0); 811 n->m_next = m_split(m, len, wait); 812 if (n->m_next == 0) { 813 (void) m_free(n); 814 m0->m_pkthdr.len = len_save; 815 return (0); 816 } else 817 return (n); 818 } else 819 MH_ALIGN(n, remain); 820 } else if (remain == 0) { 821 n = m->m_next; 822 m->m_next = 0; 823 return (n); 824 } else { 825 MGET(n, wait, m->m_type); 826 if (n == 0) 827 return (0); 828 M_ALIGN(n, remain); 829 } 830 extpacket: 831 if (m->m_flags & M_EXT) { 832 n->m_ext = m->m_ext; 833 MCLADDREFERENCE(m, n); 834 n->m_data = m->m_data + len; 835 } else { 836 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain); 837 } 838 n->m_len = remain; 839 m->m_len = len; 840 n->m_next = m->m_next; 841 m->m_next = 0; 842 return (n); 843 } 844 /* 845 * Routine to copy from device local memory into mbufs. 846 */ 847 struct mbuf * 848 m_devget(buf, totlen, off0, ifp, copy) 849 char *buf; 850 int totlen, off0; 851 struct ifnet *ifp; 852 void (*copy) __P((const void *from, void *to, size_t len)); 853 { 854 struct mbuf *m; 855 struct mbuf *top = 0, **mp = ⊤ 856 int off = off0, len; 857 char *cp; 858 char *epkt; 859 860 cp = buf; 861 epkt = cp + totlen; 862 if (off) { 863 /* 864 * If 'off' is non-zero, packet is trailer-encapsulated, 865 * so we have to skip the type and length fields. 866 */ 867 cp += off + 2 * sizeof(u_int16_t); 868 totlen -= 2 * sizeof(u_int16_t); 869 } 870 MGETHDR(m, M_DONTWAIT, MT_DATA); 871 if (m == 0) 872 return (0); 873 m->m_pkthdr.rcvif = ifp; 874 m->m_pkthdr.len = totlen; 875 m->m_len = MHLEN; 876 877 while (totlen > 0) { 878 if (top) { 879 MGET(m, M_DONTWAIT, MT_DATA); 880 if (m == 0) { 881 m_freem(top); 882 return (0); 883 } 884 m->m_len = MLEN; 885 } 886 len = min(totlen, epkt - cp); 887 if (len >= MINCLSIZE) { 888 MCLGET(m, M_DONTWAIT); 889 if ((m->m_flags & M_EXT) == 0) { 890 m_free(m); 891 m_freem(top); 892 return (0); 893 } 894 m->m_len = len = min(len, MCLBYTES); 895 } else { 896 /* 897 * Place initial small packet/header at end of mbuf. 898 */ 899 if (len < m->m_len) { 900 if (top == 0 && len + max_linkhdr <= m->m_len) 901 m->m_data += max_linkhdr; 902 m->m_len = len; 903 } else 904 len = m->m_len; 905 } 906 if (copy) 907 copy(cp, mtod(m, caddr_t), (size_t)len); 908 else 909 memcpy(mtod(m, caddr_t), cp, (size_t)len); 910 cp += len; 911 *mp = m; 912 mp = &m->m_next; 913 totlen -= len; 914 if (cp == epkt) 915 cp = buf; 916 } 917 return (top); 918 } 919 920 /* 921 * Copy data from a buffer back into the indicated mbuf chain, 922 * starting "off" bytes from the beginning, extending the mbuf 923 * chain if necessary. 924 */ 925 void 926 m_copyback(m0, off, len, cp) 927 struct mbuf *m0; 928 int off; 929 int len; 930 caddr_t cp; 931 { 932 int mlen; 933 struct mbuf *m = m0, *n; 934 int totlen = 0; 935 936 if (m0 == 0) 937 return; 938 while (off > (mlen = m->m_len)) { 939 off -= mlen; 940 totlen += mlen; 941 if (m->m_next == 0) { 942 n = m_getclr(M_DONTWAIT, m->m_type); 943 if (n == 0) 944 goto out; 945 n->m_len = min(MLEN, len + off); 946 m->m_next = n; 947 } 948 m = m->m_next; 949 } 950 while (len > 0) { 951 mlen = min (m->m_len - off, len); 952 memcpy(mtod(m, caddr_t) + off, cp, (unsigned)mlen); 953 cp += mlen; 954 len -= mlen; 955 mlen += off; 956 off = 0; 957 totlen += mlen; 958 if (len == 0) 959 break; 960 if (m->m_next == 0) { 961 n = m_get(M_DONTWAIT, m->m_type); 962 if (n == 0) 963 break; 964 n->m_len = min(MLEN, len); 965 m->m_next = n; 966 } 967 m = m->m_next; 968 } 969 out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 970 m->m_pkthdr.len = totlen; 971 } 972