OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [kern/] [uipc_mbuf.c] - Diff between revs 30 and 173

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 30 Rev 173
/*
/*
 * Copyright (c) 1982, 1986, 1988, 1991, 1993
 * Copyright (c) 1982, 1986, 1988, 1991, 1993
 *      The Regents of the University of California.  All rights reserved.
 *      The Regents of the University of California.  All rights reserved.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
 * are met:
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *    without specific prior written permission.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * SUCH DAMAGE.
 *
 *
 *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
 *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
 * $Id: uipc_mbuf.c,v 1.2 2001-09-27 12:01:51 chris Exp $
 * $Id: uipc_mbuf.c,v 1.2 2001-09-27 12:01:51 chris Exp $
 */
 */
 
 
#include <sys/param.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/malloc.h>
#define MBTYPES
#define MBTYPES
#include <sys/mbuf.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
#include <sys/syslog.h>
#include <sys/domain.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/protosw.h>
 
 
#include <vm/vm.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_kern.h>
#include <vm/vm_extern.h>
#include <vm/vm_extern.h>
 
 
static void mbinit __P((void *))  __attribute__ ((unused));
static void mbinit __P((void *))  __attribute__ ((unused));
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
 
 
struct mbuf *mbutl;
struct mbuf *mbutl;
char    *mclrefcnt;
char    *mclrefcnt;
struct mbstat mbstat;
struct mbstat mbstat;
struct mbuf *mmbfree;
struct mbuf *mmbfree;
union mcluster *mclfree;
union mcluster *mclfree;
int     max_linkhdr;
int     max_linkhdr;
int     max_protohdr;
int     max_protohdr;
int     max_hdr;
int     max_hdr;
int     max_datalen;
int     max_datalen;
 
 
/* "number of clusters of pages" */
/* "number of clusters of pages" */
#define NCL_INIT        1
#define NCL_INIT        1
 
 
#define NMB_INIT        16
#define NMB_INIT        16
 
 
/*
/*
 * When MGET failes, ask protocols to free space when short of memory,
 * When MGET failes, ask protocols to free space when short of memory,
 * then re-attempt to allocate an mbuf.
 * then re-attempt to allocate an mbuf.
 */
 */
struct mbuf *
struct mbuf *
m_retry(i, t)
m_retry(i, t)
        int i, t;
        int i, t;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
 
 
        m_reclaim();
        m_reclaim();
#define m_retry(i, t)   (struct mbuf *)0
#define m_retry(i, t)   (struct mbuf *)0
        MGET(m, i, t);
        MGET(m, i, t);
#undef m_retry
#undef m_retry
        if (m != NULL)
        if (m != NULL)
                mbstat.m_wait++;
                mbstat.m_wait++;
        else
        else
                mbstat.m_drops++;
                mbstat.m_drops++;
        return (m);
        return (m);
}
}
 
 
/*
/*
 * As above; retry an MGETHDR.
 * As above; retry an MGETHDR.
 */
 */
struct mbuf *
struct mbuf *
m_retryhdr(i, t)
m_retryhdr(i, t)
        int i, t;
        int i, t;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
 
 
        m_reclaim();
        m_reclaim();
#define m_retryhdr(i, t) (struct mbuf *)0
#define m_retryhdr(i, t) (struct mbuf *)0
        MGETHDR(m, i, t);
        MGETHDR(m, i, t);
#undef m_retryhdr
#undef m_retryhdr
        if (m != NULL)
        if (m != NULL)
                mbstat.m_wait++;
                mbstat.m_wait++;
        else
        else
                mbstat.m_drops++;
                mbstat.m_drops++;
        return (m);
        return (m);
}
}
 
 
void
void
m_reclaim(void)
m_reclaim(void)
{
{
        register struct domain *dp;
        register struct domain *dp;
        register struct protosw *pr;
        register struct protosw *pr;
        int s = splimp();
        int s = splimp();
 
 
        for (dp = domains; dp; dp = dp->dom_next)
        for (dp = domains; dp; dp = dp->dom_next)
                for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
                for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
                        if (pr->pr_drain)
                        if (pr->pr_drain)
                                (*pr->pr_drain)();
                                (*pr->pr_drain)();
        splx(s);
        splx(s);
        mbstat.m_drain++;
        mbstat.m_drain++;
}
}
 
 
/*
/*
 * Space allocation routines.
 * Space allocation routines.
 * These are also available as macros
 * These are also available as macros
 * for critical paths.
 * for critical paths.
 */
 */
struct mbuf *
struct mbuf *
m_get(nowait, type)
m_get(nowait, type)
        int nowait, type;
        int nowait, type;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
 
 
        MGET(m, nowait, type);
        MGET(m, nowait, type);
        return (m);
        return (m);
}
}
 
 
struct mbuf *
struct mbuf *
m_gethdr(nowait, type)
m_gethdr(nowait, type)
        int nowait, type;
        int nowait, type;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
 
 
        MGETHDR(m, nowait, type);
        MGETHDR(m, nowait, type);
        return (m);
        return (m);
}
}
 
 
struct mbuf *
struct mbuf *
m_getclr(nowait, type)
m_getclr(nowait, type)
        int nowait, type;
        int nowait, type;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
 
 
        MGET(m, nowait, type);
        MGET(m, nowait, type);
        if (m == 0)
        if (m == 0)
                return (0);
                return (0);
        bzero(mtod(m, caddr_t), MLEN);
        bzero(mtod(m, caddr_t), MLEN);
        return (m);
        return (m);
}
}
 
 
struct mbuf *
struct mbuf *
m_free(m)
m_free(m)
        struct mbuf *m;
        struct mbuf *m;
{
{
        register struct mbuf *n;
        register struct mbuf *n;
 
 
        MFREE(m, n);
        MFREE(m, n);
        return (n);
        return (n);
}
}
 
 
void
void
m_freem(m)
m_freem(m)
        register struct mbuf *m;
        register struct mbuf *m;
{
{
        register struct mbuf *n;
        register struct mbuf *n;
 
 
        if (m == NULL)
        if (m == NULL)
                return;
                return;
        do {
        do {
                MFREE(m, n);
                MFREE(m, n);
                m = n;
                m = n;
        } while (m);
        } while (m);
}
}
 
 
/*
/*
 * Mbuffer utility routines.
 * Mbuffer utility routines.
 */
 */
 
 
/*
/*
 * Lesser-used path for M_PREPEND:
 * Lesser-used path for M_PREPEND:
 * allocate new mbuf to prepend to chain,
 * allocate new mbuf to prepend to chain,
 * copy junk along.
 * copy junk along.
 */
 */
struct mbuf *
struct mbuf *
m_prepend(m, len, how)
m_prepend(m, len, how)
        register struct mbuf *m;
        register struct mbuf *m;
        int len, how;
        int len, how;
{
{
        struct mbuf *mn;
        struct mbuf *mn;
 
 
        MGET(mn, how, m->m_type);
        MGET(mn, how, m->m_type);
        if (mn == (struct mbuf *)NULL) {
        if (mn == (struct mbuf *)NULL) {
                m_freem(m);
                m_freem(m);
                return ((struct mbuf *)NULL);
                return ((struct mbuf *)NULL);
        }
        }
        if (m->m_flags & M_PKTHDR) {
        if (m->m_flags & M_PKTHDR) {
                M_COPY_PKTHDR(mn, m);
                M_COPY_PKTHDR(mn, m);
                m->m_flags &= ~M_PKTHDR;
                m->m_flags &= ~M_PKTHDR;
        }
        }
        mn->m_next = m;
        mn->m_next = m;
        m = mn;
        m = mn;
        if (len < MHLEN)
        if (len < MHLEN)
                MH_ALIGN(m, len);
                MH_ALIGN(m, len);
        m->m_len = len;
        m->m_len = len;
        return (m);
        return (m);
}
}
 
 
/*
/*
 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
 * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
 * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
 */
 */
static int MCFail;
static int MCFail;
 
 
struct mbuf *
struct mbuf *
m_copym(m, off0, len, wait)
m_copym(m, off0, len, wait)
        register struct mbuf *m;
        register struct mbuf *m;
        int off0, wait;
        int off0, wait;
        register int len;
        register int len;
{
{
        register struct mbuf *n, **np;
        register struct mbuf *n, **np;
        register int off = off0;
        register int off = off0;
        struct mbuf *top;
        struct mbuf *top;
        int copyhdr = 0;
        int copyhdr = 0;
 
 
        if (off < 0 || len < 0)
        if (off < 0 || len < 0)
                panic("m_copym");
                panic("m_copym");
        if (off == 0 && m->m_flags & M_PKTHDR)
        if (off == 0 && m->m_flags & M_PKTHDR)
                copyhdr = 1;
                copyhdr = 1;
        while (off > 0) {
        while (off > 0) {
                if (m == 0)
                if (m == 0)
                        panic("m_copym");
                        panic("m_copym");
                if (off < m->m_len)
                if (off < m->m_len)
                        break;
                        break;
                off -= m->m_len;
                off -= m->m_len;
                m = m->m_next;
                m = m->m_next;
        }
        }
        np = &top;
        np = &top;
        top = 0;
        top = 0;
        while (len > 0) {
        while (len > 0) {
                if (m == 0) {
                if (m == 0) {
                        if (len != M_COPYALL)
                        if (len != M_COPYALL)
                                panic("m_copym");
                                panic("m_copym");
                        break;
                        break;
                }
                }
                MGET(n, wait, m->m_type);
                MGET(n, wait, m->m_type);
                *np = n;
                *np = n;
                if (n == 0)
                if (n == 0)
                        goto nospace;
                        goto nospace;
                if (copyhdr) {
                if (copyhdr) {
                        M_COPY_PKTHDR(n, m);
                        M_COPY_PKTHDR(n, m);
                        if (len == M_COPYALL)
                        if (len == M_COPYALL)
                                n->m_pkthdr.len -= off0;
                                n->m_pkthdr.len -= off0;
                        else
                        else
                                n->m_pkthdr.len = len;
                                n->m_pkthdr.len = len;
                        copyhdr = 0;
                        copyhdr = 0;
                }
                }
                n->m_len = min(len, m->m_len - off);
                n->m_len = min(len, m->m_len - off);
                if (m->m_flags & M_EXT) {
                if (m->m_flags & M_EXT) {
                        n->m_data = m->m_data + off;
                        n->m_data = m->m_data + off;
                        if(!m->m_ext.ext_ref)
                        if(!m->m_ext.ext_ref)
                                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                        else
                        else
                                (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
                                (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
                                                        m->m_ext.ext_size);
                                                        m->m_ext.ext_size);
                        n->m_ext = m->m_ext;
                        n->m_ext = m->m_ext;
                        n->m_flags |= M_EXT;
                        n->m_flags |= M_EXT;
                } else
                } else
                        bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
                        bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
                            (unsigned)n->m_len);
                            (unsigned)n->m_len);
                if (len != M_COPYALL)
                if (len != M_COPYALL)
                        len -= n->m_len;
                        len -= n->m_len;
                off = 0;
                off = 0;
                m = m->m_next;
                m = m->m_next;
                np = &n->m_next;
                np = &n->m_next;
        }
        }
        if (top == 0)
        if (top == 0)
                MCFail++;
                MCFail++;
        return (top);
        return (top);
nospace:
nospace:
        m_freem(top);
        m_freem(top);
        MCFail++;
        MCFail++;
        return (0);
        return (0);
}
}
 
 
/*
/*
 * Copy an entire packet, including header (which must be present).
 * Copy an entire packet, including header (which must be present).
 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
 */
 */
struct mbuf *
struct mbuf *
m_copypacket(m, how)
m_copypacket(m, how)
        struct mbuf *m;
        struct mbuf *m;
        int how;
        int how;
{
{
        struct mbuf *top, *n, *o;
        struct mbuf *top, *n, *o;
 
 
        MGET(n, how, m->m_type);
        MGET(n, how, m->m_type);
        top = n;
        top = n;
        if (!n)
        if (!n)
                goto nospace;
                goto nospace;
 
 
        M_COPY_PKTHDR(n, m);
        M_COPY_PKTHDR(n, m);
        n->m_len = m->m_len;
        n->m_len = m->m_len;
        if (m->m_flags & M_EXT) {
        if (m->m_flags & M_EXT) {
                n->m_data = m->m_data;
                n->m_data = m->m_data;
                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                n->m_ext = m->m_ext;
                n->m_ext = m->m_ext;
                n->m_flags |= M_EXT;
                n->m_flags |= M_EXT;
        } else {
        } else {
                bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
                bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
        }
        }
 
 
        m = m->m_next;
        m = m->m_next;
        while (m) {
        while (m) {
                MGET(o, how, m->m_type);
                MGET(o, how, m->m_type);
                if (!o)
                if (!o)
                        goto nospace;
                        goto nospace;
 
 
                n->m_next = o;
                n->m_next = o;
                n = n->m_next;
                n = n->m_next;
 
 
                n->m_len = m->m_len;
                n->m_len = m->m_len;
                if (m->m_flags & M_EXT) {
                if (m->m_flags & M_EXT) {
                        n->m_data = m->m_data;
                        n->m_data = m->m_data;
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                        n->m_ext = m->m_ext;
                        n->m_ext = m->m_ext;
                        n->m_flags |= M_EXT;
                        n->m_flags |= M_EXT;
                } else {
                } else {
                        bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
                        bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
                }
                }
 
 
                m = m->m_next;
                m = m->m_next;
        }
        }
        return top;
        return top;
nospace:
nospace:
        m_freem(top);
        m_freem(top);
        MCFail++;
        MCFail++;
        return 0;
        return 0;
}
}
 
 
/*
/*
 * Copy data from an mbuf chain starting "off" bytes from the beginning,
 * Copy data from an mbuf chain starting "off" bytes from the beginning,
 * continuing for "len" bytes, into the indicated buffer.
 * continuing for "len" bytes, into the indicated buffer.
 */
 */
void
void
m_copydata(m, off, len, cp)
m_copydata(m, off, len, cp)
        register struct mbuf *m;
        register struct mbuf *m;
        register int off;
        register int off;
        register int len;
        register int len;
        caddr_t cp;
        caddr_t cp;
{
{
        register unsigned count;
        register unsigned count;
 
 
        if (off < 0 || len < 0)
        if (off < 0 || len < 0)
                panic("m_copydata");
                panic("m_copydata");
        while (off > 0) {
        while (off > 0) {
                if (m == 0)
                if (m == 0)
                        panic("m_copydata");
                        panic("m_copydata");
                if (off < m->m_len)
                if (off < m->m_len)
                        break;
                        break;
                off -= m->m_len;
                off -= m->m_len;
                m = m->m_next;
                m = m->m_next;
        }
        }
        while (len > 0) {
        while (len > 0) {
                if (m == 0)
                if (m == 0)
                        panic("m_copydata");
                        panic("m_copydata");
                count = min(m->m_len - off, len);
                count = min(m->m_len - off, len);
                bcopy(mtod(m, caddr_t) + off, cp, count);
                bcopy(mtod(m, caddr_t) + off, cp, count);
                len -= count;
                len -= count;
                cp += count;
                cp += count;
                off = 0;
                off = 0;
                m = m->m_next;
                m = m->m_next;
        }
        }
}
}
 
 
/*
/*
 * Concatenate mbuf chain n to m.
 * Concatenate mbuf chain n to m.
 * Both chains must be of the same type (e.g. MT_DATA).
 * Both chains must be of the same type (e.g. MT_DATA).
 * Any m_pkthdr is not updated.
 * Any m_pkthdr is not updated.
 */
 */
void
void
m_cat(m, n)
m_cat(m, n)
        register struct mbuf *m, *n;
        register struct mbuf *m, *n;
{
{
        while (m->m_next)
        while (m->m_next)
                m = m->m_next;
                m = m->m_next;
        while (n) {
        while (n) {
                if (m->m_flags & M_EXT ||
                if (m->m_flags & M_EXT ||
                    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
                    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
                        /* just join the two chains */
                        /* just join the two chains */
                        m->m_next = n;
                        m->m_next = n;
                        return;
                        return;
                }
                }
                /* splat the data from one into the other */
                /* splat the data from one into the other */
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
                    (u_int)n->m_len);
                    (u_int)n->m_len);
                m->m_len += n->m_len;
                m->m_len += n->m_len;
                n = m_free(n);
                n = m_free(n);
        }
        }
}
}
 
 
void
void
m_adj(mp, req_len)
m_adj(mp, req_len)
        struct mbuf *mp;
        struct mbuf *mp;
        int req_len;
        int req_len;
{
{
        register int len = req_len;
        register int len = req_len;
        register struct mbuf *m;
        register struct mbuf *m;
        register int count;
        register int count;
 
 
        if ((m = mp) == NULL)
        if ((m = mp) == NULL)
                return;
                return;
        if (len >= 0) {
        if (len >= 0) {
                /*
                /*
                 * Trim from head.
                 * Trim from head.
                 */
                 */
                while (m != NULL && len > 0) {
                while (m != NULL && len > 0) {
                        if (m->m_len <= len) {
                        if (m->m_len <= len) {
                                len -= m->m_len;
                                len -= m->m_len;
                                m->m_len = 0;
                                m->m_len = 0;
                                m = m->m_next;
                                m = m->m_next;
                        } else {
                        } else {
                                m->m_len -= len;
                                m->m_len -= len;
                                m->m_data += len;
                                m->m_data += len;
                                len = 0;
                                len = 0;
                        }
                        }
                }
                }
                m = mp;
                m = mp;
                if (mp->m_flags & M_PKTHDR)
                if (mp->m_flags & M_PKTHDR)
                        m->m_pkthdr.len -= (req_len - len);
                        m->m_pkthdr.len -= (req_len - len);
        } else {
        } else {
                /*
                /*
                 * Trim from tail.  Scan the mbuf chain,
                 * Trim from tail.  Scan the mbuf chain,
                 * calculating its length and finding the last mbuf.
                 * calculating its length and finding the last mbuf.
                 * If the adjustment only affects this mbuf, then just
                 * If the adjustment only affects this mbuf, then just
                 * adjust and return.  Otherwise, rescan and truncate
                 * adjust and return.  Otherwise, rescan and truncate
                 * after the remaining size.
                 * after the remaining size.
                 */
                 */
                len = -len;
                len = -len;
                count = 0;
                count = 0;
                for (;;) {
                for (;;) {
                        count += m->m_len;
                        count += m->m_len;
                        if (m->m_next == (struct mbuf *)0)
                        if (m->m_next == (struct mbuf *)0)
                                break;
                                break;
                        m = m->m_next;
                        m = m->m_next;
                }
                }
                if (m->m_len >= len) {
                if (m->m_len >= len) {
                        m->m_len -= len;
                        m->m_len -= len;
                        if (mp->m_flags & M_PKTHDR)
                        if (mp->m_flags & M_PKTHDR)
                                mp->m_pkthdr.len -= len;
                                mp->m_pkthdr.len -= len;
                        return;
                        return;
                }
                }
                count -= len;
                count -= len;
                if (count < 0)
                if (count < 0)
                        count = 0;
                        count = 0;
                /*
                /*
                 * Correct length for chain is "count".
                 * Correct length for chain is "count".
                 * Find the mbuf with last data, adjust its length,
                 * Find the mbuf with last data, adjust its length,
                 * and toss data from remaining mbufs on chain.
                 * and toss data from remaining mbufs on chain.
                 */
                 */
                m = mp;
                m = mp;
                if (m->m_flags & M_PKTHDR)
                if (m->m_flags & M_PKTHDR)
                        m->m_pkthdr.len = count;
                        m->m_pkthdr.len = count;
                for (; m; m = m->m_next) {
                for (; m; m = m->m_next) {
                        if (m->m_len >= count) {
                        if (m->m_len >= count) {
                                m->m_len = count;
                                m->m_len = count;
                                break;
                                break;
                        }
                        }
                        count -= m->m_len;
                        count -= m->m_len;
                }
                }
                while (m->m_next)
                while (m->m_next)
                        (m = m->m_next) ->m_len = 0;
                        (m = m->m_next) ->m_len = 0;
        }
        }
}
}
 
 
/*
/*
 * Rearange an mbuf chain so that len bytes are contiguous
 * Rearange an mbuf chain so that len bytes are contiguous
 * and in the data area of an mbuf (so that mtod and dtom
 * and in the data area of an mbuf (so that mtod and dtom
 * will work for a structure of size len).  Returns the resulting
 * will work for a structure of size len).  Returns the resulting
 * mbuf chain on success, frees it and returns null on failure.
 * mbuf chain on success, frees it and returns null on failure.
 * If there is room, it will add up to max_protohdr-len extra bytes to the
 * If there is room, it will add up to max_protohdr-len extra bytes to the
 * contiguous region in an attempt to avoid being called next time.
 * contiguous region in an attempt to avoid being called next time.
 */
 */
static int MPFail;
static int MPFail;
 
 
struct mbuf *
struct mbuf *
m_pullup(n, len)
m_pullup(n, len)
        register struct mbuf *n;
        register struct mbuf *n;
        int len;
        int len;
{
{
        register struct mbuf *m;
        register struct mbuf *m;
        register int count;
        register int count;
        int space;
        int space;
 
 
        /*
        /*
         * If first mbuf has no cluster, and has room for len bytes
         * If first mbuf has no cluster, and has room for len bytes
         * without shifting current data, pullup into it,
         * without shifting current data, pullup into it,
         * otherwise allocate a new mbuf to prepend to the chain.
         * otherwise allocate a new mbuf to prepend to the chain.
         */
         */
        if ((n->m_flags & M_EXT) == 0 &&
        if ((n->m_flags & M_EXT) == 0 &&
            n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
            n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
                if (n->m_len >= len)
                if (n->m_len >= len)
                        return (n);
                        return (n);
                m = n;
                m = n;
                n = n->m_next;
                n = n->m_next;
                len -= m->m_len;
                len -= m->m_len;
        } else {
        } else {
                if (len > MHLEN)
                if (len > MHLEN)
                        goto bad;
                        goto bad;
                MGET(m, M_DONTWAIT, n->m_type);
                MGET(m, M_DONTWAIT, n->m_type);
                if (m == 0)
                if (m == 0)
                        goto bad;
                        goto bad;
                m->m_len = 0;
                m->m_len = 0;
                if (n->m_flags & M_PKTHDR) {
                if (n->m_flags & M_PKTHDR) {
                        M_COPY_PKTHDR(m, n);
                        M_COPY_PKTHDR(m, n);
                        n->m_flags &= ~M_PKTHDR;
                        n->m_flags &= ~M_PKTHDR;
                }
                }
        }
        }
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
        do {
        do {
                count = min(min(max(len, max_protohdr), space), n->m_len);
                count = min(min(max(len, max_protohdr), space), n->m_len);
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
                  (unsigned)count);
                  (unsigned)count);
                len -= count;
                len -= count;
                m->m_len += count;
                m->m_len += count;
                n->m_len -= count;
                n->m_len -= count;
                space -= count;
                space -= count;
                if (n->m_len)
                if (n->m_len)
                        n->m_data += count;
                        n->m_data += count;
                else
                else
                        n = m_free(n);
                        n = m_free(n);
        } while (len > 0 && n);
        } while (len > 0 && n);
        if (len > 0) {
        if (len > 0) {
                (void) m_free(m);
                (void) m_free(m);
                goto bad;
                goto bad;
        }
        }
        m->m_next = n;
        m->m_next = n;
        return (m);
        return (m);
bad:
bad:
        m_freem(n);
        m_freem(n);
        MPFail++;
        MPFail++;
        return (0);
        return (0);
}
}
 
 
/*
/*
 * Partition an mbuf chain in two pieces, returning the tail --
 * Partition an mbuf chain in two pieces, returning the tail --
 * all but the first len0 bytes.  In case of failure, it returns NULL and
 * all but the first len0 bytes.  In case of failure, it returns NULL and
 * attempts to restore the chain to its original state.
 * attempts to restore the chain to its original state.
 */
 */
struct mbuf *
struct mbuf *
m_split(m0, len0, wait)
m_split(m0, len0, wait)
        register struct mbuf *m0;
        register struct mbuf *m0;
        int len0, wait;
        int len0, wait;
{
{
        register struct mbuf *m, *n;
        register struct mbuf *m, *n;
        unsigned len = len0, remain;
        unsigned len = len0, remain;
 
 
        for (m = m0; m && len > m->m_len; m = m->m_next)
        for (m = m0; m && len > m->m_len; m = m->m_next)
                len -= m->m_len;
                len -= m->m_len;
        if (m == 0)
        if (m == 0)
                return (0);
                return (0);
        remain = m->m_len - len;
        remain = m->m_len - len;
        if (m0->m_flags & M_PKTHDR) {
        if (m0->m_flags & M_PKTHDR) {
                MGETHDR(n, wait, m0->m_type);
                MGETHDR(n, wait, m0->m_type);
                if (n == 0)
                if (n == 0)
                        return (0);
                        return (0);
                n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
                n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
                n->m_pkthdr.len = m0->m_pkthdr.len - len0;
                n->m_pkthdr.len = m0->m_pkthdr.len - len0;
                m0->m_pkthdr.len = len0;
                m0->m_pkthdr.len = len0;
                if (m->m_flags & M_EXT)
                if (m->m_flags & M_EXT)
                        goto extpacket;
                        goto extpacket;
                if (remain > MHLEN) {
                if (remain > MHLEN) {
                        /* m can't be the lead packet */
                        /* m can't be the lead packet */
                        MH_ALIGN(n, 0);
                        MH_ALIGN(n, 0);
                        n->m_next = m_split(m, len, wait);
                        n->m_next = m_split(m, len, wait);
                        if (n->m_next == 0) {
                        if (n->m_next == 0) {
                                (void) m_free(n);
                                (void) m_free(n);
                                return (0);
                                return (0);
                        } else
                        } else
                                return (n);
                                return (n);
                } else
                } else
                        MH_ALIGN(n, remain);
                        MH_ALIGN(n, remain);
        } else if (remain == 0) {
        } else if (remain == 0) {
                n = m->m_next;
                n = m->m_next;
                m->m_next = 0;
                m->m_next = 0;
                return (n);
                return (n);
        } else {
        } else {
                MGET(n, wait, m->m_type);
                MGET(n, wait, m->m_type);
                if (n == 0)
                if (n == 0)
                        return (0);
                        return (0);
                M_ALIGN(n, remain);
                M_ALIGN(n, remain);
        }
        }
extpacket:
extpacket:
        if (m->m_flags & M_EXT) {
        if (m->m_flags & M_EXT) {
                n->m_flags |= M_EXT;
                n->m_flags |= M_EXT;
                n->m_ext = m->m_ext;
                n->m_ext = m->m_ext;
                if(!m->m_ext.ext_ref)
                if(!m->m_ext.ext_ref)
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
                else
                else
                        (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
                        (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
                                                m->m_ext.ext_size);
                                                m->m_ext.ext_size);
                m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
                m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
                n->m_data = m->m_data + len;
                n->m_data = m->m_data + len;
        } else {
        } else {
                bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
                bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
        }
        }
        n->m_len = remain;
        n->m_len = remain;
        m->m_len = len;
        m->m_len = len;
        n->m_next = m->m_next;
        n->m_next = m->m_next;
        m->m_next = 0;
        m->m_next = 0;
        return (n);
        return (n);
}
}
/*
/*
 * Routine to copy from device local memory into mbufs.
 * Routine to copy from device local memory into mbufs.
 */
 */
struct mbuf *
struct mbuf *
m_devget(buf, totlen, off0, ifp, copy)
m_devget(buf, totlen, off0, ifp, copy)
        char *buf;
        char *buf;
        int totlen, off0;
        int totlen, off0;
        struct ifnet *ifp;
        struct ifnet *ifp;
        void (*copy) __P((char *from, caddr_t to, u_int len));
        void (*copy) __P((char *from, caddr_t to, u_int len));
{
{
        register struct mbuf *m;
        register struct mbuf *m;
        struct mbuf *top = 0, **mp = &top;
        struct mbuf *top = 0, **mp = &top;
        register int off = off0, len;
        register int off = off0, len;
        register char *cp;
        register char *cp;
        char *epkt;
        char *epkt;
 
 
        cp = buf;
        cp = buf;
        epkt = cp + totlen;
        epkt = cp + totlen;
        if (off) {
        if (off) {
                cp += off + 2 * sizeof(u_short);
                cp += off + 2 * sizeof(u_short);
                totlen -= 2 * sizeof(u_short);
                totlen -= 2 * sizeof(u_short);
        }
        }
        MGETHDR(m, M_DONTWAIT, MT_DATA);
        MGETHDR(m, M_DONTWAIT, MT_DATA);
        if (m == 0)
        if (m == 0)
                return (0);
                return (0);
        m->m_pkthdr.rcvif = ifp;
        m->m_pkthdr.rcvif = ifp;
        m->m_pkthdr.len = totlen;
        m->m_pkthdr.len = totlen;
        m->m_len = MHLEN;
        m->m_len = MHLEN;
 
 
        while (totlen > 0) {
        while (totlen > 0) {
                if (top) {
                if (top) {
                        MGET(m, M_DONTWAIT, MT_DATA);
                        MGET(m, M_DONTWAIT, MT_DATA);
                        if (m == 0) {
                        if (m == 0) {
                                m_freem(top);
                                m_freem(top);
                                return (0);
                                return (0);
                        }
                        }
                        m->m_len = MLEN;
                        m->m_len = MLEN;
                }
                }
                len = min(totlen, epkt - cp);
                len = min(totlen, epkt - cp);
                if (len >= MINCLSIZE) {
                if (len >= MINCLSIZE) {
                        MCLGET(m, M_DONTWAIT);
                        MCLGET(m, M_DONTWAIT);
                        if (m->m_flags & M_EXT)
                        if (m->m_flags & M_EXT)
                                m->m_len = len = min(len, MCLBYTES);
                                m->m_len = len = min(len, MCLBYTES);
                        else
                        else
                                len = m->m_len;
                                len = m->m_len;
                } else {
                } else {
                        /*
                        /*
                         * Place initial small packet/header at end of mbuf.
                         * Place initial small packet/header at end of mbuf.
                         */
                         */
                        if (len < m->m_len) {
                        if (len < m->m_len) {
                                if (top == 0 && len + max_linkhdr <= m->m_len)
                                if (top == 0 && len + max_linkhdr <= m->m_len)
                                        m->m_data += max_linkhdr;
                                        m->m_data += max_linkhdr;
                                m->m_len = len;
                                m->m_len = len;
                        } else
                        } else
                                len = m->m_len;
                                len = m->m_len;
                }
                }
                if (copy)
                if (copy)
                        copy(cp, mtod(m, caddr_t), (unsigned)len);
                        copy(cp, mtod(m, caddr_t), (unsigned)len);
                else
                else
                        bcopy(cp, mtod(m, caddr_t), (unsigned)len);
                        bcopy(cp, mtod(m, caddr_t), (unsigned)len);
                cp += len;
                cp += len;
                *mp = m;
                *mp = m;
                mp = &m->m_next;
                mp = &m->m_next;
                totlen -= len;
                totlen -= len;
                if (cp == epkt)
                if (cp == epkt)
                        cp = buf;
                        cp = buf;
        }
        }
        return (top);
        return (top);
}
}
 
 
/*
/*
 * Copy data from a buffer back into the indicated mbuf chain,
 * Copy data from a buffer back into the indicated mbuf chain,
 * starting "off" bytes from the beginning, extending the mbuf
 * starting "off" bytes from the beginning, extending the mbuf
 * chain if necessary.
 * chain if necessary.
 */
 */
void
void
m_copyback(m0, off, len, cp)
m_copyback(m0, off, len, cp)
        struct  mbuf *m0;
        struct  mbuf *m0;
        register int off;
        register int off;
        register int len;
        register int len;
        caddr_t cp;
        caddr_t cp;
{
{
        register int mlen;
        register int mlen;
        register struct mbuf *m = m0, *n;
        register struct mbuf *m = m0, *n;
        int totlen = 0;
        int totlen = 0;
 
 
        if (m0 == 0)
        if (m0 == 0)
                return;
                return;
        while (off > (mlen = m->m_len)) {
        while (off > (mlen = m->m_len)) {
                off -= mlen;
                off -= mlen;
                totlen += mlen;
                totlen += mlen;
                if (m->m_next == 0) {
                if (m->m_next == 0) {
                        n = m_getclr(M_DONTWAIT, m->m_type);
                        n = m_getclr(M_DONTWAIT, m->m_type);
                        if (n == 0)
                        if (n == 0)
                                goto out;
                                goto out;
                        n->m_len = min(MLEN, len + off);
                        n->m_len = min(MLEN, len + off);
                        m->m_next = n;
                        m->m_next = n;
                }
                }
                m = m->m_next;
                m = m->m_next;
        }
        }
        while (len > 0) {
        while (len > 0) {
                mlen = min (m->m_len - off, len);
                mlen = min (m->m_len - off, len);
                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
                cp += mlen;
                cp += mlen;
                len -= mlen;
                len -= mlen;
                mlen += off;
                mlen += off;
                off = 0;
                off = 0;
                totlen += mlen;
                totlen += mlen;
                if (len == 0)
                if (len == 0)
                        break;
                        break;
                if (m->m_next == 0) {
                if (m->m_next == 0) {
                        n = m_get(M_DONTWAIT, m->m_type);
                        n = m_get(M_DONTWAIT, m->m_type);
                        if (n == 0)
                        if (n == 0)
                                break;
                                break;
                        n->m_len = min(MLEN, len);
                        n->m_len = min(MLEN, len);
                        m->m_next = n;
                        m->m_next = n;
                }
                }
                m = m->m_next;
                m = m->m_next;
        }
        }
out:    if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
out:    if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
                m->m_pkthdr.len = totlen;
                m->m_pkthdr.len = totlen;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.