Annotation of XNU/bsd/kern/uipc_mbuf.c, revision 1.1.1.1

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 = &top;
                    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 = &top;
                    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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.