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

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

unix.superglobalmegacorp.com

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