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