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 * $Id$ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/proc.h> 40 #include <sys/malloc.h> 41 #include <sys/map.h> 42 #define MBTYPES 43 #include <sys/mbuf.h> 44 #include <sys/kernel.h> 45 #include <sys/syslog.h> 46 #include <sys/domain.h> 47 #include <sys/protosw.h> 48 49 #include <vm/vm.h> 50 51 void m_reclaim __P(()); 52 53 extern vm_map_t mb_map; 54 struct mbuf *mbutl; 55 char *mclrefcnt; 56 57 void 58 mbinit() 59 { 60 int s; 61 62 #if CLBYTES < 4096 63 #define NCL_INIT (4096/CLBYTES) 64 #else 65 #define NCL_INIT 1 66 #endif 67 s = splimp(); 68 if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) 69 goto bad; 70 splx(s); 71 return; 72 bad: 73 panic("mbinit"); 74 } 75 76 /* 77 * Allocate some number of mbuf clusters 78 * and place on cluster free list. 79 * Must be called at splimp. 80 */ 81 /* ARGSUSED */ 82 int 83 m_clalloc(ncl, nowait) 84 register int ncl; 85 int nowait; 86 { 87 static int logged; 88 register caddr_t p; 89 register int i; 90 int npg; 91 92 npg = ncl * CLSIZE; 93 p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait); 94 if (p == NULL) { 95 if (logged == 0) { 96 logged++; 97 log(LOG_ERR, "mb_map full\n"); 98 } 99 return (0); 100 } 101 ncl = ncl * CLBYTES / MCLBYTES; 102 for (i = 0; i < ncl; i++) { 103 ((union mcluster *)p)->mcl_next = mclfree; 104 mclfree = (union mcluster *)p; 105 p += MCLBYTES; 106 mbstat.m_clfree++; 107 } 108 mbstat.m_clusters += ncl; 109 return (1); 110 } 111 112 /* 113 * When MGET failes, ask protocols to free space when short of memory, 114 * then re-attempt to allocate an mbuf. 115 */ 116 struct mbuf * 117 m_retry(i, t) 118 int i, t; 119 { 120 register struct mbuf *m; 121 122 m_reclaim(); 123 #define m_retry(i, t) (struct mbuf *)0 124 MGET(m, i, t); 125 #undef m_retry 126 return (m); 127 } 128 129 /* 130 * As above; retry an MGETHDR. 131 */ 132 struct mbuf * 133 m_retryhdr(i, t) 134 int i, t; 135 { 136 register struct mbuf *m; 137 138 m_reclaim(); 139 #define m_retryhdr(i, t) (struct mbuf *)0 140 MGETHDR(m, i, t); 141 #undef m_retryhdr 142 return (m); 143 } 144 145 void 146 m_reclaim() 147 { 148 register struct domain *dp; 149 register struct protosw *pr; 150 int s = splimp(); 151 152 for (dp = domains; dp; dp = dp->dom_next) 153 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 154 if (pr->pr_drain) 155 (*pr->pr_drain)(); 156 splx(s); 157 mbstat.m_drain++; 158 } 159 160 /* 161 * Space allocation routines. 162 * These are also available as macros 163 * for critical paths. 164 */ 165 struct mbuf * 166 m_get(nowait, type) 167 int nowait, type; 168 { 169 register struct mbuf *m; 170 171 MGET(m, nowait, type); 172 return (m); 173 } 174 175 struct mbuf * 176 m_gethdr(nowait, type) 177 int nowait, type; 178 { 179 register struct mbuf *m; 180 181 MGETHDR(m, nowait, type); 182 return (m); 183 } 184 185 struct mbuf * 186 m_getclr(nowait, type) 187 int nowait, type; 188 { 189 register struct mbuf *m; 190 191 MGET(m, nowait, type); 192 if (m == 0) 193 return (0); 194 bzero(mtod(m, caddr_t), MLEN); 195 return (m); 196 } 197 198 struct mbuf * 199 m_free(m) 200 struct mbuf *m; 201 { 202 register struct mbuf *n; 203 204 MFREE(m, n); 205 return (n); 206 } 207 208 void 209 m_freem(m) 210 register struct mbuf *m; 211 { 212 register struct mbuf *n; 213 214 if (m == NULL) 215 return; 216 do { 217 MFREE(m, n); 218 } while (m = n); 219 } 220 221 /* 222 * Mbuffer utility routines. 223 */ 224 225 /* 226 * Lesser-used path for M_PREPEND: 227 * allocate new mbuf to prepend to chain, 228 * copy junk along. 229 */ 230 struct mbuf * 231 m_prepend(m, len, how) 232 register struct mbuf *m; 233 int len, how; 234 { 235 struct mbuf *mn; 236 237 MGET(mn, how, m->m_type); 238 if (mn == (struct mbuf *)NULL) { 239 m_freem(m); 240 return ((struct mbuf *)NULL); 241 } 242 if (m->m_flags & M_PKTHDR) { 243 M_COPY_PKTHDR(mn, m); 244 m->m_flags &= ~M_PKTHDR; 245 } 246 mn->m_next = m; 247 m = mn; 248 if (len < MHLEN) 249 MH_ALIGN(m, len); 250 m->m_len = len; 251 return (m); 252 } 253 254 /* 255 * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 256 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 257 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 258 */ 259 int MCFail; 260 261 struct mbuf * 262 m_copym(m, off0, len, wait) 263 register struct mbuf *m; 264 int off0, wait; 265 register int len; 266 { 267 register struct mbuf *n, **np; 268 register int off = off0; 269 struct mbuf *top; 270 int copyhdr = 0; 271 272 if (off < 0 || len < 0) 273 panic("m_copym"); 274 if (off == 0 && m->m_flags & M_PKTHDR) 275 copyhdr = 1; 276 while (off > 0) { 277 if (m == 0) 278 panic("m_copym"); 279 if (off < m->m_len) 280 break; 281 off -= m->m_len; 282 m = m->m_next; 283 } 284 np = ⊤ 285 top = 0; 286 while (len > 0) { 287 if (m == 0) { 288 if (len != M_COPYALL) 289 panic("m_copym"); 290 break; 291 } 292 MGET(n, wait, m->m_type); 293 *np = n; 294 if (n == 0) 295 goto nospace; 296 if (copyhdr) { 297 M_COPY_PKTHDR(n, m); 298 if (len == M_COPYALL) 299 n->m_pkthdr.len -= off0; 300 else 301 n->m_pkthdr.len = len; 302 copyhdr = 0; 303 } 304 n->m_len = min(len, m->m_len - off); 305 if (m->m_flags & M_EXT) { 306 n->m_data = m->m_data + off; 307 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 308 n->m_ext = m->m_ext; 309 n->m_flags |= M_EXT; 310 } else 311 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 312 (unsigned)n->m_len); 313 if (len != M_COPYALL) 314 len -= n->m_len; 315 off = 0; 316 m = m->m_next; 317 np = &n->m_next; 318 } 319 if (top == 0) 320 MCFail++; 321 return (top); 322 nospace: 323 m_freem(top); 324 MCFail++; 325 return (0); 326 } 327 328 /* 329 * Copy data from an mbuf chain starting "off" bytes from the beginning, 330 * continuing for "len" bytes, into the indicated buffer. 331 */ 332 void 333 m_copydata(m, off, len, cp) 334 register struct mbuf *m; 335 register int off; 336 register int len; 337 caddr_t cp; 338 { 339 register unsigned count; 340 341 if (off < 0 || len < 0) 342 panic("m_copydata"); 343 while (off > 0) { 344 if (m == 0) 345 panic("m_copydata"); 346 if (off < m->m_len) 347 break; 348 off -= m->m_len; 349 m = m->m_next; 350 } 351 while (len > 0) { 352 if (m == 0) 353 panic("m_copydata"); 354 count = min(m->m_len - off, len); 355 bcopy(mtod(m, caddr_t) + off, cp, count); 356 len -= count; 357 cp += count; 358 off = 0; 359 m = m->m_next; 360 } 361 } 362 363 /* 364 * Concatenate mbuf chain n to m. 365 * Both chains must be of the same type (e.g. MT_DATA). 366 * Any m_pkthdr is not updated. 367 */ 368 void 369 m_cat(m, n) 370 register struct mbuf *m, *n; 371 { 372 while (m->m_next) 373 m = m->m_next; 374 while (n) { 375 if (m->m_flags & M_EXT || 376 m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 377 /* just join the two chains */ 378 m->m_next = n; 379 return; 380 } 381 /* splat the data from one into the other */ 382 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 383 (u_int)n->m_len); 384 m->m_len += n->m_len; 385 n = m_free(n); 386 } 387 } 388 389 void 390 m_adj(mp, req_len) 391 struct mbuf *mp; 392 int req_len; 393 { 394 register int len = req_len; 395 register struct mbuf *m; 396 register count; 397 398 if ((m = mp) == NULL) 399 return; 400 if (len >= 0) { 401 /* 402 * Trim from head. 403 */ 404 while (m != NULL && len > 0) { 405 if (m->m_len <= len) { 406 len -= m->m_len; 407 m->m_len = 0; 408 m = m->m_next; 409 } else { 410 m->m_len -= len; 411 m->m_data += len; 412 len = 0; 413 } 414 } 415 m = mp; 416 if (mp->m_flags & M_PKTHDR) 417 m->m_pkthdr.len -= (req_len - len); 418 } else { 419 /* 420 * Trim from tail. Scan the mbuf chain, 421 * calculating its length and finding the last mbuf. 422 * If the adjustment only affects this mbuf, then just 423 * adjust and return. Otherwise, rescan and truncate 424 * after the remaining size. 425 */ 426 len = -len; 427 count = 0; 428 for (;;) { 429 count += m->m_len; 430 if (m->m_next == (struct mbuf *)0) 431 break; 432 m = m->m_next; 433 } 434 if (m->m_len >= len) { 435 m->m_len -= len; 436 if (mp->m_flags & M_PKTHDR) 437 mp->m_pkthdr.len -= len; 438 return; 439 } 440 count -= len; 441 if (count < 0) 442 count = 0; 443 /* 444 * Correct length for chain is "count". 445 * Find the mbuf with last data, adjust its length, 446 * and toss data from remaining mbufs on chain. 447 */ 448 m = mp; 449 if (m->m_flags & M_PKTHDR) 450 m->m_pkthdr.len = count; 451 for (; m; m = m->m_next) { 452 if (m->m_len >= count) { 453 m->m_len = count; 454 break; 455 } 456 count -= m->m_len; 457 } 458 while (m = m->m_next) 459 m->m_len = 0; 460 } 461 } 462 463 /* 464 * Rearange an mbuf chain so that len bytes are contiguous 465 * and in the data area of an mbuf (so that mtod and dtom 466 * will work for a structure of size len). Returns the resulting 467 * mbuf chain on success, frees it and returns null on failure. 468 * If there is room, it will add up to max_protohdr-len extra bytes to the 469 * contiguous region in an attempt to avoid being called next time. 470 */ 471 int MPFail; 472 473 struct mbuf * 474 m_pullup(n, len) 475 register struct mbuf *n; 476 int len; 477 { 478 register struct mbuf *m; 479 register int count; 480 int space; 481 482 /* 483 * If first mbuf has no cluster, and has room for len bytes 484 * without shifting current data, pullup into it, 485 * otherwise allocate a new mbuf to prepend to the chain. 486 */ 487 if ((n->m_flags & M_EXT) == 0 && 488 n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 489 if (n->m_len >= len) 490 return (n); 491 m = n; 492 n = n->m_next; 493 len -= m->m_len; 494 } else { 495 if (len > MHLEN) 496 goto bad; 497 MGET(m, M_DONTWAIT, n->m_type); 498 if (m == 0) 499 goto bad; 500 m->m_len = 0; 501 if (n->m_flags & M_PKTHDR) { 502 M_COPY_PKTHDR(m, n); 503 n->m_flags &= ~M_PKTHDR; 504 } 505 } 506 space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 507 do { 508 count = min(min(max(len, max_protohdr), space), n->m_len); 509 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 510 (unsigned)count); 511 len -= count; 512 m->m_len += count; 513 n->m_len -= count; 514 space -= count; 515 if (n->m_len) 516 n->m_data += count; 517 else 518 n = m_free(n); 519 } while (len > 0 && n); 520 if (len > 0) { 521 (void) m_free(m); 522 goto bad; 523 } 524 m->m_next = n; 525 return (m); 526 bad: 527 m_freem(n); 528 MPFail++; 529 return (0); 530 } 531 532 /* 533 * Partition an mbuf chain in two pieces, returning the tail -- 534 * all but the first len0 bytes. In case of failure, it returns NULL and 535 * attempts to restore the chain to its original state. 536 */ 537 struct mbuf * 538 m_split(m0, len0, wait) 539 register struct mbuf *m0; 540 int len0, wait; 541 { 542 register struct mbuf *m, *n; 543 unsigned len = len0, remain; 544 545 for (m = m0; m && len > m->m_len; m = m->m_next) 546 len -= m->m_len; 547 if (m == 0) 548 return (0); 549 remain = m->m_len - len; 550 if (m0->m_flags & M_PKTHDR) { 551 MGETHDR(n, wait, m0->m_type); 552 if (n == 0) 553 return (0); 554 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 555 n->m_pkthdr.len = m0->m_pkthdr.len - len0; 556 m0->m_pkthdr.len = len0; 557 if (m->m_flags & M_EXT) 558 goto extpacket; 559 if (remain > MHLEN) { 560 /* m can't be the lead packet */ 561 MH_ALIGN(n, 0); 562 n->m_next = m_split(m, len, wait); 563 if (n->m_next == 0) { 564 (void) m_free(n); 565 return (0); 566 } else 567 return (n); 568 } else 569 MH_ALIGN(n, remain); 570 } else if (remain == 0) { 571 n = m->m_next; 572 m->m_next = 0; 573 return (n); 574 } else { 575 MGET(n, wait, m->m_type); 576 if (n == 0) 577 return (0); 578 M_ALIGN(n, remain); 579 } 580 extpacket: 581 if (m->m_flags & M_EXT) { 582 n->m_flags |= M_EXT; 583 n->m_ext = m->m_ext; 584 mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 585 m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ 586 n->m_data = m->m_data + len; 587 } else { 588 bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); 589 } 590 n->m_len = remain; 591 m->m_len = len; 592 n->m_next = m->m_next; 593 m->m_next = 0; 594 return (n); 595 } 596 /* 597 * Routine to copy from device local memory into mbufs. 598 */ 599 struct mbuf * 600 m_devget(buf, totlen, off0, ifp, copy) 601 char *buf; 602 int totlen, off0; 603 struct ifnet *ifp; 604 void (*copy)(); 605 { 606 register struct mbuf *m; 607 struct mbuf *top = 0, **mp = ⊤ 608 register int off = off0, len; 609 register char *cp; 610 char *epkt; 611 612 cp = buf; 613 epkt = cp + totlen; 614 if (off) { 615 cp += off + 2 * sizeof(u_short); 616 totlen -= 2 * sizeof(u_short); 617 } 618 MGETHDR(m, M_DONTWAIT, MT_DATA); 619 if (m == 0) 620 return (0); 621 m->m_pkthdr.rcvif = ifp; 622 m->m_pkthdr.len = totlen; 623 m->m_len = MHLEN; 624 625 while (totlen > 0) { 626 if (top) { 627 MGET(m, M_DONTWAIT, MT_DATA); 628 if (m == 0) { 629 m_freem(top); 630 return (0); 631 } 632 m->m_len = MLEN; 633 } 634 len = min(totlen, epkt - cp); 635 if (len >= MINCLSIZE) { 636 MCLGET(m, M_DONTWAIT); 637 if (m->m_flags & M_EXT) 638 m->m_len = len = min(len, MCLBYTES); 639 else 640 len = m->m_len; 641 } else { 642 /* 643 * Place initial small packet/header at end of mbuf. 644 */ 645 if (len < m->m_len) { 646 if (top == 0 && len + max_linkhdr <= m->m_len) 647 m->m_data += max_linkhdr; 648 m->m_len = len; 649 } else 650 len = m->m_len; 651 } 652 if (copy) 653 copy(cp, mtod(m, caddr_t), (unsigned)len); 654 else 655 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 656 cp += len; 657 *mp = m; 658 mp = &m->m_next; 659 totlen -= len; 660 if (cp == epkt) 661 cp = buf; 662 } 663 return (top); 664 } 665