123417Smckusick /* 248445Skarels * Copyright (c) 1982, 1986, 1988, 1991 Regents of the University of California. 333185Sbostic * All rights reserved. 423417Smckusick * 544448Sbostic * %sccs.include.redist.c% 633185Sbostic * 7*56517Sbostic * @(#)uipc_mbuf.c 7.25 (Berkeley) 10/11/92 823417Smckusick */ 94585Swnj 10*56517Sbostic #include <sys/param.h> 11*56517Sbostic #include <sys/systm.h> 12*56517Sbostic #include <sys/proc.h> 13*56517Sbostic #include <sys/malloc.h> 14*56517Sbostic #include <sys/map.h> 1538962Skarels #define MBTYPES 16*56517Sbostic #include <sys/mbuf.h> 17*56517Sbostic #include <sys/kernel.h> 18*56517Sbostic #include <sys/syslog.h> 19*56517Sbostic #include <sys/domain.h> 20*56517Sbostic #include <sys/protosw.h> 214585Swnj 22*56517Sbostic #include <vm/vm.h> 23*56517Sbostic 2448445Skarels extern vm_map_t mb_map; 2548445Skarels struct mbuf *mbutl; 2648445Skarels char *mclrefcnt; 2745736Smckusick 285228Swnj mbinit() 295228Swnj { 3021107Skarels int s; 315228Swnj 3245736Smckusick #if CLBYTES < 4096 3341998Smckusick #define NCL_INIT (4096/CLBYTES) 3432659Skarels #else 3532659Skarels #define NCL_INIT 1 3632659Skarels #endif 3721107Skarels s = splimp(); 3838962Skarels if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) 395228Swnj goto bad; 4021107Skarels splx(s); 415228Swnj return; 425228Swnj bad: 435228Swnj panic("mbinit"); 445228Swnj } 455228Swnj 4621107Skarels /* 4738962Skarels * Allocate some number of mbuf clusters 4838962Skarels * and place on cluster free list. 4921107Skarels * Must be called at splimp. 5021107Skarels */ 5130442Skarels /* ARGSUSED */ 5252038Smckusick m_clalloc(ncl, nowait) 535228Swnj register int ncl; 5452038Smckusick int nowait; 555228Swnj { 565228Swnj int npg, mbx; 5738962Skarels register caddr_t p; 585228Swnj register int i; 5930442Skarels static int logged; 605228Swnj 615228Swnj npg = ncl * CLSIZE; 6252038Smckusick p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait); 6345736Smckusick if (p == NULL) { 6430442Skarels if (logged == 0) { 6530442Skarels logged++; 6645736Smckusick log(LOG_ERR, "mb_map full\n"); 6730442Skarels } 685228Swnj return (0); 6921107Skarels } 7038962Skarels ncl = ncl * CLBYTES / MCLBYTES; 7138962Skarels for (i = 0; i < ncl; i++) { 7238962Skarels ((union mcluster *)p)->mcl_next = mclfree; 7338962Skarels mclfree = (union mcluster *)p; 7438962Skarels p += MCLBYTES; 7538962Skarels mbstat.m_clfree++; 7638962Skarels } 7738962Skarels mbstat.m_clusters += ncl; 7838962Skarels return (1); 7938962Skarels } 805228Swnj 8138962Skarels /* 8238962Skarels * When MGET failes, ask protocols to free space when short of memory, 8338962Skarels * then re-attempt to allocate an mbuf. 8438962Skarels */ 8538962Skarels struct mbuf * 8638962Skarels m_retry(i, t) 8738962Skarels int i, t; 8838962Skarels { 8938962Skarels register struct mbuf *m; 905228Swnj 9138962Skarels m_reclaim(); 9238962Skarels #define m_retry(i, t) (struct mbuf *)0 9338962Skarels MGET(m, i, t); 9438962Skarels #undef m_retry 9538962Skarels return (m); 965228Swnj } 975228Swnj 9821107Skarels /* 9938962Skarels * As above; retry an MGETHDR. 10021107Skarels */ 10138962Skarels struct mbuf * 10238962Skarels m_retryhdr(i, t) 10338962Skarels int i, t; 1045228Swnj { 10538962Skarels register struct mbuf *m; 10638962Skarels 10738962Skarels m_reclaim(); 10838962Skarels #define m_retryhdr(i, t) (struct mbuf *)0 10938962Skarels MGETHDR(m, i, t); 11038962Skarels #undef m_retryhdr 11138962Skarels return (m); 11238962Skarels } 11338962Skarels 11438962Skarels m_reclaim() 11538962Skarels { 11630442Skarels register struct domain *dp; 11730442Skarels register struct protosw *pr; 11838962Skarels int s = splimp(); 1195228Swnj 12038962Skarels for (dp = domains; dp; dp = dp->dom_next) 12138962Skarels for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 12238962Skarels if (pr->pr_drain) 12338962Skarels (*pr->pr_drain)(); 12438962Skarels splx(s); 12538962Skarels mbstat.m_drain++; 1265228Swnj } 1275228Swnj 1285228Swnj /* 1295228Swnj * Space allocation routines. 1305228Swnj * These are also available as macros 1315228Swnj * for critical paths. 1325228Swnj */ 1334585Swnj struct mbuf * 13452038Smckusick m_get(nowait, type) 13552038Smckusick int nowait, type; 1364585Swnj { 1374585Swnj register struct mbuf *m; 1384585Swnj 13952038Smckusick MGET(m, nowait, type); 1404585Swnj return (m); 1414585Swnj } 1424585Swnj 1434585Swnj struct mbuf * 14452038Smckusick m_gethdr(nowait, type) 14552038Smckusick int nowait, type; 14638962Skarels { 14738962Skarels register struct mbuf *m; 14838962Skarels 14952038Smckusick MGETHDR(m, nowait, type); 15038962Skarels return (m); 15138962Skarels } 15238962Skarels 15338962Skarels struct mbuf * 15452038Smckusick m_getclr(nowait, type) 15552038Smckusick int nowait, type; 1564890Swnj { 1574890Swnj register struct mbuf *m; 1584890Swnj 15952038Smckusick MGET(m, nowait, type); 1604890Swnj if (m == 0) 1614890Swnj return (0); 1624890Swnj bzero(mtod(m, caddr_t), MLEN); 1634890Swnj return (m); 1644890Swnj } 1654890Swnj 1664890Swnj struct mbuf * 1674585Swnj m_free(m) 1684585Swnj struct mbuf *m; 1694585Swnj { 1704585Swnj register struct mbuf *n; 1714585Swnj 1724585Swnj MFREE(m, n); 1734585Swnj return (n); 1744585Swnj } 1754585Swnj 17652394Storek void 1774669Swnj m_freem(m) 1784585Swnj register struct mbuf *m; 1794585Swnj { 1804585Swnj register struct mbuf *n; 1814585Swnj 1824585Swnj if (m == NULL) 1834916Swnj return; 1844585Swnj do { 1854585Swnj MFREE(m, n); 1864585Swnj } while (m = n); 1874585Swnj } 1884585Swnj 1895228Swnj /* 1905228Swnj * Mbuffer utility routines. 1915228Swnj */ 19221107Skarels 19321107Skarels /* 19438962Skarels * Lesser-used path for M_PREPEND: 19538962Skarels * allocate new mbuf to prepend to chain, 19638962Skarels * copy junk along. 19738962Skarels */ 19838962Skarels struct mbuf * 19938962Skarels m_prepend(m, len, how) 20038962Skarels register struct mbuf *m; 20138962Skarels int len, how; 20238962Skarels { 20338962Skarels struct mbuf *mn; 20438962Skarels 20538962Skarels MGET(mn, how, m->m_type); 20638962Skarels if (mn == (struct mbuf *)NULL) { 20738962Skarels m_freem(m); 20838962Skarels return ((struct mbuf *)NULL); 20938962Skarels } 21038962Skarels if (m->m_flags & M_PKTHDR) { 21138962Skarels M_COPY_PKTHDR(mn, m); 21238962Skarels m->m_flags &= ~M_PKTHDR; 21338962Skarels } 21438962Skarels mn->m_next = m; 21538962Skarels m = mn; 21638962Skarels if (len < MHLEN) 21738962Skarels MH_ALIGN(m, len); 21838962Skarels m->m_len = len; 21938962Skarels return (m); 22038962Skarels } 22138962Skarels 22233606Skarels /* 22338962Skarels * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 22421107Skarels * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 22538962Skarels * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 22621107Skarels */ 22741999Smckusick int MCFail; 22841999Smckusick 2294927Swnj struct mbuf * 23038962Skarels m_copym(m, off0, len, wait) 2314927Swnj register struct mbuf *m; 23238962Skarels int off0, wait; 2334927Swnj register int len; 2344927Swnj { 2354927Swnj register struct mbuf *n, **np; 23638962Skarels register int off = off0; 23738962Skarels struct mbuf *top; 23838962Skarels int copyhdr = 0; 2394927Swnj 2404927Swnj if (off < 0 || len < 0) 24138962Skarels panic("m_copym"); 24238962Skarels if (off == 0 && m->m_flags & M_PKTHDR) 24338962Skarels copyhdr = 1; 2444927Swnj while (off > 0) { 2454927Swnj if (m == 0) 24638962Skarels panic("m_copym"); 2474927Swnj if (off < m->m_len) 2484927Swnj break; 2494927Swnj off -= m->m_len; 2504927Swnj m = m->m_next; 2514927Swnj } 2524927Swnj np = ⊤ 2534927Swnj top = 0; 2544927Swnj while (len > 0) { 2555609Swnj if (m == 0) { 2565609Swnj if (len != M_COPYALL) 25738962Skarels panic("m_copym"); 2585609Swnj break; 2595609Swnj } 26038962Skarels MGET(n, wait, m->m_type); 2614927Swnj *np = n; 2624927Swnj if (n == 0) 2634927Swnj goto nospace; 26438962Skarels if (copyhdr) { 26538962Skarels M_COPY_PKTHDR(n, m); 26638962Skarels if (len == M_COPYALL) 26738962Skarels n->m_pkthdr.len -= off0; 26838962Skarels else 26938962Skarels n->m_pkthdr.len = len; 27038962Skarels copyhdr = 0; 27138962Skarels } 27255058Spendry n->m_len = min(len, m->m_len - off); 27338962Skarels if (m->m_flags & M_EXT) { 27438962Skarels n->m_data = m->m_data + off; 27538962Skarels mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 27638962Skarels n->m_ext = m->m_ext; 27738962Skarels n->m_flags |= M_EXT; 2788318Sroot } else 2794927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2804927Swnj (unsigned)n->m_len); 2815609Swnj if (len != M_COPYALL) 2825609Swnj len -= n->m_len; 2834927Swnj off = 0; 2844927Swnj m = m->m_next; 2854927Swnj np = &n->m_next; 2864927Swnj } 28741999Smckusick if (top == 0) 28841999Smckusick MCFail++; 2894927Swnj return (top); 2904927Swnj nospace: 2914927Swnj m_freem(top); 29241999Smckusick MCFail++; 2934927Swnj return (0); 2944927Swnj } 2954927Swnj 29633606Skarels /* 29733606Skarels * Copy data from an mbuf chain starting "off" bytes from the beginning, 29833606Skarels * continuing for "len" bytes, into the indicated buffer. 29933606Skarels */ 30033606Skarels m_copydata(m, off, len, cp) 30133606Skarels register struct mbuf *m; 30233988Skarels register int off; 30333606Skarels register int len; 30433988Skarels caddr_t cp; 30533606Skarels { 30633606Skarels register unsigned count; 30733606Skarels 30833606Skarels if (off < 0 || len < 0) 30933606Skarels panic("m_copydata"); 31033606Skarels while (off > 0) { 31133606Skarels if (m == 0) 31233606Skarels panic("m_copydata"); 31333606Skarels if (off < m->m_len) 31433606Skarels break; 31533606Skarels off -= m->m_len; 31633606Skarels m = m->m_next; 31733606Skarels } 31833606Skarels while (len > 0) { 31933606Skarels if (m == 0) 32033606Skarels panic("m_copydata"); 32155058Spendry count = min(m->m_len - off, len); 32233606Skarels bcopy(mtod(m, caddr_t) + off, cp, count); 32333606Skarels len -= count; 32433988Skarels cp += count; 32533606Skarels off = 0; 32633606Skarels m = m->m_next; 32733606Skarels } 32833606Skarels } 32933606Skarels 33038962Skarels /* 33138962Skarels * Concatenate mbuf chain n to m. 33238962Skarels * Both chains must be of the same type (e.g. MT_DATA). 33338962Skarels * Any m_pkthdr is not updated. 33438962Skarels */ 3354669Swnj m_cat(m, n) 3364669Swnj register struct mbuf *m, *n; 3374669Swnj { 3384669Swnj while (m->m_next) 3394669Swnj m = m->m_next; 3406091Sroot while (n) { 34138962Skarels if (m->m_flags & M_EXT || 34238962Skarels m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 3436091Sroot /* just join the two chains */ 3444669Swnj m->m_next = n; 3456091Sroot return; 3464669Swnj } 3476091Sroot /* splat the data from one into the other */ 3486091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 3496091Sroot (u_int)n->m_len); 3506091Sroot m->m_len += n->m_len; 3516091Sroot n = m_free(n); 3526091Sroot } 3534669Swnj } 3544669Swnj 35538962Skarels m_adj(mp, req_len) 3564585Swnj struct mbuf *mp; 35752394Storek int req_len; 3584585Swnj { 35938962Skarels register int len = req_len; 36024764Skarels register struct mbuf *m; 36124764Skarels register count; 3624585Swnj 3634585Swnj if ((m = mp) == NULL) 3644585Swnj return; 3654822Swnj if (len >= 0) { 36638962Skarels /* 36738962Skarels * Trim from head. 36838962Skarels */ 3694585Swnj while (m != NULL && len > 0) { 3704822Swnj if (m->m_len <= len) { 3714585Swnj len -= m->m_len; 3724585Swnj m->m_len = 0; 3734585Swnj m = m->m_next; 3744822Swnj } else { 3754585Swnj m->m_len -= len; 37638962Skarels m->m_data += len; 37738962Skarels len = 0; 3784585Swnj } 3794585Swnj } 38038962Skarels m = mp; 38138962Skarels if (mp->m_flags & M_PKTHDR) 38238962Skarels m->m_pkthdr.len -= (req_len - len); 3834822Swnj } else { 38424764Skarels /* 38524764Skarels * Trim from tail. Scan the mbuf chain, 38624764Skarels * calculating its length and finding the last mbuf. 38724764Skarels * If the adjustment only affects this mbuf, then just 38824764Skarels * adjust and return. Otherwise, rescan and truncate 38924764Skarels * after the remaining size. 39024764Skarels */ 3914585Swnj len = -len; 39224764Skarels count = 0; 39324764Skarels for (;;) { 39424764Skarels count += m->m_len; 39524764Skarels if (m->m_next == (struct mbuf *)0) 3964585Swnj break; 39724764Skarels m = m->m_next; 39824764Skarels } 39924764Skarels if (m->m_len >= len) { 40024764Skarels m->m_len -= len; 40139227Ssklower if ((mp = m)->m_flags & M_PKTHDR) 40239227Ssklower m->m_pkthdr.len -= len; 40324764Skarels return; 40424764Skarels } 40524764Skarels count -= len; 40638962Skarels if (count < 0) 40738962Skarels count = 0; 40824764Skarels /* 40924764Skarels * Correct length for chain is "count". 41024764Skarels * Find the mbuf with last data, adjust its length, 41124764Skarels * and toss data from remaining mbufs on chain. 41224764Skarels */ 41338962Skarels m = mp; 41438962Skarels if (m->m_flags & M_PKTHDR) 41538962Skarels m->m_pkthdr.len = count; 41638962Skarels for (; m; m = m->m_next) { 41724764Skarels if (m->m_len >= count) { 41824764Skarels m->m_len = count; 41924764Skarels break; 4204585Swnj } 42124764Skarels count -= m->m_len; 4224585Swnj } 42324764Skarels while (m = m->m_next) 42424764Skarels m->m_len = 0; 4254585Swnj } 4264585Swnj } 4275228Swnj 42823816Skarels /* 42923816Skarels * Rearange an mbuf chain so that len bytes are contiguous 43023816Skarels * and in the data area of an mbuf (so that mtod and dtom 43124764Skarels * will work for a structure of size len). Returns the resulting 43224764Skarels * mbuf chain on success, frees it and returns null on failure. 43338962Skarels * If there is room, it will add up to max_protohdr-len extra bytes to the 43424764Skarels * contiguous region in an attempt to avoid being called next time. 43523816Skarels */ 43641999Smckusick int MPFail; 43741999Smckusick 4385310Sroot struct mbuf * 43924764Skarels m_pullup(n, len) 44024764Skarels register struct mbuf *n; 4415228Swnj int len; 4425228Swnj { 44324764Skarels register struct mbuf *m; 44424764Skarels register int count; 44524764Skarels int space; 4465228Swnj 44738962Skarels /* 44838962Skarels * If first mbuf has no cluster, and has room for len bytes 44938962Skarels * without shifting current data, pullup into it, 45038962Skarels * otherwise allocate a new mbuf to prepend to the chain. 45138962Skarels */ 45238962Skarels if ((n->m_flags & M_EXT) == 0 && 45338962Skarels n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 45438962Skarels if (n->m_len >= len) 45538962Skarels return (n); 45624764Skarels m = n; 45724764Skarels n = n->m_next; 45824764Skarels len -= m->m_len; 45924764Skarels } else { 46038962Skarels if (len > MHLEN) 46124764Skarels goto bad; 46224764Skarels MGET(m, M_DONTWAIT, n->m_type); 46324764Skarels if (m == 0) 46424764Skarels goto bad; 46524764Skarels m->m_len = 0; 46644969Skarels if (n->m_flags & M_PKTHDR) { 46738962Skarels M_COPY_PKTHDR(m, n); 46844969Skarels n->m_flags &= ~M_PKTHDR; 46944969Skarels } 47024764Skarels } 47138962Skarels space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 4725310Sroot do { 47338962Skarels count = min(min(max(len, max_protohdr), space), n->m_len); 47438962Skarels bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 4756164Ssam (unsigned)count); 4766164Ssam len -= count; 4776164Ssam m->m_len += count; 4786164Ssam n->m_len -= count; 47938962Skarels space -= count; 4805310Sroot if (n->m_len) 48138962Skarels n->m_data += count; 48223816Skarels else 48323816Skarels n = m_free(n); 48424764Skarels } while (len > 0 && n); 48524764Skarels if (len > 0) { 4865310Sroot (void) m_free(m); 4875310Sroot goto bad; 4885310Sroot } 4895310Sroot m->m_next = n; 4905310Sroot return (m); 4915310Sroot bad: 4925732Sroot m_freem(n); 49341999Smckusick MPFail++; 4945228Swnj return (0); 4955228Swnj } 49650941Ssklower 49750941Ssklower /* 49850941Ssklower * Partition an mbuf chain in two pieces, returning the tail -- 49950941Ssklower * all but the first len0 bytes. In case of failure, it returns NULL and 50050941Ssklower * attempts to restore the chain to its original state. 50150941Ssklower */ 50250941Ssklower struct mbuf * 50350941Ssklower m_split(m0, len0, wait) 50452394Storek register struct mbuf *m0; 50552394Storek int len0, wait; 50650941Ssklower { 50750941Ssklower register struct mbuf *m, *n; 50850941Ssklower unsigned len = len0, remain; 50950941Ssklower 51050941Ssklower for (m = m0; m && len > m->m_len; m = m->m_next) 51150941Ssklower len -= m->m_len; 51250941Ssklower if (m == 0) 51350941Ssklower return (0); 51450941Ssklower remain = m->m_len - len; 51550941Ssklower if (m0->m_flags & M_PKTHDR) { 51650941Ssklower MGETHDR(n, wait, m0->m_type); 51750941Ssklower if (n == 0) 51850941Ssklower return (0); 51950941Ssklower n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 52050941Ssklower n->m_pkthdr.len = m0->m_pkthdr.len - len0; 52150941Ssklower m0->m_pkthdr.len = len0; 52250941Ssklower if (m->m_flags & M_EXT) 52350941Ssklower goto extpacket; 52450941Ssklower if (remain > MHLEN) { 52550941Ssklower /* m can't be the lead packet */ 52650941Ssklower MH_ALIGN(n, 0); 52750941Ssklower n->m_next = m_split(m, len, wait); 52850941Ssklower if (n->m_next == 0) { 52950941Ssklower (void) m_free(n); 53050941Ssklower return (0); 53150941Ssklower } else 53250941Ssklower return (n); 53350941Ssklower } else 53450941Ssklower MH_ALIGN(n, remain); 53550941Ssklower } else if (remain == 0) { 53650941Ssklower n = m->m_next; 53750941Ssklower m->m_next = 0; 53850941Ssklower return (n); 53950941Ssklower } else { 54050941Ssklower MGET(n, wait, m->m_type); 54150941Ssklower if (n == 0) 54250941Ssklower return (0); 54350941Ssklower M_ALIGN(n, remain); 54450941Ssklower } 54550941Ssklower extpacket: 54650941Ssklower if (m->m_flags & M_EXT) { 54750941Ssklower n->m_flags |= M_EXT; 54850941Ssklower n->m_ext = m->m_ext; 54950941Ssklower mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 55050941Ssklower m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ 55150941Ssklower n->m_data = m->m_data + len; 55250941Ssklower } else { 55350941Ssklower bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); 55450941Ssklower } 55550941Ssklower n->m_len = remain; 55650941Ssklower m->m_len = len; 55750941Ssklower n->m_next = m->m_next; 55850941Ssklower m->m_next = 0; 55950941Ssklower return (n); 56050941Ssklower } 56150941Ssklower /* 56250941Ssklower * Routine to copy from device local memory into mbufs. 56350941Ssklower */ 56450941Ssklower struct mbuf * 56550941Ssklower m_devget(buf, totlen, off0, ifp, copy) 56650941Ssklower char *buf; 56750941Ssklower int totlen, off0; 56850941Ssklower struct ifnet *ifp; 56950941Ssklower void (*copy)(); 57050941Ssklower { 57150941Ssklower register struct mbuf *m; 57250941Ssklower struct mbuf *top = 0, **mp = ⊤ 57350941Ssklower register int off = off0, len; 57450941Ssklower register char *cp; 57550941Ssklower char *epkt; 57650941Ssklower 57750941Ssklower cp = buf; 57850941Ssklower epkt = cp + totlen; 57950941Ssklower if (off) { 58050941Ssklower cp += off + 2 * sizeof(u_short); 58150941Ssklower totlen -= 2 * sizeof(u_short); 58250941Ssklower } 58350941Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 58450941Ssklower if (m == 0) 58550941Ssklower return (0); 58650941Ssklower m->m_pkthdr.rcvif = ifp; 58750941Ssklower m->m_pkthdr.len = totlen; 58850941Ssklower m->m_len = MHLEN; 58950941Ssklower 59050941Ssklower while (totlen > 0) { 59150941Ssklower if (top) { 59250941Ssklower MGET(m, M_DONTWAIT, MT_DATA); 59350941Ssklower if (m == 0) { 59450941Ssklower m_freem(top); 59550941Ssklower return (0); 59650941Ssklower } 59750941Ssklower m->m_len = MLEN; 59850941Ssklower } 59950941Ssklower len = min(totlen, epkt - cp); 60050941Ssklower if (len >= MINCLSIZE) { 60150941Ssklower MCLGET(m, M_DONTWAIT); 60250941Ssklower if (m->m_flags & M_EXT) 60350941Ssklower m->m_len = len = min(len, MCLBYTES); 60450941Ssklower else 60550941Ssklower len = m->m_len; 60650941Ssklower } else { 60750941Ssklower /* 60850941Ssklower * Place initial small packet/header at end of mbuf. 60950941Ssklower */ 61050941Ssklower if (len < m->m_len) { 61150941Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 61250941Ssklower m->m_data += max_linkhdr; 61350941Ssklower m->m_len = len; 61450941Ssklower } else 61550941Ssklower len = m->m_len; 61650941Ssklower } 61750941Ssklower if (copy) 61850941Ssklower copy(cp, mtod(m, caddr_t), (unsigned)len); 61950941Ssklower else 62050941Ssklower bcopy(cp, mtod(m, caddr_t), (unsigned)len); 62150941Ssklower cp += len; 62250941Ssklower *mp = m; 62350941Ssklower mp = &m->m_next; 62450941Ssklower totlen -= len; 62550941Ssklower if (cp == epkt) 62650941Ssklower cp = buf; 62750941Ssklower } 62850941Ssklower return (top); 62950941Ssklower } 630