|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1982, 1986, 1988, 1991, 1993
25: * The Regents of the University of California. All rights reserved.
26: *
27: * Redistribution and use in source and binary forms, with or without
28: * modification, are permitted provided that the following conditions
29: * are met:
30: * 1. Redistributions of source code must retain the above copyright
31: * notice, this list of conditions and the following disclaimer.
32: * 2. Redistributions in binary form must reproduce the above copyright
33: * notice, this list of conditions and the following disclaimer in the
34: * documentation and/or other materials provided with the distribution.
35: * 3. All advertising materials mentioning features or use of this software
36: * must display the following acknowledgement:
37: * This product includes software developed by the University of
38: * California, Berkeley and its contributors.
39: * 4. Neither the name of the University nor the names of its contributors
40: * may be used to endorse or promote products derived from this software
41: * without specific prior written permission.
42: *
43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53: * SUCH DAMAGE.
54: *
55: * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
56: */
57: /* HISTORY
58: *
59: * 10/15/97 Annette DeSchon ([email protected])
60: * Fixed bug in which all cluster mbufs were broken up
61: * into regular mbufs: Some clusters are now reserved.
62: * When a cluster is needed, regular mbufs are no longer
63: * used. (Radar 1683621)
64: * 20-May-95 Mac Gillon (mgillon) at NeXT
65: * New version based on 4.4
66: */
67:
68: #include <sys/param.h>
69: #include <sys/systm.h>
70: #include <sys/malloc.h>
71: #include <sys/mbuf.h>
72: #include <sys/kernel.h>
73: #include <sys/syslog.h>
74: #include <sys/protosw.h>
75: #include <sys/domain.h>
76: #include <net/netisr.h>
77:
78: #include <kern/queue.h>
79:
80: extern kernel_pmap; /* The kernel's pmap */
81:
82: struct mbuf *mfree; /* mbuf free list */
83: struct mbuf *mfreelater; /* mbuf deallocation list */
84: extern vm_map_t mb_map; /* special map */
85: int m_want; /* sleepers on mbufs */
86: extern int nmbclusters; /* max number of mapped clusters */
87: short *mclrefcnt; /* mapped cluster reference counts */
88: int *mcl_paddr;
89: union mcluster *mclfree; /* mapped cluster free list */
90: int max_linkhdr; /* largest link-level header */
91: int max_protohdr; /* largest protocol header */
92: int max_hdr; /* largest link+protocol header */
93: int max_datalen; /* MHLEN - max_hdr */
94: struct mbstat mbstat; /* statistics */
95: union mcluster *mbutl; /* first mapped cluster address */
96: union mcluster *embutl; /* ending virtual address of mclusters */
97:
98: static int nclpp; /* # clusters per physical page */
99: static char mbfail[] = "mbuf not mapped";
100:
101: static int m_howmany();
102:
103: /* The number of cluster mbufs that are allocated, to start. */
104: #define MINCL max(16, 2)
105:
106: void
107: mbinit()
108: {
109: int s,m;
110:
111: if (nclpp)
112: return;
113: s = splimp();
114: nclpp = round_page(MCLBYTES) / MCLBYTES; /* see mbufgc() */
115: if (nclpp < 1) nclpp = 1;
116: MBUF_LOCKINIT();
117: // NETISR_LOCKINIT();
118: if (nmbclusters == 0)
119: nmbclusters = NMBCLUSTERS;
120: MALLOC(mclrefcnt, short *, nmbclusters * sizeof (short),
121: M_TEMP, M_WAITOK);
122: if (mclrefcnt == 0)
123: panic("mbinit");
124: for (m = 0; m < nmbclusters; m++)
125: mclrefcnt[m] = -1;
126:
127: MALLOC(mcl_paddr, int *, (nmbclusters/(PAGE_SIZE/CLBYTES)) * sizeof (int),
128: M_TEMP, M_WAITOK);
129: if (mcl_paddr == 0)
130: panic("mbinit1");
131: bzero((char *)mcl_paddr, (nmbclusters/(PAGE_SIZE/CLBYTES)) * sizeof (int));
132:
133: embutl = (union mcluster *)((unsigned char *)mbutl + (nmbclusters * MCLBYTES));
134:
135:
136: MBUF_LOCK();
137: if (m_clalloc(max(PAGE_SIZE/CLBYTES, 1) * 10, M_DONTWAIT) == 0)
138: goto bad;
139: MBUF_UNLOCK();
140: splx(s);
141: return;
142: bad:
143: panic("mbinit");
144: }
145:
146: /*
147: * Allocate some number of mbuf clusters
148: * and place on cluster free list.
149: * Must be called at splimp.
150: */
151: /* ARGSUSED */
152: m_clalloc(ncl, nowait)
153: register int ncl;
154: int nowait;
155: {
156: register union mcluster *mcl;
157: register int i;
158: vm_size_t size;
159: static char doing_alloc;
160:
161: if (doing_alloc || (i = m_howmany()) <= 0)
162: goto out;
163: doing_alloc = 1;
164: MBUF_UNLOCK();
165:
166: if (ncl < i) ncl = i;
167: size = round_page(ncl * MCLBYTES);
168: mcl = (union mcluster *)kmem_mb_alloc(mb_map, size);
169: if (mcl == 0 && ncl > 1) {
170: size = round_page(MCLBYTES); /* Try for 1 if failed */
171: mcl = (union mcluster *)kmem_mb_alloc(mb_map, size);
172: }
173: MBUF_LOCK();
174: doing_alloc = 0;
175: if (mcl) {
176: ncl = size / MCLBYTES;
177: for (i = 0; i < ncl; i++) {
178: if (++mclrefcnt[mtocl(mcl)] != 0)
179: panic("m_clalloc already there");
180: if (((int)mcl & PAGE_MASK) == 0)
181: mcl_paddr[((char *)mcl - (char *)mbutl)/PAGE_SIZE] = pmap_extract(kernel_pmap, (char *)mcl);
182:
183: mcl->mcl_next = mclfree;
184: mclfree = mcl++;
185: }
186: mbstat.m_clfree += ncl;
187: mbstat.m_clusters += ncl;
188: return (ncl);
189: } /* else ... */
190: out:
191: if (mclfree)
192: return 1;
193: mbstat.m_drops++;
194: return 0;
195: }
196:
197: /*
198: * Add more free mbufs by cutting up a cluster.
199: */
200: m_expand(canwait)
201: int canwait;
202: {
203: register caddr_t mcl;
204:
205: if (mbstat.m_clfree < (mbstat.m_clusters >> 4))
206: /* 1/16th of the total number of cluster mbufs allocated is
207: reserved for large packets. The number reserved must
208: always be < 1/2, or future allocation will be prevented.
209: */
210: return 0;
211:
212: MCLALLOC(mcl, canwait);
213: if (mcl) {
214: register struct mbuf *m = (struct mbuf *)mcl;
215: register int i = NMBPCL;
216: int s = splimp();
217: MBUF_LOCK();
218: mbstat.m_mtypes[MT_FREE] += i;
219: mbstat.m_mbufs += i;
220: while (i--) {
221: m->m_type = MT_FREE;
222: m->m_next = mfree;
223: mfree = m++;
224: }
225: i = m_want;
226: m_want = 0;
227: MBUF_UNLOCK();
228: splx(s);
229: if (i) wakeup((caddr_t)&mfree);
230: return 1;
231: }
232: return 0;
233: }
234:
235: /*
236: * When MGET failes, ask protocols to free space when short of memory,
237: * then re-attempt to allocate an mbuf.
238: */
239: struct mbuf *
240: m_retry(canwait, type)
241: int canwait, type;
242: {
243: #define m_retry(h, t) 0
244: register struct mbuf *m;
245: int wait, s;
246:
247: for (;;) {
248: (void) m_expand(canwait);
249: MGET(m, XXX, type);
250: if (m || canwait == M_DONTWAIT)
251: break;
252: s = splimp();
253: MBUF_LOCK();
254: wait = m_want++;
255: if (wait == 0)
256: mbstat.m_drain++;
257: else {
258: assert_wait((caddr_t)&mfree, THREAD_UNINT);
259: mbstat.m_wait++;
260: }
261: MBUF_UNLOCK();
262: if (wait == 0) {
263: splx(s);
264: m_reclaim();
265: } else {
266: /* Sleep with a small timeout as insurance */
267: (void) tsleep((caddr_t)0, PZERO-1, "m_retry", hz);
268: splx(s);
269: }
270: }
271: return (m);
272: #undef m_retry
273: }
274:
275: /*
276: * As above; retry an MGETHDR.
277: */
278: struct mbuf *
279: m_retryhdr(canwait, type)
280: int canwait, type;
281: {
282: register struct mbuf *m;
283:
284: if (m = m_retry(canwait, type)) {
285: m->m_flags |= M_PKTHDR;
286: m->m_data = m->m_pktdat;
287: }
288: return (m);
289: }
290:
291: m_reclaim()
292: {
293: register struct domain *dp;
294: register struct protosw *pr;
295: int s = splimp();
296:
297: for (dp = domains; dp; dp = dp->dom_next)
298: for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
299: if (pr->pr_drain)
300: (*pr->pr_drain)();
301: splx(s);
302: mbstat.m_drain++;
303: }
304:
305: /*
306: * Space allocation routines.
307: * These are also available as macros
308: * for critical paths.
309: */
310: struct mbuf *
311: m_get(nowait, type)
312: int nowait, type;
313: {
314: register struct mbuf *m;
315:
316: MGET(m, nowait, type);
317: return (m);
318: }
319:
320: struct mbuf *
321: m_gethdr(nowait, type)
322: int nowait, type;
323: {
324: register struct mbuf *m;
325:
326: MGETHDR(m, nowait, type);
327: return (m);
328: }
329:
330: struct mbuf *
331: m_getclr(nowait, type)
332: int nowait, type;
333: {
334: register struct mbuf *m;
335:
336: MGET(m, nowait, type);
337: if (m == 0)
338: return (0);
339: bzero(mtod(m, caddr_t), MLEN);
340: return (m);
341: }
342:
343: struct mbuf *
344: m_free(m)
345: struct mbuf *m;
346: {
347: struct mbuf *n = m->m_next;
348: int i, s;
349:
350: if (m->m_type == MT_FREE)
351: panic("freeing free mbuf");
352: s = splimp();
353: MBUF_LOCK();
354: if (m->m_flags & M_EXT) {
355: if (MCLHASREFERENCE(m)) {
356: remque((queue_t)&m->m_ext.ext_refs);
357: } else if (m->m_ext.ext_free == NULL) {
358: union mcluster *mcl= (union mcluster *)m->m_ext.ext_buf;
359: if (MCLUNREF(mcl)) {
360: mcl->mcl_next = mclfree;
361: mclfree = mcl;
362: ++mbstat.m_clfree;
363: } else /* sanity check - not referenced this way */
364: panic("m_free m_ext cluster not free");
365: } else {
366: (*(m->m_ext.ext_free))(m->m_ext.ext_buf,
367: m->m_ext.ext_size, m->m_ext.ext_arg);
368: }
369: }
370: mbstat.m_mtypes[m->m_type]--;
371: (void) MCLUNREF(m);
372: m->m_type = MT_FREE;
373: mbstat.m_mtypes[m->m_type]++;
374: m->m_flags = 0;
375: m->m_next = mfree;
376: m->m_len = 0;
377: mfree = m;
378: i = m_want;
379: m_want = 0;
380: MBUF_UNLOCK();
381: splx(s);
382: if (i) wakeup((caddr_t)&mfree);
383: return (n);
384: }
385:
386: void
387: m_freem(m)
388: register struct mbuf *m;
389: {
390: while (m)
391: m = m_free(m);
392: }
393:
394: /*
395: * Mbuffer utility routines.
396: */
397: /*
398: * Compute the amount of space available
399: * before the current start of data in an mbuf.
400: */
401: m_leadingspace(m)
402: register struct mbuf *m;
403: {
404: if (m->m_flags & M_EXT) {
405: if (MCLHASREFERENCE(m))
406: return(0);
407: return (m->m_data - m->m_ext.ext_buf);
408: }
409: if (m->m_flags & M_PKTHDR)
410: return (m->m_data - m->m_pktdat);
411: return (m->m_data - m->m_dat);
412: }
413:
414: /*
415: * Compute the amount of space available
416: * after the end of data in an mbuf.
417: */
418: m_trailingspace(m)
419: register struct mbuf *m;
420: {
421: if (m->m_flags & M_EXT) {
422: if (MCLHASREFERENCE(m))
423: return(0);
424: return (m->m_ext.ext_buf + m->m_ext.ext_size -
425: (m->m_data + m->m_len));
426: }
427: return (&m->m_dat[MLEN] - (m->m_data + m->m_len));
428: }
429:
430: /*
431: * Lesser-used path for M_PREPEND:
432: * allocate new mbuf to prepend to chain,
433: * copy junk along.
434: */
435: struct mbuf *
436: m_prepend(m, len, how)
437: register struct mbuf *m;
438: int len, how;
439: {
440: struct mbuf *mn;
441:
442: MGET(mn, how, m->m_type);
443: if (mn == (struct mbuf *)NULL) {
444: m_freem(m);
445: return ((struct mbuf *)NULL);
446: }
447: if (m->m_flags & M_PKTHDR) {
448: M_COPY_PKTHDR(mn, m);
449: m->m_flags &= ~M_PKTHDR;
450: }
451: mn->m_next = m;
452: m = mn;
453: if (len < MHLEN)
454: MH_ALIGN(m, len);
455: m->m_len = len;
456: return (m);
457: }
458:
459: /*
460: * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
461: * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
462: * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
463: */
464: int MCFail;
465:
466: struct mbuf *
467: m_copym(m, off0, len, wait)
468: register struct mbuf *m;
469: int off0, wait;
470: register int len;
471: {
472: register struct mbuf *n, **np;
473: register int off = off0;
474: struct mbuf *top;
475: int copyhdr = 0;
476:
477: if (off < 0 || len < 0)
478: panic("m_copym");
479: if (off == 0 && m->m_flags & M_PKTHDR)
480: copyhdr = 1;
481: while (off > 0) {
482: if (m == 0)
483: panic("m_copym");
484: if (off < m->m_len)
485: break;
486: off -= m->m_len;
487: m = m->m_next;
488: }
489: np = ⊤
490: top = 0;
491: while (len > 0) {
492: if (m == 0) {
493: if (len != M_COPYALL)
494: panic("m_copym");
495: break;
496: }
497: MGET(n, wait, m->m_type);
498: *np = n;
499: if (n == 0)
500: goto nospace;
501: if (copyhdr) {
502: M_COPY_PKTHDR(n, m);
503: if (len == M_COPYALL)
504: n->m_pkthdr.len -= off0;
505: else
506: n->m_pkthdr.len = len;
507: copyhdr = 0;
508: }
509: if (len == M_COPYALL) {
510: if (min(len, (m->m_len - off)) == len) {
511: printf("m->m_len %d - off %d = %d, %d\n",
512: m->m_len, off, m->m_len - off,
513: min(len, (m->m_len - off)));
514: }
515: }
516: n->m_len = min(len, (m->m_len - off));
517: if (n->m_len == M_COPYALL) {
518: printf("n->m_len == M_COPYALL, fixing\n");
519: n->m_len = MHLEN;
520: }
521: if (m->m_flags & M_EXT) {
522: int s = splimp();
523: MBUF_LOCK();
524: n->m_ext = m->m_ext;
525: insque((queue_t)&n->m_ext.ext_refs, (queue_t)&m->m_ext.ext_refs);
526: MBUF_UNLOCK();
527: splx(s);
528: n->m_data = m->m_data + off;
529: n->m_flags |= M_EXT;
530: } else
531: bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
532: (unsigned)n->m_len);
533: if (len != M_COPYALL)
534: len -= n->m_len;
535: off = 0;
536: m = m->m_next;
537: np = &n->m_next;
538: }
539: if (top == 0)
540: MCFail++;
541: return (top);
542: nospace:
543: m_freem(top);
544: MCFail++;
545: return (0);
546: }
547:
548: /*
549: * Copy data from an mbuf chain starting "off" bytes from the beginning,
550: * continuing for "len" bytes, into the indicated buffer.
551: */
552: void m_copydata(m, off, len, cp)
553: register struct mbuf *m;
554: register int off;
555: register int len;
556: caddr_t cp;
557: {
558: register unsigned count;
559:
560: if (off < 0 || len < 0)
561: panic("m_copydata");
562: while (off > 0) {
563: if (m == 0)
564: panic("m_copydata");
565: if (off < m->m_len)
566: break;
567: off -= m->m_len;
568: m = m->m_next;
569: }
570: while (len > 0) {
571: if (m == 0)
572: panic("m_copydata");
573: count = min(m->m_len - off, len);
574: bcopy(mtod(m, caddr_t) + off, cp, count);
575: len -= count;
576: cp += count;
577: off = 0;
578: m = m->m_next;
579: }
580: }
581:
582: /*
583: * Concatenate mbuf chain n to m.
584: * Both chains must be of the same type (e.g. MT_DATA).
585: * Any m_pkthdr is not updated.
586: */
587: void m_cat(m, n)
588: register struct mbuf *m, *n;
589: {
590: while (m->m_next)
591: m = m->m_next;
592: while (n) {
593: if (m->m_flags & M_EXT ||
594: m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
595: /* just join the two chains */
596: m->m_next = n;
597: return;
598: }
599: /* splat the data from one into the other */
600: bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
601: (u_int)n->m_len);
602: m->m_len += n->m_len;
603: n = m_free(n);
604: }
605: }
606:
607: void
608: m_adj(mp, req_len)
609: struct mbuf *mp;
610: int req_len;
611: {
612: register int len = req_len;
613: register struct mbuf *m;
614: register count;
615:
616: if ((m = mp) == NULL)
617: return;
618: if (len >= 0) {
619: /*
620: * Trim from head.
621: */
622: while (m != NULL && len > 0) {
623: if (m->m_len <= len) {
624: len -= m->m_len;
625: m->m_len = 0;
626: m = m->m_next;
627: } else {
628: m->m_len -= len;
629: m->m_data += len;
630: len = 0;
631: }
632: }
633: m = mp;
634: if (m->m_flags & M_PKTHDR)
635: m->m_pkthdr.len -= (req_len - len);
636: } else {
637: /*
638: * Trim from tail. Scan the mbuf chain,
639: * calculating its length and finding the last mbuf.
640: * If the adjustment only affects this mbuf, then just
641: * adjust and return. Otherwise, rescan and truncate
642: * after the remaining size.
643: */
644: len = -len;
645: count = 0;
646: for (;;) {
647: count += m->m_len;
648: if (m->m_next == (struct mbuf *)0)
649: break;
650: m = m->m_next;
651: }
652: if (m->m_len >= len) {
653: m->m_len -= len;
654: m = mp;
655: if (m->m_flags & M_PKTHDR)
656: m->m_pkthdr.len -= len;
657: return;
658: }
659: count -= len;
660: if (count < 0)
661: count = 0;
662: /*
663: * Correct length for chain is "count".
664: * Find the mbuf with last data, adjust its length,
665: * and toss data from remaining mbufs on chain.
666: */
667: m = mp;
668: if (m->m_flags & M_PKTHDR)
669: m->m_pkthdr.len = count;
670: for (; m; m = m->m_next) {
671: if (m->m_len >= count) {
672: m->m_len = count;
673: break;
674: }
675: count -= m->m_len;
676: }
677: while (m = m->m_next)
678: m->m_len = 0;
679: }
680: }
681:
682: /*
683: * Rearange an mbuf chain so that len bytes are contiguous
684: * and in the data area of an mbuf (so that mtod and dtom
685: * will work for a structure of size len). Returns the resulting
686: * mbuf chain on success, frees it and returns null on failure.
687: * If there is room, it will add up to max_protohdr-len extra bytes to the
688: * contiguous region in an attempt to avoid being called next time.
689: */
690: int MPFail;
691:
692: struct mbuf *
693: m_pullup(n, len)
694: register struct mbuf *n;
695: int len;
696: {
697: register struct mbuf *m;
698: register int count;
699: int space;
700:
701: /*
702: * If first mbuf has no cluster, and has room for len bytes
703: * without shifting current data, pullup into it,
704: * otherwise allocate a new mbuf to prepend to the chain.
705: */
706: if ((n->m_flags & M_EXT) == 0 &&
707: n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
708: if (n->m_len >= len)
709: return (n);
710: m = n;
711: n = n->m_next;
712: len -= m->m_len;
713: } else {
714: if (len > MHLEN)
715: goto bad;
716: MGET(m, M_DONTWAIT, n->m_type);
717: if (m == 0)
718: goto bad;
719: m->m_len = 0;
720: if (n->m_flags & M_PKTHDR) {
721: M_COPY_PKTHDR(m, n);
722: n->m_flags &= ~M_PKTHDR;
723: }
724: }
725: space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
726: do {
727: count = min(min(max(len, max_protohdr), space), n->m_len);
728: bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
729: (unsigned)count);
730: len -= count;
731: m->m_len += count;
732: n->m_len -= count;
733: space -= count;
734: if (n->m_len)
735: n->m_data += count;
736: else
737: n = m_free(n);
738: } while (len > 0 && n);
739: if (len > 0) {
740: (void) m_free(m);
741: goto bad;
742: }
743: m->m_next = n;
744: return (m);
745: bad:
746: m_freem(n);
747: MPFail++;
748: return (0);
749: }
750:
751: /*
752: * Partition an mbuf chain in two pieces, returning the tail --
753: * all but the first len0 bytes. In case of failure, it returns NULL and
754: * attempts to restore the chain to its original state.
755: */
756: struct mbuf *
757: m_split(m0, len0, wait)
758: register struct mbuf *m0;
759: int len0, wait;
760: {
761: register struct mbuf *m, *n;
762: unsigned len = len0, remain;
763:
764: for (m = m0; m && len > m->m_len; m = m->m_next)
765: len -= m->m_len;
766: if (m == 0)
767: return (0);
768: remain = m->m_len - len;
769: if (m0->m_flags & M_PKTHDR) {
770: MGETHDR(n, wait, m0->m_type);
771: if (n == 0)
772: return (0);
773: n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
774: n->m_pkthdr.len = m0->m_pkthdr.len - len0;
775: m0->m_pkthdr.len = len0;
776: if (m->m_flags & M_EXT)
777: goto extpacket;
778: if (remain > MHLEN) {
779: /* m can't be the lead packet */
780: MH_ALIGN(n, 0);
781: n->m_next = m_split(m, len, wait);
782: if (n->m_next == 0) {
783: (void) m_free(n);
784: return (0);
785: } else
786: return (n);
787: } else
788: MH_ALIGN(n, remain);
789: } else if (remain == 0) {
790: n = m->m_next;
791: m->m_next = 0;
792: return (n);
793: } else {
794: MGET(n, wait, m->m_type);
795: if (n == 0)
796: return (0);
797: M_ALIGN(n, remain);
798: }
799: extpacket:
800: if (m->m_flags & M_EXT) {
801: n->m_flags |= M_EXT;
802: n->m_ext = m->m_ext;
803: mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
804: m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
805: n->m_data = m->m_data + len;
806: } else {
807: bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
808: }
809: n->m_len = remain;
810: m->m_len = len;
811: n->m_next = m->m_next;
812: m->m_next = 0;
813: return (n);
814: }
815: /*
816: * Routine to copy from device local memory into mbufs.
817: */
818: struct mbuf *
819: m_devget(buf, totlen, off0, ifp, copy)
820: char *buf;
821: int totlen, off0;
822: struct ifnet *ifp;
823: void (*copy)();
824: {
825: register struct mbuf *m;
826: struct mbuf *top = 0, **mp = ⊤
827: register int off = off0, len;
828: register char *cp;
829: char *epkt;
830:
831: cp = buf;
832: epkt = cp + totlen;
833: if (off) {
834: /*
835: * If 'off' is non-zero, packet is trailer-encapsulated,
836: * so we have to skip the type and length fields.
837: */
838: cp += off + 2 * sizeof(u_int16_t);
839: totlen -= 2 * sizeof(u_int16_t);
840: }
841: MGETHDR(m, M_DONTWAIT, MT_DATA);
842: if (m == 0)
843: return (0);
844: m->m_pkthdr.rcvif = ifp;
845: m->m_pkthdr.len = totlen;
846: m->m_len = MHLEN;
847:
848: while (totlen > 0) {
849: if (top) {
850: MGET(m, M_DONTWAIT, MT_DATA);
851: if (m == 0) {
852: m_freem(top);
853: return (0);
854: }
855: m->m_len = MLEN;
856: }
857: len = min(totlen, epkt - cp);
858: if (len >= MINCLSIZE) {
859: MCLGET(m, M_DONTWAIT);
860: if (m->m_flags & M_EXT)
861: m->m_len = len = min(len, MCLBYTES);
862: else {
863: /* give up when it's out of cluster mbufs */
864: if (top)
865: m_freem(top);
866: m_freem(m);
867: return (0);
868: }
869: } else {
870: /*
871: * Place initial small packet/header at end of mbuf.
872: */
873: if (len < m->m_len) {
874: if (top == 0 && len + max_linkhdr <= m->m_len)
875: m->m_data += max_linkhdr;
876: m->m_len = len;
877: } else
878: len = m->m_len;
879: }
880: if (copy)
881: copy(cp, mtod(m, caddr_t), (unsigned)len);
882: else
883: bcopy(cp, mtod(m, caddr_t), (unsigned)len);
884: cp += len;
885: *mp = m;
886: mp = &m->m_next;
887: totlen -= len;
888: if (cp == epkt)
889: cp = buf;
890: }
891: return (top);
892: }
893:
894: /*
895: * Cluster freelist allocation check. Mbuf lock/splimp must be held.
896: * Ensure hysteresis between hi/lo.
897: */
898: static int
899: m_howmany()
900: {
901: register int i;
902:
903: /* Under minimum */
904: if (mbstat.m_clusters < MINCL)
905: return (MINCL - mbstat.m_clusters);
906: /* Too few (free < 1/2 total) and not over maximum */
907: if (mbstat.m_clusters < nmbclusters &&
908: (i = ((mbstat.m_clusters >> 1) - mbstat.m_clfree)) > 0)
909: return i;
910: return 0;
911: }
912:
913:
914: /*
915: * Copy data from a buffer back into the indicated mbuf chain,
916: * starting "off" bytes from the beginning, extending the mbuf
917: * chain if necessary.
918: */
919: void
920: m_copyback(m0, off, len, cp)
921: struct mbuf *m0;
922: register int off;
923: register int len;
924: caddr_t cp;
925: {
926: register int mlen;
927: register struct mbuf *m = m0, *n;
928: int totlen = 0;
929:
930: if (m0 == 0)
931: return;
932: while (off > (mlen = m->m_len)) {
933: off -= mlen;
934: totlen += mlen;
935: if (m->m_next == 0) {
936: n = m_getclr(M_DONTWAIT, m->m_type);
937: if (n == 0)
938: goto out;
939: n->m_len = min(MLEN, len + off);
940: m->m_next = n;
941: }
942: m = m->m_next;
943: }
944: while (len > 0) {
945: mlen = min (m->m_len - off, len);
946: bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
947: cp += mlen;
948: len -= mlen;
949: mlen += off;
950: off = 0;
951: totlen += mlen;
952: if (len == 0)
953: break;
954: if (m->m_next == 0) {
955: n = m_get(M_DONTWAIT, m->m_type);
956: if (n == 0)
957: break;
958: n->m_len = min(MLEN, len);
959: m->m_next = n;
960: }
961: m = m->m_next;
962: }
963: out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
964: m->m_pkthdr.len = totlen;
965: }
966:
967:
968: char *mcl_to_paddr(register char *addr) {
969: register int base_phys;
970:
971: if (addr < (char *)mbutl || addr >= (char *)embutl)
972: return (0);
973: base_phys = mcl_paddr[(addr - (char *)mbutl) >> PAGE_SHIFT];
974:
975: if (base_phys == 0)
976: return (0);
977: return ((char *)((int)base_phys | ((int)addr & PAGE_MASK)));
978: }
979:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.