1 /* $NetBSD: uipc_mbuf.c,v 1.111 2006/05/25 14:27:28 yamt 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.111 2006/05/25 14:27:28 yamt Exp $"); 73 74 #include "opt_mbuftrace.h" 75 #include "opt_ddb.h" 76 77 #include <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/proc.h> 80 #include <sys/malloc.h> 81 #define MBTYPES 82 #include <sys/mbuf.h> 83 #include <sys/kernel.h> 84 #include <sys/syslog.h> 85 #include <sys/domain.h> 86 #include <sys/protosw.h> 87 #include <sys/pool.h> 88 #include <sys/socket.h> 89 #include <sys/sysctl.h> 90 91 #include <net/if.h> 92 93 #include <uvm/uvm.h> 94 95 96 struct pool mbpool; /* mbuf pool */ 97 struct pool mclpool; /* mbuf cluster pool */ 98 99 struct pool_cache mbpool_cache; 100 struct pool_cache mclpool_cache; 101 102 struct mbstat mbstat; 103 int max_linkhdr; 104 int max_protohdr; 105 int max_hdr; 106 int max_datalen; 107 108 static int mb_ctor(void *, void *, int); 109 110 static void *mclpool_alloc(struct pool *, int); 111 static void mclpool_release(struct pool *, void *); 112 113 static struct pool_allocator mclpool_allocator = { 114 mclpool_alloc, mclpool_release, 0, 115 }; 116 117 static struct mbuf *m_copym0(struct mbuf *, int, int, int, int); 118 static struct mbuf *m_split0(struct mbuf *, int, int, int); 119 static int m_copyback0(struct mbuf **, int, int, const void *, int, int); 120 121 /* flags for m_copyback0 */ 122 #define M_COPYBACK0_COPYBACK 0x0001 /* copyback from cp */ 123 #define M_COPYBACK0_PRESERVE 0x0002 /* preserve original data */ 124 #define M_COPYBACK0_COW 0x0004 /* do copy-on-write */ 125 #define M_COPYBACK0_EXTEND 0x0008 /* extend chain */ 126 127 static const char mclpool_warnmsg[] = 128 "WARNING: mclpool limit reached; increase NMBCLUSTERS"; 129 130 MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf"); 131 132 #ifdef MBUFTRACE 133 struct mownerhead mowners = LIST_HEAD_INITIALIZER(mowners); 134 struct mowner unknown_mowners[] = { 135 { "unknown", "free" }, 136 { "unknown", "data" }, 137 { "unknown", "header" }, 138 { "unknown", "soname" }, 139 { "unknown", "soopts" }, 140 { "unknown", "ftable" }, 141 { "unknown", "control" }, 142 { "unknown", "oobdata" }, 143 }; 144 struct mowner revoked_mowner = { "revoked", "" }; 145 #endif 146 147 /* 148 * Initialize the mbuf allocator. 149 */ 150 void 151 mbinit(void) 152 { 153 154 KASSERT(sizeof(struct _m_ext) <= MHLEN); 155 KASSERT(sizeof(struct mbuf) == MSIZE); 156 157 mclpool_allocator.pa_backingmap = mb_map; 158 pool_init(&mbpool, msize, 0, 0, 0, "mbpl", NULL); 159 pool_init(&mclpool, mclbytes, 0, 0, 0, "mclpl", &mclpool_allocator); 160 161 pool_set_drain_hook(&mbpool, m_reclaim, NULL); 162 pool_set_drain_hook(&mclpool, m_reclaim, NULL); 163 164 pool_cache_init(&mbpool_cache, &mbpool, mb_ctor, NULL, NULL); 165 pool_cache_init(&mclpool_cache, &mclpool, NULL, NULL, NULL); 166 167 /* 168 * Set the hard limit on the mclpool to the number of 169 * mbuf clusters the kernel is to support. Log the limit 170 * reached message max once a minute. 171 */ 172 pool_sethardlimit(&mclpool, nmbclusters, mclpool_warnmsg, 60); 173 174 /* 175 * Set a low water mark for both mbufs and clusters. This should 176 * help ensure that they can be allocated in a memory starvation 177 * situation. This is important for e.g. diskless systems which 178 * must allocate mbufs in order for the pagedaemon to clean pages. 179 */ 180 pool_setlowat(&mbpool, mblowat); 181 pool_setlowat(&mclpool, mcllowat); 182 183 #ifdef MBUFTRACE 184 { 185 /* 186 * Attach the unknown mowners. 187 */ 188 int i; 189 MOWNER_ATTACH(&revoked_mowner); 190 for (i = sizeof(unknown_mowners)/sizeof(unknown_mowners[0]); 191 i-- > 0; ) 192 MOWNER_ATTACH(&unknown_mowners[i]); 193 } 194 #endif 195 } 196 197 /* 198 * sysctl helper routine for the kern.mbuf subtree. nmbclusters may 199 * or may not be writable, and mblowat and mcllowat need range 200 * checking and pool tweaking after being reset. 201 */ 202 static int 203 sysctl_kern_mbuf(SYSCTLFN_ARGS) 204 { 205 int error, newval; 206 struct sysctlnode node; 207 208 node = *rnode; 209 node.sysctl_data = &newval; 210 switch (rnode->sysctl_num) { 211 case MBUF_NMBCLUSTERS: 212 if (mb_map != NULL) { 213 node.sysctl_flags &= ~CTLFLAG_READWRITE; 214 node.sysctl_flags |= CTLFLAG_READONLY; 215 } 216 /* FALLTHROUGH */ 217 case MBUF_MBLOWAT: 218 case MBUF_MCLLOWAT: 219 newval = *(int*)rnode->sysctl_data; 220 break; 221 default: 222 return (EOPNOTSUPP); 223 } 224 225 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 226 if (error || newp == NULL) 227 return (error); 228 if (newval < 0) 229 return (EINVAL); 230 231 switch (node.sysctl_num) { 232 case MBUF_NMBCLUSTERS: 233 if (newval < nmbclusters) 234 return (EINVAL); 235 nmbclusters = newval; 236 pool_sethardlimit(&mclpool, nmbclusters, mclpool_warnmsg, 60); 237 break; 238 case MBUF_MBLOWAT: 239 mblowat = newval; 240 pool_setlowat(&mbpool, mblowat); 241 break; 242 case MBUF_MCLLOWAT: 243 mcllowat = newval; 244 pool_setlowat(&mclpool, mcllowat); 245 break; 246 } 247 248 return (0); 249 } 250 251 #ifdef MBUFTRACE 252 static int 253 sysctl_kern_mbuf_mowners(SYSCTLFN_ARGS) 254 { 255 struct mowner *mo; 256 size_t len = 0; 257 int error = 0; 258 259 if (namelen != 0) 260 return (EINVAL); 261 if (newp != NULL) 262 return (EPERM); 263 264 LIST_FOREACH(mo, &mowners, mo_link) { 265 if (oldp != NULL) { 266 if (*oldlenp - len < sizeof(*mo)) { 267 error = ENOMEM; 268 break; 269 } 270 error = copyout(mo, (caddr_t) oldp + len, 271 sizeof(*mo)); 272 if (error) 273 break; 274 } 275 len += sizeof(*mo); 276 } 277 278 if (error == 0) 279 *oldlenp = len; 280 281 return (error); 282 } 283 #endif /* MBUFTRACE */ 284 285 SYSCTL_SETUP(sysctl_kern_mbuf_setup, "sysctl kern.mbuf subtree setup") 286 { 287 288 sysctl_createv(clog, 0, NULL, NULL, 289 CTLFLAG_PERMANENT, 290 CTLTYPE_NODE, "kern", NULL, 291 NULL, 0, NULL, 0, 292 CTL_KERN, CTL_EOL); 293 sysctl_createv(clog, 0, NULL, NULL, 294 CTLFLAG_PERMANENT, 295 CTLTYPE_NODE, "mbuf", 296 SYSCTL_DESCR("mbuf control variables"), 297 NULL, 0, NULL, 0, 298 CTL_KERN, KERN_MBUF, CTL_EOL); 299 300 sysctl_createv(clog, 0, NULL, NULL, 301 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 302 CTLTYPE_INT, "msize", 303 SYSCTL_DESCR("mbuf base size"), 304 NULL, msize, NULL, 0, 305 CTL_KERN, KERN_MBUF, MBUF_MSIZE, CTL_EOL); 306 sysctl_createv(clog, 0, NULL, NULL, 307 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 308 CTLTYPE_INT, "mclbytes", 309 SYSCTL_DESCR("mbuf cluster size"), 310 NULL, mclbytes, NULL, 0, 311 CTL_KERN, KERN_MBUF, MBUF_MCLBYTES, CTL_EOL); 312 sysctl_createv(clog, 0, NULL, NULL, 313 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 314 CTLTYPE_INT, "nmbclusters", 315 SYSCTL_DESCR("Limit on the number of mbuf clusters"), 316 sysctl_kern_mbuf, 0, &nmbclusters, 0, 317 CTL_KERN, KERN_MBUF, MBUF_NMBCLUSTERS, CTL_EOL); 318 sysctl_createv(clog, 0, NULL, NULL, 319 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 320 CTLTYPE_INT, "mblowat", 321 SYSCTL_DESCR("mbuf low water mark"), 322 sysctl_kern_mbuf, 0, &mblowat, 0, 323 CTL_KERN, KERN_MBUF, MBUF_MBLOWAT, CTL_EOL); 324 sysctl_createv(clog, 0, NULL, NULL, 325 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 326 CTLTYPE_INT, "mcllowat", 327 SYSCTL_DESCR("mbuf cluster low water mark"), 328 sysctl_kern_mbuf, 0, &mcllowat, 0, 329 CTL_KERN, KERN_MBUF, MBUF_MCLLOWAT, CTL_EOL); 330 sysctl_createv(clog, 0, NULL, NULL, 331 CTLFLAG_PERMANENT, 332 CTLTYPE_STRUCT, "stats", 333 SYSCTL_DESCR("mbuf allocation statistics"), 334 NULL, 0, &mbstat, sizeof(mbstat), 335 CTL_KERN, KERN_MBUF, MBUF_STATS, CTL_EOL); 336 #ifdef MBUFTRACE 337 sysctl_createv(clog, 0, NULL, NULL, 338 CTLFLAG_PERMANENT, 339 CTLTYPE_STRUCT, "mowners", 340 SYSCTL_DESCR("Information about mbuf owners"), 341 sysctl_kern_mbuf_mowners, 0, NULL, 0, 342 CTL_KERN, KERN_MBUF, MBUF_MOWNERS, CTL_EOL); 343 #endif /* MBUFTRACE */ 344 } 345 346 static void * 347 mclpool_alloc(struct pool *pp, int flags) 348 { 349 boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE; 350 351 return ((void *)uvm_km_alloc_poolpage(mb_map, waitok)); 352 } 353 354 static void 355 mclpool_release(struct pool *pp, void *v) 356 { 357 358 uvm_km_free_poolpage(mb_map, (vaddr_t)v); 359 } 360 361 /*ARGSUSED*/ 362 static int 363 mb_ctor(void *arg, void *object, int flags) 364 { 365 struct mbuf *m = object; 366 367 #ifdef POOL_VTOPHYS 368 m->m_paddr = POOL_VTOPHYS(m); 369 #else 370 m->m_paddr = M_PADDR_INVALID; 371 #endif 372 return (0); 373 } 374 375 void 376 m_reclaim(void *arg, int flags) 377 { 378 struct domain *dp; 379 const struct protosw *pr; 380 struct ifnet *ifp; 381 int s = splvm(); 382 383 DOMAIN_FOREACH(dp) { 384 for (pr = dp->dom_protosw; 385 pr < dp->dom_protoswNPROTOSW; pr++) 386 if (pr->pr_drain) 387 (*pr->pr_drain)(); 388 } 389 IFNET_FOREACH(ifp) { 390 if (ifp->if_drain) 391 (*ifp->if_drain)(ifp); 392 } 393 splx(s); 394 mbstat.m_drain++; 395 } 396 397 /* 398 * Space allocation routines. 399 * These are also available as macros 400 * for critical paths. 401 */ 402 struct mbuf * 403 m_get(int nowait, int type) 404 { 405 struct mbuf *m; 406 407 MGET(m, nowait, type); 408 return (m); 409 } 410 411 struct mbuf * 412 m_gethdr(int nowait, int type) 413 { 414 struct mbuf *m; 415 416 MGETHDR(m, nowait, type); 417 return (m); 418 } 419 420 struct mbuf * 421 m_getclr(int nowait, int type) 422 { 423 struct mbuf *m; 424 425 MGET(m, nowait, type); 426 if (m == 0) 427 return (NULL); 428 memset(mtod(m, caddr_t), 0, MLEN); 429 return (m); 430 } 431 432 void 433 m_clget(struct mbuf *m, int nowait) 434 { 435 436 MCLGET(m, nowait); 437 } 438 439 struct mbuf * 440 m_free(struct mbuf *m) 441 { 442 struct mbuf *n; 443 444 MFREE(m, n); 445 return (n); 446 } 447 448 void 449 m_freem(struct mbuf *m) 450 { 451 struct mbuf *n; 452 453 if (m == NULL) 454 return; 455 do { 456 MFREE(m, n); 457 m = n; 458 } while (m); 459 } 460 461 #ifdef MBUFTRACE 462 /* 463 * Walk a chain of mbufs, claiming ownership of each mbuf in the chain. 464 */ 465 void 466 m_claimm(struct mbuf *m, struct mowner *mo) 467 { 468 469 for (; m != NULL; m = m->m_next) 470 MCLAIM(m, mo); 471 } 472 #endif 473 474 /* 475 * Mbuffer utility routines. 476 */ 477 478 /* 479 * Lesser-used path for M_PREPEND: 480 * allocate new mbuf to prepend to chain, 481 * copy junk along. 482 */ 483 struct mbuf * 484 m_prepend(struct mbuf *m, int len, int how) 485 { 486 struct mbuf *mn; 487 488 MGET(mn, how, m->m_type); 489 if (mn == (struct mbuf *)NULL) { 490 m_freem(m); 491 return ((struct mbuf *)NULL); 492 } 493 if (m->m_flags & M_PKTHDR) { 494 M_MOVE_PKTHDR(mn, m); 495 } else { 496 MCLAIM(mn, m->m_owner); 497 } 498 mn->m_next = m; 499 m = mn; 500 if (len < MHLEN) 501 MH_ALIGN(m, len); 502 m->m_len = len; 503 return (m); 504 } 505 506 /* 507 * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 508 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 509 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 510 */ 511 int MCFail; 512 513 struct mbuf * 514 m_copym(struct mbuf *m, int off0, int len, int wait) 515 { 516 517 return m_copym0(m, off0, len, wait, 0); /* shallow copy on M_EXT */ 518 } 519 520 struct mbuf * 521 m_dup(struct mbuf *m, int off0, int len, int wait) 522 { 523 524 return m_copym0(m, off0, len, wait, 1); /* deep copy */ 525 } 526 527 static struct mbuf * 528 m_copym0(struct mbuf *m, int off0, int len, int wait, int deep) 529 { 530 struct mbuf *n, **np; 531 int off = off0; 532 struct mbuf *top; 533 int copyhdr = 0; 534 535 if (off < 0 || len < 0) 536 panic("m_copym: off %d, len %d", off, len); 537 if (off == 0 && m->m_flags & M_PKTHDR) 538 copyhdr = 1; 539 while (off > 0) { 540 if (m == 0) 541 panic("m_copym: m == 0, off %d", off); 542 if (off < m->m_len) 543 break; 544 off -= m->m_len; 545 m = m->m_next; 546 } 547 np = ⊤ 548 top = 0; 549 while (len > 0) { 550 if (m == 0) { 551 if (len != M_COPYALL) 552 panic("m_copym: m == 0, len %d [!COPYALL]", 553 len); 554 break; 555 } 556 MGET(n, wait, m->m_type); 557 *np = n; 558 if (n == 0) 559 goto nospace; 560 MCLAIM(n, m->m_owner); 561 if (copyhdr) { 562 M_COPY_PKTHDR(n, m); 563 if (len == M_COPYALL) 564 n->m_pkthdr.len -= off0; 565 else 566 n->m_pkthdr.len = len; 567 copyhdr = 0; 568 } 569 n->m_len = min(len, m->m_len - off); 570 if (m->m_flags & M_EXT) { 571 if (!deep) { 572 n->m_data = m->m_data + off; 573 n->m_ext = m->m_ext; 574 MCLADDREFERENCE(m, n); 575 } else { 576 /* 577 * we are unsure about the way m was allocated. 578 * copy into multiple MCLBYTES cluster mbufs. 579 */ 580 MCLGET(n, wait); 581 n->m_len = 0; 582 n->m_len = M_TRAILINGSPACE(n); 583 n->m_len = min(n->m_len, len); 584 n->m_len = min(n->m_len, m->m_len - off); 585 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, 586 (unsigned)n->m_len); 587 } 588 } else 589 memcpy(mtod(n, caddr_t), mtod(m, caddr_t)+off, 590 (unsigned)n->m_len); 591 if (len != M_COPYALL) 592 len -= n->m_len; 593 off += n->m_len; 594 #ifdef DIAGNOSTIC 595 if (off > m->m_len) 596 panic("m_copym0 overrun"); 597 #endif 598 if (off == m->m_len) { 599 m = m->m_next; 600 off = 0; 601 } 602 np = &n->m_next; 603 } 604 if (top == 0) 605 MCFail++; 606 return (top); 607 nospace: 608 m_freem(top); 609 MCFail++; 610 return (NULL); 611 } 612 613 /* 614 * Copy an entire packet, including header (which must be present). 615 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'. 616 */ 617 struct mbuf * 618 m_copypacket(struct mbuf *m, int how) 619 { 620 struct mbuf *top, *n, *o; 621 622 MGET(n, how, m->m_type); 623 top = n; 624 if (!n) 625 goto nospace; 626 627 MCLAIM(n, m->m_owner); 628 M_COPY_PKTHDR(n, m); 629 n->m_len = m->m_len; 630 if (m->m_flags & M_EXT) { 631 n->m_data = m->m_data; 632 n->m_ext = m->m_ext; 633 MCLADDREFERENCE(m, n); 634 } else { 635 memcpy(mtod(n, char *), mtod(m, char *), n->m_len); 636 } 637 638 m = m->m_next; 639 while (m) { 640 MGET(o, how, m->m_type); 641 if (!o) 642 goto nospace; 643 644 MCLAIM(o, m->m_owner); 645 n->m_next = o; 646 n = n->m_next; 647 648 n->m_len = m->m_len; 649 if (m->m_flags & M_EXT) { 650 n->m_data = m->m_data; 651 n->m_ext = m->m_ext; 652 MCLADDREFERENCE(m, n); 653 } else { 654 memcpy(mtod(n, char *), mtod(m, char *), n->m_len); 655 } 656 657 m = m->m_next; 658 } 659 return top; 660 nospace: 661 m_freem(top); 662 MCFail++; 663 return NULL; 664 } 665 666 /* 667 * Copy data from an mbuf chain starting "off" bytes from the beginning, 668 * continuing for "len" bytes, into the indicated buffer. 669 */ 670 void 671 m_copydata(struct mbuf *m, int off, int len, void *vp) 672 { 673 unsigned count; 674 caddr_t cp = vp; 675 676 if (off < 0 || len < 0) 677 panic("m_copydata: off %d, len %d", off, len); 678 while (off > 0) { 679 if (m == NULL) 680 panic("m_copydata: m == NULL, off %d", off); 681 if (off < m->m_len) 682 break; 683 off -= m->m_len; 684 m = m->m_next; 685 } 686 while (len > 0) { 687 if (m == NULL) 688 panic("m_copydata: m == NULL, len %d", len); 689 count = min(m->m_len - off, len); 690 memcpy(cp, mtod(m, caddr_t) + off, count); 691 len -= count; 692 cp += count; 693 off = 0; 694 m = m->m_next; 695 } 696 } 697 698 /* 699 * Concatenate mbuf chain n to m. 700 * n might be copied into m (when n->m_len is small), therefore data portion of 701 * n could be copied into an mbuf of different mbuf type. 702 * Any m_pkthdr is not updated. 703 */ 704 void 705 m_cat(struct mbuf *m, struct mbuf *n) 706 { 707 708 while (m->m_next) 709 m = m->m_next; 710 while (n) { 711 if (M_READONLY(m) || n->m_len > M_TRAILINGSPACE(m)) { 712 /* just join the two chains */ 713 m->m_next = n; 714 return; 715 } 716 /* splat the data from one into the other */ 717 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 718 (u_int)n->m_len); 719 m->m_len += n->m_len; 720 n = m_free(n); 721 } 722 } 723 724 void 725 m_adj(struct mbuf *mp, int req_len) 726 { 727 int len = req_len; 728 struct mbuf *m; 729 int count; 730 731 if ((m = mp) == NULL) 732 return; 733 if (len >= 0) { 734 /* 735 * Trim from head. 736 */ 737 while (m != NULL && len > 0) { 738 if (m->m_len <= len) { 739 len -= m->m_len; 740 m->m_len = 0; 741 m = m->m_next; 742 } else { 743 m->m_len -= len; 744 m->m_data += len; 745 len = 0; 746 } 747 } 748 m = mp; 749 if (mp->m_flags & M_PKTHDR) 750 m->m_pkthdr.len -= (req_len - len); 751 } else { 752 /* 753 * Trim from tail. Scan the mbuf chain, 754 * calculating its length and finding the last mbuf. 755 * If the adjustment only affects this mbuf, then just 756 * adjust and return. Otherwise, rescan and truncate 757 * after the remaining size. 758 */ 759 len = -len; 760 count = 0; 761 for (;;) { 762 count += m->m_len; 763 if (m->m_next == (struct mbuf *)0) 764 break; 765 m = m->m_next; 766 } 767 if (m->m_len >= len) { 768 m->m_len -= len; 769 if (mp->m_flags & M_PKTHDR) 770 mp->m_pkthdr.len -= len; 771 return; 772 } 773 count -= len; 774 if (count < 0) 775 count = 0; 776 /* 777 * Correct length for chain is "count". 778 * Find the mbuf with last data, adjust its length, 779 * and toss data from remaining mbufs on chain. 780 */ 781 m = mp; 782 if (m->m_flags & M_PKTHDR) 783 m->m_pkthdr.len = count; 784 for (; m; m = m->m_next) { 785 if (m->m_len >= count) { 786 m->m_len = count; 787 break; 788 } 789 count -= m->m_len; 790 } 791 if (m) 792 while (m->m_next) 793 (m = m->m_next)->m_len = 0; 794 } 795 } 796 797 /* 798 * Rearrange an mbuf chain so that len bytes are contiguous 799 * and in the data area of an mbuf (so that mtod and dtom 800 * will work for a structure of size len). Returns the resulting 801 * mbuf chain on success, frees it and returns null on failure. 802 * If there is room, it will add up to max_protohdr-len extra bytes to the 803 * contiguous region in an attempt to avoid being called next time. 804 */ 805 int MPFail; 806 807 struct mbuf * 808 m_pullup(struct mbuf *n, int len) 809 { 810 struct mbuf *m; 811 int count; 812 int space; 813 814 /* 815 * If first mbuf has no cluster, and has room for len bytes 816 * without shifting current data, pullup into it, 817 * otherwise allocate a new mbuf to prepend to the chain. 818 */ 819 if ((n->m_flags & M_EXT) == 0 && 820 n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 821 if (n->m_len >= len) 822 return (n); 823 m = n; 824 n = n->m_next; 825 len -= m->m_len; 826 } else { 827 if (len > MHLEN) 828 goto bad; 829 MGET(m, M_DONTWAIT, n->m_type); 830 if (m == 0) 831 goto bad; 832 MCLAIM(m, n->m_owner); 833 m->m_len = 0; 834 if (n->m_flags & M_PKTHDR) { 835 M_MOVE_PKTHDR(m, n); 836 } 837 } 838 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 839 do { 840 count = min(min(max(len, max_protohdr), space), n->m_len); 841 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 842 (unsigned)count); 843 len -= count; 844 m->m_len += count; 845 n->m_len -= count; 846 space -= count; 847 if (n->m_len) 848 n->m_data += count; 849 else 850 n = m_free(n); 851 } while (len > 0 && n); 852 if (len > 0) { 853 (void) m_free(m); 854 goto bad; 855 } 856 m->m_next = n; 857 return (m); 858 bad: 859 m_freem(n); 860 MPFail++; 861 return (NULL); 862 } 863 864 /* 865 * Like m_pullup(), except a new mbuf is always allocated, and we allow 866 * the amount of empty space before the data in the new mbuf to be specified 867 * (in the event that the caller expects to prepend later). 868 */ 869 int MSFail; 870 871 struct mbuf * 872 m_copyup(struct mbuf *n, int len, int dstoff) 873 { 874 struct mbuf *m; 875 int count, space; 876 877 if (len > (MHLEN - dstoff)) 878 goto bad; 879 MGET(m, M_DONTWAIT, n->m_type); 880 if (m == NULL) 881 goto bad; 882 MCLAIM(m, n->m_owner); 883 m->m_len = 0; 884 if (n->m_flags & M_PKTHDR) { 885 M_MOVE_PKTHDR(m, n); 886 } 887 m->m_data += dstoff; 888 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 889 do { 890 count = min(min(max(len, max_protohdr), space), n->m_len); 891 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), 892 (unsigned)count); 893 len -= count; 894 m->m_len += count; 895 n->m_len -= count; 896 space -= count; 897 if (n->m_len) 898 n->m_data += count; 899 else 900 n = m_free(n); 901 } while (len > 0 && n); 902 if (len > 0) { 903 (void) m_free(m); 904 goto bad; 905 } 906 m->m_next = n; 907 return (m); 908 bad: 909 m_freem(n); 910 MSFail++; 911 return (NULL); 912 } 913 914 /* 915 * Partition an mbuf chain in two pieces, returning the tail -- 916 * all but the first len0 bytes. In case of failure, it returns NULL and 917 * attempts to restore the chain to its original state. 918 */ 919 struct mbuf * 920 m_split(struct mbuf *m0, int len0, int wait) 921 { 922 923 return m_split0(m0, len0, wait, 1); 924 } 925 926 static struct mbuf * 927 m_split0(struct mbuf *m0, int len0, int wait, int copyhdr) 928 { 929 struct mbuf *m, *n; 930 unsigned len = len0, remain, len_save; 931 932 for (m = m0; m && len > m->m_len; m = m->m_next) 933 len -= m->m_len; 934 if (m == 0) 935 return (NULL); 936 remain = m->m_len - len; 937 if (copyhdr && (m0->m_flags & M_PKTHDR)) { 938 MGETHDR(n, wait, m0->m_type); 939 if (n == 0) 940 return (NULL); 941 MCLAIM(m, m0->m_owner); 942 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 943 n->m_pkthdr.len = m0->m_pkthdr.len - len0; 944 len_save = m0->m_pkthdr.len; 945 m0->m_pkthdr.len = len0; 946 if (m->m_flags & M_EXT) 947 goto extpacket; 948 if (remain > MHLEN) { 949 /* m can't be the lead packet */ 950 MH_ALIGN(n, 0); 951 n->m_next = m_split(m, len, wait); 952 if (n->m_next == 0) { 953 (void) m_free(n); 954 m0->m_pkthdr.len = len_save; 955 return (NULL); 956 } else 957 return (n); 958 } else 959 MH_ALIGN(n, remain); 960 } else if (remain == 0) { 961 n = m->m_next; 962 m->m_next = 0; 963 return (n); 964 } else { 965 MGET(n, wait, m->m_type); 966 if (n == 0) 967 return (NULL); 968 MCLAIM(n, m->m_owner); 969 M_ALIGN(n, remain); 970 } 971 extpacket: 972 if (m->m_flags & M_EXT) { 973 n->m_ext = m->m_ext; 974 MCLADDREFERENCE(m, n); 975 n->m_data = m->m_data + len; 976 } else { 977 memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain); 978 } 979 n->m_len = remain; 980 m->m_len = len; 981 n->m_next = m->m_next; 982 m->m_next = 0; 983 return (n); 984 } 985 /* 986 * Routine to copy from device local memory into mbufs. 987 */ 988 struct mbuf * 989 m_devget(char *buf, int totlen, int off0, struct ifnet *ifp, 990 void (*copy)(const void *from, void *to, size_t len)) 991 { 992 struct mbuf *m; 993 struct mbuf *top = 0, **mp = ⊤ 994 int off = off0, len; 995 char *cp; 996 char *epkt; 997 998 cp = buf; 999 epkt = cp + totlen; 1000 if (off) { 1001 /* 1002 * If 'off' is non-zero, packet is trailer-encapsulated, 1003 * so we have to skip the type and length fields. 1004 */ 1005 cp += off + 2 * sizeof(uint16_t); 1006 totlen -= 2 * sizeof(uint16_t); 1007 } 1008 MGETHDR(m, M_DONTWAIT, MT_DATA); 1009 if (m == 0) 1010 return (NULL); 1011 m->m_pkthdr.rcvif = ifp; 1012 m->m_pkthdr.len = totlen; 1013 m->m_len = MHLEN; 1014 1015 while (totlen > 0) { 1016 if (top) { 1017 MGET(m, M_DONTWAIT, MT_DATA); 1018 if (m == 0) { 1019 m_freem(top); 1020 return (NULL); 1021 } 1022 m->m_len = MLEN; 1023 } 1024 len = min(totlen, epkt - cp); 1025 if (len >= MINCLSIZE) { 1026 MCLGET(m, M_DONTWAIT); 1027 if ((m->m_flags & M_EXT) == 0) { 1028 m_free(m); 1029 m_freem(top); 1030 return (NULL); 1031 } 1032 m->m_len = len = min(len, MCLBYTES); 1033 } else { 1034 /* 1035 * Place initial small packet/header at end of mbuf. 1036 */ 1037 if (len < m->m_len) { 1038 if (top == 0 && len + max_linkhdr <= m->m_len) 1039 m->m_data += max_linkhdr; 1040 m->m_len = len; 1041 } else 1042 len = m->m_len; 1043 } 1044 if (copy) 1045 copy(cp, mtod(m, caddr_t), (size_t)len); 1046 else 1047 memcpy(mtod(m, caddr_t), cp, (size_t)len); 1048 cp += len; 1049 *mp = m; 1050 mp = &m->m_next; 1051 totlen -= len; 1052 if (cp == epkt) 1053 cp = buf; 1054 } 1055 return (top); 1056 } 1057 1058 /* 1059 * Copy data from a buffer back into the indicated mbuf chain, 1060 * starting "off" bytes from the beginning, extending the mbuf 1061 * chain if necessary. 1062 */ 1063 void 1064 m_copyback(struct mbuf *m0, int off, int len, const void *cp) 1065 { 1066 #if defined(DEBUG) 1067 struct mbuf *origm = m0; 1068 int error; 1069 #endif /* defined(DEBUG) */ 1070 1071 if (m0 == NULL) 1072 return; 1073 1074 #if defined(DEBUG) 1075 error = 1076 #endif /* defined(DEBUG) */ 1077 m_copyback0(&m0, off, len, cp, 1078 M_COPYBACK0_COPYBACK|M_COPYBACK0_EXTEND, M_DONTWAIT); 1079 1080 #if defined(DEBUG) 1081 if (error != 0 || (m0 != NULL && origm != m0)) 1082 panic("m_copyback"); 1083 #endif /* defined(DEBUG) */ 1084 } 1085 1086 struct mbuf * 1087 m_copyback_cow(struct mbuf *m0, int off, int len, const void *cp, int how) 1088 { 1089 int error; 1090 1091 /* don't support chain expansion */ 1092 KDASSERT(off + len <= m_length(m0)); 1093 1094 error = m_copyback0(&m0, off, len, cp, 1095 M_COPYBACK0_COPYBACK|M_COPYBACK0_COW, how); 1096 if (error) { 1097 /* 1098 * no way to recover from partial success. 1099 * just free the chain. 1100 */ 1101 m_freem(m0); 1102 return NULL; 1103 } 1104 return m0; 1105 } 1106 1107 /* 1108 * m_makewritable: ensure the specified range writable. 1109 */ 1110 int 1111 m_makewritable(struct mbuf **mp, int off, int len, int how) 1112 { 1113 int error; 1114 #if defined(DEBUG) 1115 struct mbuf *n; 1116 int origlen, reslen; 1117 1118 origlen = m_length(*mp); 1119 #endif /* defined(DEBUG) */ 1120 1121 #if 0 /* M_COPYALL is large enough */ 1122 if (len == M_COPYALL) 1123 len = m_length(*mp) - off; /* XXX */ 1124 #endif 1125 1126 error = m_copyback0(mp, off, len, NULL, 1127 M_COPYBACK0_PRESERVE|M_COPYBACK0_COW, how); 1128 1129 #if defined(DEBUG) 1130 reslen = 0; 1131 for (n = *mp; n; n = n->m_next) 1132 reslen += n->m_len; 1133 if (origlen != reslen) 1134 panic("m_makewritable: length changed"); 1135 if (((*mp)->m_flags & M_PKTHDR) != 0 && reslen != (*mp)->m_pkthdr.len) 1136 panic("m_makewritable: inconsist"); 1137 #endif /* defined(DEBUG) */ 1138 1139 return error; 1140 } 1141 1142 int 1143 m_copyback0(struct mbuf **mp0, int off, int len, const void *vp, int flags, 1144 int how) 1145 { 1146 int mlen; 1147 struct mbuf *m, *n; 1148 struct mbuf **mp; 1149 int totlen = 0; 1150 const char *cp = vp; 1151 1152 KASSERT(mp0 != NULL); 1153 KASSERT(*mp0 != NULL); 1154 KASSERT((flags & M_COPYBACK0_PRESERVE) == 0 || cp == NULL); 1155 KASSERT((flags & M_COPYBACK0_COPYBACK) == 0 || cp != NULL); 1156 1157 /* 1158 * we don't bother to update "totlen" in the case of M_COPYBACK0_COW, 1159 * assuming that M_COPYBACK0_EXTEND and M_COPYBACK0_COW are exclusive. 1160 */ 1161 1162 KASSERT((~flags & (M_COPYBACK0_EXTEND|M_COPYBACK0_COW)) != 0); 1163 1164 mp = mp0; 1165 m = *mp; 1166 while (off > (mlen = m->m_len)) { 1167 off -= mlen; 1168 totlen += mlen; 1169 if (m->m_next == NULL) { 1170 int tspace; 1171 extend: 1172 if ((flags & M_COPYBACK0_EXTEND) == 0) 1173 goto out; 1174 1175 /* 1176 * try to make some space at the end of "m". 1177 */ 1178 1179 mlen = m->m_len; 1180 if (off + len >= MINCLSIZE && 1181 (m->m_flags & M_EXT) == 0 && m->m_len == 0) { 1182 MCLGET(m, how); 1183 } 1184 tspace = M_TRAILINGSPACE(m); 1185 if (tspace > 0) { 1186 tspace = min(tspace, off + len); 1187 KASSERT(tspace > 0); 1188 memset(mtod(m, char *) + m->m_len, 0, 1189 min(off, tspace)); 1190 m->m_len += tspace; 1191 off += mlen; 1192 totlen -= mlen; 1193 continue; 1194 } 1195 1196 /* 1197 * need to allocate an mbuf. 1198 */ 1199 1200 if (off + len >= MINCLSIZE) { 1201 n = m_getcl(how, m->m_type, 0); 1202 } else { 1203 n = m_get(how, m->m_type); 1204 } 1205 if (n == NULL) { 1206 goto out; 1207 } 1208 n->m_len = 0; 1209 n->m_len = min(M_TRAILINGSPACE(n), off + len); 1210 memset(mtod(n, char *), 0, min(n->m_len, off)); 1211 m->m_next = n; 1212 } 1213 mp = &m->m_next; 1214 m = m->m_next; 1215 } 1216 while (len > 0) { 1217 mlen = m->m_len - off; 1218 if (mlen != 0 && M_READONLY(m)) { 1219 char *datap; 1220 int eatlen; 1221 1222 /* 1223 * this mbuf is read-only. 1224 * allocate a new writable mbuf and try again. 1225 */ 1226 1227 #if defined(DIAGNOSTIC) 1228 if ((flags & M_COPYBACK0_COW) == 0) 1229 panic("m_copyback0: read-only"); 1230 #endif /* defined(DIAGNOSTIC) */ 1231 1232 /* 1233 * if we're going to write into the middle of 1234 * a mbuf, split it first. 1235 */ 1236 if (off > 0 && len < mlen) { 1237 n = m_split0(m, off, how, 0); 1238 if (n == NULL) 1239 goto enobufs; 1240 m->m_next = n; 1241 mp = &m->m_next; 1242 m = n; 1243 off = 0; 1244 continue; 1245 } 1246 1247 /* 1248 * XXX TODO coalesce into the trailingspace of 1249 * the previous mbuf when possible. 1250 */ 1251 1252 /* 1253 * allocate a new mbuf. copy packet header if needed. 1254 */ 1255 MGET(n, how, m->m_type); 1256 if (n == NULL) 1257 goto enobufs; 1258 MCLAIM(n, m->m_owner); 1259 if (off == 0 && (m->m_flags & M_PKTHDR) != 0) { 1260 M_MOVE_PKTHDR(n, m); 1261 n->m_len = MHLEN; 1262 } else { 1263 if (len >= MINCLSIZE) 1264 MCLGET(n, M_DONTWAIT); 1265 n->m_len = 1266 (n->m_flags & M_EXT) ? MCLBYTES : MLEN; 1267 } 1268 if (n->m_len > len) 1269 n->m_len = len; 1270 1271 /* 1272 * free the region which has been overwritten. 1273 * copying data from old mbufs if requested. 1274 */ 1275 if (flags & M_COPYBACK0_PRESERVE) 1276 datap = mtod(n, char *); 1277 else 1278 datap = NULL; 1279 eatlen = n->m_len; 1280 KDASSERT(off == 0 || eatlen >= mlen); 1281 if (off > 0) { 1282 KDASSERT(len >= mlen); 1283 m->m_len = off; 1284 m->m_next = n; 1285 if (datap) { 1286 m_copydata(m, off, mlen, datap); 1287 datap += mlen; 1288 } 1289 eatlen -= mlen; 1290 mp = &m->m_next; 1291 m = m->m_next; 1292 } 1293 while (m != NULL && M_READONLY(m) && 1294 n->m_type == m->m_type && eatlen > 0) { 1295 mlen = min(eatlen, m->m_len); 1296 if (datap) { 1297 m_copydata(m, 0, mlen, datap); 1298 datap += mlen; 1299 } 1300 m->m_data += mlen; 1301 m->m_len -= mlen; 1302 eatlen -= mlen; 1303 if (m->m_len == 0) 1304 *mp = m = m_free(m); 1305 } 1306 if (eatlen > 0) 1307 n->m_len -= eatlen; 1308 n->m_next = m; 1309 *mp = m = n; 1310 continue; 1311 } 1312 mlen = min(mlen, len); 1313 if (flags & M_COPYBACK0_COPYBACK) { 1314 memcpy(mtod(m, caddr_t) + off, cp, (unsigned)mlen); 1315 cp += mlen; 1316 } 1317 len -= mlen; 1318 mlen += off; 1319 off = 0; 1320 totlen += mlen; 1321 if (len == 0) 1322 break; 1323 if (m->m_next == NULL) { 1324 goto extend; 1325 } 1326 mp = &m->m_next; 1327 m = m->m_next; 1328 } 1329 out: if (((m = *mp0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) { 1330 KASSERT((flags & M_COPYBACK0_EXTEND) != 0); 1331 m->m_pkthdr.len = totlen; 1332 } 1333 1334 return 0; 1335 1336 enobufs: 1337 return ENOBUFS; 1338 } 1339 1340 void 1341 m_move_pkthdr(struct mbuf *to, struct mbuf *from) 1342 { 1343 1344 KASSERT((to->m_flags & M_EXT) == 0); 1345 KASSERT((to->m_flags & M_PKTHDR) == 0 || m_tag_first(to) == NULL); 1346 KASSERT((from->m_flags & M_PKTHDR) != 0); 1347 1348 to->m_pkthdr = from->m_pkthdr; 1349 to->m_flags = from->m_flags & M_COPYFLAGS; 1350 to->m_data = to->m_pktdat; 1351 1352 from->m_flags &= ~M_PKTHDR; 1353 } 1354 1355 /* 1356 * Apply function f to the data in an mbuf chain starting "off" bytes from the 1357 * beginning, continuing for "len" bytes. 1358 */ 1359 int 1360 m_apply(struct mbuf *m, int off, int len, 1361 int (*f)(void *, caddr_t, unsigned int), void *arg) 1362 { 1363 unsigned int count; 1364 int rval; 1365 1366 KASSERT(len >= 0); 1367 KASSERT(off >= 0); 1368 1369 while (off > 0) { 1370 KASSERT(m != NULL); 1371 if (off < m->m_len) 1372 break; 1373 off -= m->m_len; 1374 m = m->m_next; 1375 } 1376 while (len > 0) { 1377 KASSERT(m != NULL); 1378 count = min(m->m_len - off, len); 1379 1380 rval = (*f)(arg, mtod(m, caddr_t) + off, count); 1381 if (rval) 1382 return (rval); 1383 1384 len -= count; 1385 off = 0; 1386 m = m->m_next; 1387 } 1388 1389 return (0); 1390 } 1391 1392 /* 1393 * Return a pointer to mbuf/offset of location in mbuf chain. 1394 */ 1395 struct mbuf * 1396 m_getptr(struct mbuf *m, int loc, int *off) 1397 { 1398 1399 while (loc >= 0) { 1400 /* Normal end of search */ 1401 if (m->m_len > loc) { 1402 *off = loc; 1403 return (m); 1404 } else { 1405 loc -= m->m_len; 1406 1407 if (m->m_next == NULL) { 1408 if (loc == 0) { 1409 /* Point at the end of valid data */ 1410 *off = m->m_len; 1411 return (m); 1412 } else 1413 return (NULL); 1414 } else 1415 m = m->m_next; 1416 } 1417 } 1418 1419 return (NULL); 1420 } 1421 1422 #if defined(DDB) 1423 void 1424 m_print(const struct mbuf *m, const char *modif, void (*pr)(const char *, ...)) 1425 { 1426 char ch; 1427 boolean_t opt_c = FALSE; 1428 char buf[512]; 1429 1430 while ((ch = *(modif++)) != '\0') { 1431 switch (ch) { 1432 case 'c': 1433 opt_c = TRUE; 1434 break; 1435 } 1436 } 1437 1438 nextchain: 1439 (*pr)("MBUF %p\n", m); 1440 bitmask_snprintf(m->m_flags, M_FLAGS_BITS, buf, sizeof(buf)); 1441 (*pr)(" data=%p, len=%d, type=%d, flags=0x%s\n", 1442 m->m_data, m->m_len, m->m_type, buf); 1443 (*pr)(" owner=%p, next=%p, nextpkt=%p\n", m->m_owner, m->m_next, 1444 m->m_nextpkt); 1445 (*pr)(" leadingspace=%u, trailingspace=%u, readonly=%u\n", 1446 (int)M_LEADINGSPACE(m), (int)M_TRAILINGSPACE(m), 1447 (int)M_READONLY(m)); 1448 if ((m->m_flags & M_PKTHDR) != 0) { 1449 bitmask_snprintf(m->m_pkthdr.csum_flags, M_CSUM_BITS, buf, 1450 sizeof(buf)); 1451 (*pr)(" pktlen=%d, rcvif=%p, csum_flags=0x%s, csum_data=0x%" 1452 PRIx32 ", segsz=%u\n", 1453 m->m_pkthdr.len, m->m_pkthdr.rcvif, 1454 buf, m->m_pkthdr.csum_data, m->m_pkthdr.segsz); 1455 } 1456 if ((m->m_flags & M_EXT)) { 1457 (*pr)(" shared=%u, ext_buf=%p, ext_size=%zd, " 1458 "ext_free=%p, ext_arg=%p\n", 1459 (int)MCLISREFERENCED(m), 1460 m->m_ext.ext_buf, m->m_ext.ext_size, 1461 m->m_ext.ext_free, m->m_ext.ext_arg); 1462 } 1463 if ((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0) { 1464 vaddr_t sva = (vaddr_t)m->m_ext.ext_buf; 1465 vaddr_t eva = sva + m->m_ext.ext_size; 1466 int n = (round_page(eva) - trunc_page(sva)) >> PAGE_SHIFT; 1467 int i; 1468 1469 (*pr)(" pages:"); 1470 for (i = 0; i < n; i ++) { 1471 (*pr)(" %p", m->m_ext.ext_pgs[i]); 1472 } 1473 (*pr)("\n"); 1474 } 1475 1476 if (opt_c) { 1477 m = m->m_next; 1478 if (m != NULL) { 1479 goto nextchain; 1480 } 1481 } 1482 } 1483 #endif /* defined(DDB) */ 1484