uipc_mbuf.c revision 22671
1/* 2 * Copyright (c) 1982, 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 34 * $FreeBSD: head/sys/kern/uipc_mbuf.c 22671 1997-02-13 19:41:40Z wollman $ 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/proc.h> 40#include <sys/malloc.h> 41#define MBTYPES 42#include <sys/mbuf.h> 43#include <sys/kernel.h> 44#include <sys/syslog.h> 45#include <sys/domain.h> 46#include <sys/protosw.h> 47 48#include <vm/vm.h> 49#include <vm/vm_param.h> 50#include <vm/vm_kern.h> 51#include <vm/vm_extern.h> 52 53static void mbinit __P((void *)); 54SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL) 55 56struct mbuf *mbutl; 57char *mclrefcnt; 58struct mbstat mbstat; 59struct mbuf *mmbfree; 60union mcluster *mclfree; 61int max_linkhdr; 62int max_protohdr; 63int max_hdr; 64int max_datalen; 65 66static void m_reclaim __P((void)); 67 68/* "number of clusters of pages" */ 69#define NCL_INIT 1 70 71#define NMB_INIT 16 72 73/* ARGSUSED*/ 74static void 75mbinit(dummy) 76 void *dummy; 77{ 78 int s; 79 80 mmbfree = NULL; mclfree = NULL; 81 s = splimp(); 82 if (m_mballoc(NMB_INIT, M_DONTWAIT) == 0) 83 goto bad; 84#if MCLBYTES <= PAGE_SIZE 85 if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) 86 goto bad; 87#else 88 /* It's OK to call contigmalloc in this context. */ 89 if (m_clalloc(16, 0) == 0) 90 goto bad; 91#endif 92 splx(s); 93 return; 94bad: 95 panic("mbinit"); 96} 97 98/* 99 * Allocate at least nmb mbufs and place on mbuf free list. 100 * Must be called at splimp. 101 */ 102/* ARGSUSED */ 103int 104m_mballoc(nmb, nowait) 105 register int nmb; 106 int nowait; 107{ 108 register caddr_t p; 109 register int i; 110 int nbytes; 111 112 /* Once we run out of map space, it will be impossible to get 113 * any more (nothing is ever freed back to the map) (XXX which 114 * is dumb). (however you are not dead as m_reclaim might 115 * still be able to free a substantial amount of space). 116 */ 117 if (mb_map_full) 118 return (0); 119 120 nbytes = round_page(nmb * MSIZE); 121 p = (caddr_t)kmem_malloc(mb_map, nbytes, nowait ? M_NOWAIT : M_WAITOK); 122 /* 123 * Either the map is now full, or this is nowait and there 124 * are no pages left. 125 */ 126 if (p == NULL) 127 return (0); 128 129 nmb = nbytes / MSIZE; 130 for (i = 0; i < nmb; i++) { 131 ((struct mbuf *)p)->m_next = mmbfree; 132 mmbfree = (struct mbuf *)p; 133 p += MSIZE; 134 } 135 mbstat.m_mbufs += nmb; 136 return (1); 137} 138 139#if MCLBYTES > PAGE_SIZE 140int i_want_my_mcl; 141 142void 143kproc_mclalloc(void) 144{ 145 int status; 146 147 while (1) { 148 tsleep(&i_want_my_mcl, PVM, "mclalloc", 0); 149 150 for (; i_want_my_mcl; i_want_my_mcl--) { 151 if (m_clalloc(1, 0) == 0) 152 printf("m_clalloc failed even in process context!\n"); 153 } 154 } 155} 156 157static struct proc *mclallocproc; 158static struct kproc_desc mclalloc_kp = { 159 "mclalloc", 160 kproc_mclalloc, 161 &mclallocproc 162}; 163SYSINIT_KT(mclallocproc, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY, kproc_start, 164 &mclalloc_kp); 165#endif 166 167/* 168 * Allocate some number of mbuf clusters 169 * and place on cluster free list. 170 * Must be called at splimp. 171 */ 172/* ARGSUSED */ 173int 174m_clalloc(ncl, nowait) 175 register int ncl; 176 int nowait; 177{ 178 register caddr_t p; 179 register int i; 180 int npg; 181 182 /* 183 * Once we run out of map space, it will be impossible 184 * to get any more (nothing is ever freed back to the 185 * map). 186 */ 187 if (mb_map_full) 188 return (0); 189 190#if MCLBYTES > PAGE_SIZE 191 if (nowait) { 192 i_want_my_mcl += ncl; 193 wakeup(&i_want_my_mcl); 194 p = 0; 195 } else { 196 p = contigmalloc1(MCLBYTES * ncl, M_DEVBUF, M_WAITOK, 0ul, 197 ~0ul, PAGE_SIZE, 0, mb_map); 198 } 199#else 200 npg = ncl; 201 p = (caddr_t)kmem_malloc(mb_map, ctob(npg), 202 nowait ? M_NOWAIT : M_WAITOK); 203 ncl = ncl * PAGE_SIZE / MCLBYTES; 204#endif 205 /* 206 * Either the map is now full, or this is nowait and there 207 * are no pages left. 208 */ 209 if (p == NULL) 210 return (0); 211 212 for (i = 0; i < ncl; i++) { 213 ((union mcluster *)p)->mcl_next = mclfree; 214 mclfree = (union mcluster *)p; 215 p += MCLBYTES; 216 mbstat.m_clfree++; 217 } 218 mbstat.m_clusters += ncl; 219 return (1); 220} 221 222/* 223 * When MGET failes, ask protocols to free space when short of memory, 224 * then re-attempt to allocate an mbuf. 225 */ 226struct mbuf * 227m_retry(i, t) 228 int i, t; 229{ 230 register struct mbuf *m; 231 232 m_reclaim(); 233#define m_retry(i, t) (struct mbuf *)0 234 MGET(m, i, t); 235#undef m_retry 236 if (m != NULL) 237 mbstat.m_wait++; 238 else 239 mbstat.m_drops++; 240 return (m); 241} 242 243/* 244 * As above; retry an MGETHDR. 245 */ 246struct mbuf * 247m_retryhdr(i, t) 248 int i, t; 249{ 250 register struct mbuf *m; 251 252 m_reclaim(); 253#define m_retryhdr(i, t) (struct mbuf *)0 254 MGETHDR(m, i, t); 255#undef m_retryhdr 256 if (m != NULL) 257 mbstat.m_wait++; 258 else 259 mbstat.m_drops++; 260 return (m); 261} 262 263static void 264m_reclaim() 265{ 266 register struct domain *dp; 267 register struct protosw *pr; 268 int s = splimp(); 269 270 for (dp = domains; dp; dp = dp->dom_next) 271 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 272 if (pr->pr_drain) 273 (*pr->pr_drain)(); 274 splx(s); 275 mbstat.m_drain++; 276} 277 278/* 279 * Space allocation routines. 280 * These are also available as macros 281 * for critical paths. 282 */ 283struct mbuf * 284m_get(nowait, type) 285 int nowait, type; 286{ 287 register struct mbuf *m; 288 289 MGET(m, nowait, type); 290 return (m); 291} 292 293struct mbuf * 294m_gethdr(nowait, type) 295 int nowait, type; 296{ 297 register struct mbuf *m; 298 299 MGETHDR(m, nowait, type); 300 return (m); 301} 302 303struct mbuf * 304m_getclr(nowait, type) 305 int nowait, type; 306{ 307 register struct mbuf *m; 308 309 MGET(m, nowait, type); 310 if (m == 0) 311 return (0); 312 bzero(mtod(m, caddr_t), MLEN); 313 return (m); 314} 315 316struct mbuf * 317m_free(m) 318 struct mbuf *m; 319{ 320 register struct mbuf *n; 321 322 MFREE(m, n); 323 return (n); 324} 325 326void 327m_freem(m) 328 register struct mbuf *m; 329{ 330 register struct mbuf *n; 331 332 if (m == NULL) 333 return; 334 do { 335 MFREE(m, n); 336 m = n; 337 } while (m); 338} 339 340/* 341 * Mbuffer utility routines. 342 */ 343 344/* 345 * Lesser-used path for M_PREPEND: 346 * allocate new mbuf to prepend to chain, 347 * copy junk along. 348 */ 349struct mbuf * 350m_prepend(m, len, how) 351 register struct mbuf *m; 352 int len, how; 353{ 354 struct mbuf *mn; 355 356 MGET(mn, how, m->m_type); 357 if (mn == (struct mbuf *)NULL) { 358 m_freem(m); 359 return ((struct mbuf *)NULL); 360 } 361 if (m->m_flags & M_PKTHDR) { 362 M_COPY_PKTHDR(mn, m); 363 m->m_flags &= ~M_PKTHDR; 364 } 365 mn->m_next = m; 366 m = mn; 367 if (len < MHLEN) 368 MH_ALIGN(m, len); 369 m->m_len = len; 370 return (m); 371} 372 373/* 374 * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 375 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 376 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 377 */ 378static int MCFail; 379 380struct mbuf * 381m_copym(m, off0, len, wait) 382 register struct mbuf *m; 383 int off0, wait; 384 register int len; 385{ 386 register struct mbuf *n, **np; 387 register int off = off0; 388 struct mbuf *top; 389 int copyhdr = 0; 390 391 if (off < 0 || len < 0) 392 panic("m_copym"); 393 if (off == 0 && m->m_flags & M_PKTHDR) 394 copyhdr = 1; 395 while (off > 0) { 396 if (m == 0) 397 panic("m_copym"); 398 if (off < m->m_len) 399 break; 400 off -= m->m_len; 401 m = m->m_next; 402 } 403 np = ⊤ 404 top = 0; 405 while (len > 0) { 406 if (m == 0) { 407 if (len != M_COPYALL) 408 panic("m_copym"); 409 break; 410 } 411 MGET(n, wait, m->m_type); 412 *np = n; 413 if (n == 0) 414 goto nospace; 415 if (copyhdr) { 416 M_COPY_PKTHDR(n, m); 417 if (len == M_COPYALL) 418 n->m_pkthdr.len -= off0; 419 else 420 n->m_pkthdr.len = len; 421 copyhdr = 0; 422 } 423 n->m_len = min(len, m->m_len - off); 424 if (m->m_flags & M_EXT) { 425 n->m_data = m->m_data + off; 426 if(!m->m_ext.ext_ref) 427 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 428 else 429 (*(m->m_ext.ext_ref))(m->m_ext.ext_buf, 430 m->m_ext.ext_size); 431 n->m_ext = m->m_ext; 432 n->m_flags |= M_EXT; 433 } else 434 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 435 (unsigned)n->m_len); 436 if (len != M_COPYALL) 437 len -= n->m_len; 438 off = 0; 439 m = m->m_next; 440 np = &n->m_next; 441 } 442 if (top == 0) 443 MCFail++; 444 return (top); 445nospace: 446 m_freem(top); 447 MCFail++; 448 return (0); 449} 450 451/* 452 * Copy an entire packet, including header (which must be present). 453 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'. 454 */ 455struct mbuf * 456m_copypacket(m, how) 457 struct mbuf *m; 458 int how; 459{ 460 struct mbuf *top, *n, *o; 461 462 MGET(n, how, m->m_type); 463 top = n; 464 if (!n) 465 goto nospace; 466 467 M_COPY_PKTHDR(n, m); 468 n->m_len = m->m_len; 469 if (m->m_flags & M_EXT) { 470 n->m_data = m->m_data; 471 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 472 n->m_ext = m->m_ext; 473 n->m_flags |= M_EXT; 474 } else { 475 bcopy(mtod(m, char *), mtod(n, char *), n->m_len); 476 } 477 478 m = m->m_next; 479 while (m) { 480 MGET(o, how, m->m_type); 481 if (!o) 482 goto nospace; 483 484 n->m_next = o; 485 n = n->m_next; 486 487 n->m_len = m->m_len; 488 if (m->m_flags & M_EXT) { 489 n->m_data = m->m_data; 490 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 491 n->m_ext = m->m_ext; 492 n->m_flags |= M_EXT; 493 } else { 494 bcopy(mtod(m, char *), mtod(n, char *), n->m_len); 495 } 496 497 m = m->m_next; 498 } 499 return top; 500nospace: 501 m_freem(top); 502 MCFail++; 503 return 0; 504} 505 506/* 507 * Copy data from an mbuf chain starting "off" bytes from the beginning, 508 * continuing for "len" bytes, into the indicated buffer. 509 */ 510void 511m_copydata(m, off, len, cp) 512 register struct mbuf *m; 513 register int off; 514 register int len; 515 caddr_t cp; 516{ 517 register unsigned count; 518 519 if (off < 0 || len < 0) 520 panic("m_copydata"); 521 while (off > 0) { 522 if (m == 0) 523 panic("m_copydata"); 524 if (off < m->m_len) 525 break; 526 off -= m->m_len; 527 m = m->m_next; 528 } 529 while (len > 0) { 530 if (m == 0) 531 panic("m_copydata"); 532 count = min(m->m_len - off, len); 533 bcopy(mtod(m, caddr_t) + off, cp, count); 534 len -= count; 535 cp += count; 536 off = 0; 537 m = m->m_next; 538 } 539} 540 541/* 542 * Concatenate mbuf chain n to m. 543 * Both chains must be of the same type (e.g. MT_DATA). 544 * Any m_pkthdr is not updated. 545 */ 546void 547m_cat(m, n) 548 register struct mbuf *m, *n; 549{ 550 while (m->m_next) 551 m = m->m_next; 552 while (n) { 553 if (m->m_flags & M_EXT || 554 m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 555 /* just join the two chains */ 556 m->m_next = n; 557 return; 558 } 559 /* splat the data from one into the other */ 560 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 561 (u_int)n->m_len); 562 m->m_len += n->m_len; 563 n = m_free(n); 564 } 565} 566 567void 568m_adj(mp, req_len) 569 struct mbuf *mp; 570 int req_len; 571{ 572 register int len = req_len; 573 register struct mbuf *m; 574 register count; 575 576 if ((m = mp) == NULL) 577 return; 578 if (len >= 0) { 579 /* 580 * Trim from head. 581 */ 582 while (m != NULL && len > 0) { 583 if (m->m_len <= len) { 584 len -= m->m_len; 585 m->m_len = 0; 586 m = m->m_next; 587 } else { 588 m->m_len -= len; 589 m->m_data += len; 590 len = 0; 591 } 592 } 593 m = mp; 594 if (mp->m_flags & M_PKTHDR) 595 m->m_pkthdr.len -= (req_len - len); 596 } else { 597 /* 598 * Trim from tail. Scan the mbuf chain, 599 * calculating its length and finding the last mbuf. 600 * If the adjustment only affects this mbuf, then just 601 * adjust and return. Otherwise, rescan and truncate 602 * after the remaining size. 603 */ 604 len = -len; 605 count = 0; 606 for (;;) { 607 count += m->m_len; 608 if (m->m_next == (struct mbuf *)0) 609 break; 610 m = m->m_next; 611 } 612 if (m->m_len >= len) { 613 m->m_len -= len; 614 if (mp->m_flags & M_PKTHDR) 615 mp->m_pkthdr.len -= len; 616 return; 617 } 618 count -= len; 619 if (count < 0) 620 count = 0; 621 /* 622 * Correct length for chain is "count". 623 * Find the mbuf with last data, adjust its length, 624 * and toss data from remaining mbufs on chain. 625 */ 626 m = mp; 627 if (m->m_flags & M_PKTHDR) 628 m->m_pkthdr.len = count; 629 for (; m; m = m->m_next) { 630 if (m->m_len >= count) { 631 m->m_len = count; 632 break; 633 } 634 count -= m->m_len; 635 } 636 while (m->m_next) 637 (m = m->m_next) ->m_len = 0; 638 } 639} 640 641/* 642 * Rearange an mbuf chain so that len bytes are contiguous 643 * and in the data area of an mbuf (so that mtod and dtom 644 * will work for a structure of size len). Returns the resulting 645 * mbuf chain on success, frees it and returns null on failure. 646 * If there is room, it will add up to max_protohdr-len extra bytes to the 647 * contiguous region in an attempt to avoid being called next time. 648 */ 649static int MPFail; 650 651struct mbuf * 652m_pullup(n, len) 653 register struct mbuf *n; 654 int len; 655{ 656 register struct mbuf *m; 657 register int count; 658 int space; 659 660 /* 661 * If first mbuf has no cluster, and has room for len bytes 662 * without shifting current data, pullup into it, 663 * otherwise allocate a new mbuf to prepend to the chain. 664 */ 665 if ((n->m_flags & M_EXT) == 0 && 666 n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 667 if (n->m_len >= len) 668 return (n); 669 m = n; 670 n = n->m_next; 671 len -= m->m_len; 672 } else { 673 if (len > MHLEN) 674 goto bad; 675 MGET(m, M_DONTWAIT, n->m_type); 676 if (m == 0) 677 goto bad; 678 m->m_len = 0; 679 if (n->m_flags & M_PKTHDR) { 680 M_COPY_PKTHDR(m, n); 681 n->m_flags &= ~M_PKTHDR; 682 } 683 } 684 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 685 do { 686 count = min(min(max(len, max_protohdr), space), n->m_len); 687 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 688 (unsigned)count); 689 len -= count; 690 m->m_len += count; 691 n->m_len -= count; 692 space -= count; 693 if (n->m_len) 694 n->m_data += count; 695 else 696 n = m_free(n); 697 } while (len > 0 && n); 698 if (len > 0) { 699 (void) m_free(m); 700 goto bad; 701 } 702 m->m_next = n; 703 return (m); 704bad: 705 m_freem(n); 706 MPFail++; 707 return (0); 708} 709 710/* 711 * Partition an mbuf chain in two pieces, returning the tail -- 712 * all but the first len0 bytes. In case of failure, it returns NULL and 713 * attempts to restore the chain to its original state. 714 */ 715struct mbuf * 716m_split(m0, len0, wait) 717 register struct mbuf *m0; 718 int len0, wait; 719{ 720 register struct mbuf *m, *n; 721 unsigned len = len0, remain; 722 723 for (m = m0; m && len > m->m_len; m = m->m_next) 724 len -= m->m_len; 725 if (m == 0) 726 return (0); 727 remain = m->m_len - len; 728 if (m0->m_flags & M_PKTHDR) { 729 MGETHDR(n, wait, m0->m_type); 730 if (n == 0) 731 return (0); 732 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 733 n->m_pkthdr.len = m0->m_pkthdr.len - len0; 734 m0->m_pkthdr.len = len0; 735 if (m->m_flags & M_EXT) 736 goto extpacket; 737 if (remain > MHLEN) { 738 /* m can't be the lead packet */ 739 MH_ALIGN(n, 0); 740 n->m_next = m_split(m, len, wait); 741 if (n->m_next == 0) { 742 (void) m_free(n); 743 return (0); 744 } else 745 return (n); 746 } else 747 MH_ALIGN(n, remain); 748 } else if (remain == 0) { 749 n = m->m_next; 750 m->m_next = 0; 751 return (n); 752 } else { 753 MGET(n, wait, m->m_type); 754 if (n == 0) 755 return (0); 756 M_ALIGN(n, remain); 757 } 758extpacket: 759 if (m->m_flags & M_EXT) { 760 n->m_flags |= M_EXT; 761 n->m_ext = m->m_ext; 762 if(!m->m_ext.ext_ref) 763 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 764 else 765 (*(m->m_ext.ext_ref))(m->m_ext.ext_buf, 766 m->m_ext.ext_size); 767 m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ 768 n->m_data = m->m_data + len; 769 } else { 770 bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); 771 } 772 n->m_len = remain; 773 m->m_len = len; 774 n->m_next = m->m_next; 775 m->m_next = 0; 776 return (n); 777} 778/* 779 * Routine to copy from device local memory into mbufs. 780 */ 781struct mbuf * 782m_devget(buf, totlen, off0, ifp, copy) 783 char *buf; 784 int totlen, off0; 785 struct ifnet *ifp; 786 void (*copy) __P((char *from, caddr_t to, u_int len)); 787{ 788 register struct mbuf *m; 789 struct mbuf *top = 0, **mp = ⊤ 790 register int off = off0, len; 791 register char *cp; 792 char *epkt; 793 794 cp = buf; 795 epkt = cp + totlen; 796 if (off) { 797 cp += off + 2 * sizeof(u_short); 798 totlen -= 2 * sizeof(u_short); 799 } 800 MGETHDR(m, M_DONTWAIT, MT_DATA); 801 if (m == 0) 802 return (0); 803 m->m_pkthdr.rcvif = ifp; 804 m->m_pkthdr.len = totlen; 805 m->m_len = MHLEN; 806 807 while (totlen > 0) { 808 if (top) { 809 MGET(m, M_DONTWAIT, MT_DATA); 810 if (m == 0) { 811 m_freem(top); 812 return (0); 813 } 814 m->m_len = MLEN; 815 } 816 len = min(totlen, epkt - cp); 817 if (len >= MINCLSIZE) { 818 MCLGET(m, M_DONTWAIT); 819 if (m->m_flags & M_EXT) 820 m->m_len = len = min(len, MCLBYTES); 821 else 822 len = m->m_len; 823 } else { 824 /* 825 * Place initial small packet/header at end of mbuf. 826 */ 827 if (len < m->m_len) { 828 if (top == 0 && len + max_linkhdr <= m->m_len) 829 m->m_data += max_linkhdr; 830 m->m_len = len; 831 } else 832 len = m->m_len; 833 } 834 if (copy) 835 copy(cp, mtod(m, caddr_t), (unsigned)len); 836 else 837 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 838 cp += len; 839 *mp = m; 840 mp = &m->m_next; 841 totlen -= len; 842 if (cp == epkt) 843 cp = buf; 844 } 845 return (top); 846} 847 848/* 849 * Copy data from a buffer back into the indicated mbuf chain, 850 * starting "off" bytes from the beginning, extending the mbuf 851 * chain if necessary. 852 */ 853void 854m_copyback(m0, off, len, cp) 855 struct mbuf *m0; 856 register int off; 857 register int len; 858 caddr_t cp; 859{ 860 register int mlen; 861 register struct mbuf *m = m0, *n; 862 int totlen = 0; 863 864 if (m0 == 0) 865 return; 866 while (off > (mlen = m->m_len)) { 867 off -= mlen; 868 totlen += mlen; 869 if (m->m_next == 0) { 870 n = m_getclr(M_DONTWAIT, m->m_type); 871 if (n == 0) 872 goto out; 873 n->m_len = min(MLEN, len + off); 874 m->m_next = n; 875 } 876 m = m->m_next; 877 } 878 while (len > 0) { 879 mlen = min (m->m_len - off, len); 880 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 881 cp += mlen; 882 len -= mlen; 883 mlen += off; 884 off = 0; 885 totlen += mlen; 886 if (len == 0) 887 break; 888 if (m->m_next == 0) { 889 n = m_get(M_DONTWAIT, m->m_type); 890 if (n == 0) 891 break; 892 n->m_len = min(MLEN, len); 893 m->m_next = n; 894 } 895 m = m->m_next; 896 } 897out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 898 m->m_pkthdr.len = totlen; 899} 900