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*52038Smckusick * @(#)uipc_mbuf.c 7.21 (Berkeley) 12/19/91 823417Smckusick */ 94585Swnj 1017102Sbloom #include "param.h" 1117102Sbloom #include "proc.h" 1238962Skarels #include "malloc.h" 1317102Sbloom #include "map.h" 1438962Skarels #define MBTYPES 1517102Sbloom #include "mbuf.h" 1617102Sbloom #include "kernel.h" 1730442Skarels #include "syslog.h" 1830442Skarels #include "domain.h" 1930442Skarels #include "protosw.h" 2048445Skarels #include "vm/vm.h" 214585Swnj 2248445Skarels extern vm_map_t mb_map; 2348445Skarels struct mbuf *mbutl; 2448445Skarels char *mclrefcnt; 2545736Smckusick 265228Swnj mbinit() 275228Swnj { 2821107Skarels int s; 295228Swnj 3045736Smckusick #if CLBYTES < 4096 3141998Smckusick #define NCL_INIT (4096/CLBYTES) 3232659Skarels #else 3332659Skarels #define NCL_INIT 1 3432659Skarels #endif 3521107Skarels s = splimp(); 3638962Skarels if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) 375228Swnj goto bad; 3821107Skarels splx(s); 395228Swnj return; 405228Swnj bad: 415228Swnj panic("mbinit"); 425228Swnj } 435228Swnj 4421107Skarels /* 4538962Skarels * Allocate some number of mbuf clusters 4638962Skarels * and place on cluster free list. 4721107Skarels * Must be called at splimp. 4821107Skarels */ 4930442Skarels /* ARGSUSED */ 50*52038Smckusick m_clalloc(ncl, nowait) 515228Swnj register int ncl; 52*52038Smckusick int nowait; 535228Swnj { 545228Swnj int npg, mbx; 5538962Skarels register caddr_t p; 565228Swnj register int i; 5730442Skarels static int logged; 585228Swnj 595228Swnj npg = ncl * CLSIZE; 60*52038Smckusick p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait); 6145736Smckusick if (p == NULL) { 6230442Skarels if (logged == 0) { 6330442Skarels logged++; 6445736Smckusick log(LOG_ERR, "mb_map full\n"); 6530442Skarels } 665228Swnj return (0); 6721107Skarels } 6838962Skarels ncl = ncl * CLBYTES / MCLBYTES; 6938962Skarels for (i = 0; i < ncl; i++) { 7038962Skarels ((union mcluster *)p)->mcl_next = mclfree; 7138962Skarels mclfree = (union mcluster *)p; 7238962Skarels p += MCLBYTES; 7338962Skarels mbstat.m_clfree++; 7438962Skarels } 7538962Skarels mbstat.m_clusters += ncl; 7638962Skarels return (1); 7738962Skarels } 785228Swnj 7938962Skarels /* 8038962Skarels * When MGET failes, ask protocols to free space when short of memory, 8138962Skarels * then re-attempt to allocate an mbuf. 8238962Skarels */ 8338962Skarels struct mbuf * 8438962Skarels m_retry(i, t) 8538962Skarels int i, t; 8638962Skarels { 8738962Skarels register struct mbuf *m; 885228Swnj 8938962Skarels m_reclaim(); 9038962Skarels #define m_retry(i, t) (struct mbuf *)0 9138962Skarels MGET(m, i, t); 9238962Skarels #undef m_retry 9338962Skarels return (m); 945228Swnj } 955228Swnj 9621107Skarels /* 9738962Skarels * As above; retry an MGETHDR. 9821107Skarels */ 9938962Skarels struct mbuf * 10038962Skarels m_retryhdr(i, t) 10138962Skarels int i, t; 1025228Swnj { 10338962Skarels register struct mbuf *m; 10438962Skarels 10538962Skarels m_reclaim(); 10638962Skarels #define m_retryhdr(i, t) (struct mbuf *)0 10738962Skarels MGETHDR(m, i, t); 10838962Skarels #undef m_retryhdr 10938962Skarels return (m); 11038962Skarels } 11138962Skarels 11238962Skarels m_reclaim() 11338962Skarels { 11430442Skarels register struct domain *dp; 11530442Skarels register struct protosw *pr; 11638962Skarels int s = splimp(); 1175228Swnj 11838962Skarels for (dp = domains; dp; dp = dp->dom_next) 11938962Skarels for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 12038962Skarels if (pr->pr_drain) 12138962Skarels (*pr->pr_drain)(); 12238962Skarels splx(s); 12338962Skarels mbstat.m_drain++; 1245228Swnj } 1255228Swnj 1265228Swnj /* 1275228Swnj * Space allocation routines. 1285228Swnj * These are also available as macros 1295228Swnj * for critical paths. 1305228Swnj */ 1314585Swnj struct mbuf * 132*52038Smckusick m_get(nowait, type) 133*52038Smckusick int nowait, type; 1344585Swnj { 1354585Swnj register struct mbuf *m; 1364585Swnj 137*52038Smckusick MGET(m, nowait, type); 1384585Swnj return (m); 1394585Swnj } 1404585Swnj 1414585Swnj struct mbuf * 142*52038Smckusick m_gethdr(nowait, type) 143*52038Smckusick int nowait, type; 14438962Skarels { 14538962Skarels register struct mbuf *m; 14638962Skarels 147*52038Smckusick MGETHDR(m, nowait, type); 14838962Skarels return (m); 14938962Skarels } 15038962Skarels 15138962Skarels struct mbuf * 152*52038Smckusick m_getclr(nowait, type) 153*52038Smckusick int nowait, type; 1544890Swnj { 1554890Swnj register struct mbuf *m; 1564890Swnj 157*52038Smckusick MGET(m, nowait, type); 1584890Swnj if (m == 0) 1594890Swnj return (0); 1604890Swnj bzero(mtod(m, caddr_t), MLEN); 1614890Swnj return (m); 1624890Swnj } 1634890Swnj 1644890Swnj struct mbuf * 1654585Swnj m_free(m) 1664585Swnj struct mbuf *m; 1674585Swnj { 1684585Swnj register struct mbuf *n; 1694585Swnj 1704585Swnj MFREE(m, n); 1714585Swnj return (n); 1724585Swnj } 1734585Swnj 1744669Swnj m_freem(m) 1754585Swnj register struct mbuf *m; 1764585Swnj { 1774585Swnj register struct mbuf *n; 1784585Swnj 1794585Swnj if (m == NULL) 1804916Swnj return; 1814585Swnj do { 1824585Swnj MFREE(m, n); 1834585Swnj } while (m = n); 1844585Swnj } 1854585Swnj 1865228Swnj /* 1875228Swnj * Mbuffer utility routines. 1885228Swnj */ 18921107Skarels 19021107Skarels /* 19138962Skarels * Lesser-used path for M_PREPEND: 19238962Skarels * allocate new mbuf to prepend to chain, 19338962Skarels * copy junk along. 19438962Skarels */ 19538962Skarels struct mbuf * 19638962Skarels m_prepend(m, len, how) 19738962Skarels register struct mbuf *m; 19838962Skarels int len, how; 19938962Skarels { 20038962Skarels struct mbuf *mn; 20138962Skarels 20238962Skarels MGET(mn, how, m->m_type); 20338962Skarels if (mn == (struct mbuf *)NULL) { 20438962Skarels m_freem(m); 20538962Skarels return ((struct mbuf *)NULL); 20638962Skarels } 20738962Skarels if (m->m_flags & M_PKTHDR) { 20838962Skarels M_COPY_PKTHDR(mn, m); 20938962Skarels m->m_flags &= ~M_PKTHDR; 21038962Skarels } 21138962Skarels mn->m_next = m; 21238962Skarels m = mn; 21338962Skarels if (len < MHLEN) 21438962Skarels MH_ALIGN(m, len); 21538962Skarels m->m_len = len; 21638962Skarels return (m); 21738962Skarels } 21838962Skarels 21933606Skarels /* 22038962Skarels * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 22121107Skarels * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 22238962Skarels * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. 22321107Skarels */ 22441999Smckusick int MCFail; 22541999Smckusick 2264927Swnj struct mbuf * 22738962Skarels m_copym(m, off0, len, wait) 2284927Swnj register struct mbuf *m; 22938962Skarels int off0, wait; 2304927Swnj register int len; 2314927Swnj { 2324927Swnj register struct mbuf *n, **np; 23338962Skarels register int off = off0; 23438962Skarels struct mbuf *top; 23538962Skarels int copyhdr = 0; 2364927Swnj 2374927Swnj if (off < 0 || len < 0) 23838962Skarels panic("m_copym"); 23938962Skarels if (off == 0 && m->m_flags & M_PKTHDR) 24038962Skarels copyhdr = 1; 2414927Swnj while (off > 0) { 2424927Swnj if (m == 0) 24338962Skarels panic("m_copym"); 2444927Swnj if (off < m->m_len) 2454927Swnj break; 2464927Swnj off -= m->m_len; 2474927Swnj m = m->m_next; 2484927Swnj } 2494927Swnj np = ⊤ 2504927Swnj top = 0; 2514927Swnj while (len > 0) { 2525609Swnj if (m == 0) { 2535609Swnj if (len != M_COPYALL) 25438962Skarels panic("m_copym"); 2555609Swnj break; 2565609Swnj } 25738962Skarels MGET(n, wait, m->m_type); 2584927Swnj *np = n; 2594927Swnj if (n == 0) 2604927Swnj goto nospace; 26138962Skarels if (copyhdr) { 26238962Skarels M_COPY_PKTHDR(n, m); 26338962Skarels if (len == M_COPYALL) 26438962Skarels n->m_pkthdr.len -= off0; 26538962Skarels else 26638962Skarels n->m_pkthdr.len = len; 26738962Skarels copyhdr = 0; 26838962Skarels } 2694927Swnj n->m_len = MIN(len, m->m_len - off); 27038962Skarels if (m->m_flags & M_EXT) { 27138962Skarels n->m_data = m->m_data + off; 27238962Skarels mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 27338962Skarels n->m_ext = m->m_ext; 27438962Skarels n->m_flags |= M_EXT; 2758318Sroot } else 2764927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2774927Swnj (unsigned)n->m_len); 2785609Swnj if (len != M_COPYALL) 2795609Swnj len -= n->m_len; 2804927Swnj off = 0; 2814927Swnj m = m->m_next; 2824927Swnj np = &n->m_next; 2834927Swnj } 28441999Smckusick if (top == 0) 28541999Smckusick MCFail++; 2864927Swnj return (top); 2874927Swnj nospace: 2884927Swnj m_freem(top); 28941999Smckusick MCFail++; 2904927Swnj return (0); 2914927Swnj } 2924927Swnj 29333606Skarels /* 29433606Skarels * Copy data from an mbuf chain starting "off" bytes from the beginning, 29533606Skarels * continuing for "len" bytes, into the indicated buffer. 29633606Skarels */ 29733606Skarels m_copydata(m, off, len, cp) 29833606Skarels register struct mbuf *m; 29933988Skarels register int off; 30033606Skarels register int len; 30133988Skarels caddr_t cp; 30233606Skarels { 30333606Skarels register unsigned count; 30433606Skarels 30533606Skarels if (off < 0 || len < 0) 30633606Skarels panic("m_copydata"); 30733606Skarels while (off > 0) { 30833606Skarels if (m == 0) 30933606Skarels panic("m_copydata"); 31033606Skarels if (off < m->m_len) 31133606Skarels break; 31233606Skarels off -= m->m_len; 31333606Skarels m = m->m_next; 31433606Skarels } 31533606Skarels while (len > 0) { 31633606Skarels if (m == 0) 31733606Skarels panic("m_copydata"); 31833988Skarels count = MIN(m->m_len - off, len); 31933606Skarels bcopy(mtod(m, caddr_t) + off, cp, count); 32033606Skarels len -= count; 32133988Skarels cp += count; 32233606Skarels off = 0; 32333606Skarels m = m->m_next; 32433606Skarels } 32533606Skarels } 32633606Skarels 32738962Skarels /* 32838962Skarels * Concatenate mbuf chain n to m. 32938962Skarels * Both chains must be of the same type (e.g. MT_DATA). 33038962Skarels * Any m_pkthdr is not updated. 33138962Skarels */ 3324669Swnj m_cat(m, n) 3334669Swnj register struct mbuf *m, *n; 3344669Swnj { 3354669Swnj while (m->m_next) 3364669Swnj m = m->m_next; 3376091Sroot while (n) { 33838962Skarels if (m->m_flags & M_EXT || 33938962Skarels m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 3406091Sroot /* just join the two chains */ 3414669Swnj m->m_next = n; 3426091Sroot return; 3434669Swnj } 3446091Sroot /* splat the data from one into the other */ 3456091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 3466091Sroot (u_int)n->m_len); 3476091Sroot m->m_len += n->m_len; 3486091Sroot n = m_free(n); 3496091Sroot } 3504669Swnj } 3514669Swnj 35238962Skarels m_adj(mp, req_len) 3534585Swnj struct mbuf *mp; 3544585Swnj { 35538962Skarels register int len = req_len; 35624764Skarels register struct mbuf *m; 35724764Skarels register count; 3584585Swnj 3594585Swnj if ((m = mp) == NULL) 3604585Swnj return; 3614822Swnj if (len >= 0) { 36238962Skarels /* 36338962Skarels * Trim from head. 36438962Skarels */ 3654585Swnj while (m != NULL && len > 0) { 3664822Swnj if (m->m_len <= len) { 3674585Swnj len -= m->m_len; 3684585Swnj m->m_len = 0; 3694585Swnj m = m->m_next; 3704822Swnj } else { 3714585Swnj m->m_len -= len; 37238962Skarels m->m_data += len; 37338962Skarels len = 0; 3744585Swnj } 3754585Swnj } 37638962Skarels m = mp; 37738962Skarels if (mp->m_flags & M_PKTHDR) 37838962Skarels m->m_pkthdr.len -= (req_len - len); 3794822Swnj } else { 38024764Skarels /* 38124764Skarels * Trim from tail. Scan the mbuf chain, 38224764Skarels * calculating its length and finding the last mbuf. 38324764Skarels * If the adjustment only affects this mbuf, then just 38424764Skarels * adjust and return. Otherwise, rescan and truncate 38524764Skarels * after the remaining size. 38624764Skarels */ 3874585Swnj len = -len; 38824764Skarels count = 0; 38924764Skarels for (;;) { 39024764Skarels count += m->m_len; 39124764Skarels if (m->m_next == (struct mbuf *)0) 3924585Swnj break; 39324764Skarels m = m->m_next; 39424764Skarels } 39524764Skarels if (m->m_len >= len) { 39624764Skarels m->m_len -= len; 39739227Ssklower if ((mp = m)->m_flags & M_PKTHDR) 39839227Ssklower m->m_pkthdr.len -= len; 39924764Skarels return; 40024764Skarels } 40124764Skarels count -= len; 40238962Skarels if (count < 0) 40338962Skarels count = 0; 40424764Skarels /* 40524764Skarels * Correct length for chain is "count". 40624764Skarels * Find the mbuf with last data, adjust its length, 40724764Skarels * and toss data from remaining mbufs on chain. 40824764Skarels */ 40938962Skarels m = mp; 41038962Skarels if (m->m_flags & M_PKTHDR) 41138962Skarels m->m_pkthdr.len = count; 41238962Skarels for (; m; m = m->m_next) { 41324764Skarels if (m->m_len >= count) { 41424764Skarels m->m_len = count; 41524764Skarels break; 4164585Swnj } 41724764Skarels count -= m->m_len; 4184585Swnj } 41924764Skarels while (m = m->m_next) 42024764Skarels m->m_len = 0; 4214585Swnj } 4224585Swnj } 4235228Swnj 42423816Skarels /* 42523816Skarels * Rearange an mbuf chain so that len bytes are contiguous 42623816Skarels * and in the data area of an mbuf (so that mtod and dtom 42724764Skarels * will work for a structure of size len). Returns the resulting 42824764Skarels * mbuf chain on success, frees it and returns null on failure. 42938962Skarels * If there is room, it will add up to max_protohdr-len extra bytes to the 43024764Skarels * contiguous region in an attempt to avoid being called next time. 43123816Skarels */ 43241999Smckusick int MPFail; 43341999Smckusick 4345310Sroot struct mbuf * 43524764Skarels m_pullup(n, len) 43624764Skarels register struct mbuf *n; 4375228Swnj int len; 4385228Swnj { 43924764Skarels register struct mbuf *m; 44024764Skarels register int count; 44124764Skarels int space; 4425228Swnj 44338962Skarels /* 44438962Skarels * If first mbuf has no cluster, and has room for len bytes 44538962Skarels * without shifting current data, pullup into it, 44638962Skarels * otherwise allocate a new mbuf to prepend to the chain. 44738962Skarels */ 44838962Skarels if ((n->m_flags & M_EXT) == 0 && 44938962Skarels n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 45038962Skarels if (n->m_len >= len) 45138962Skarels return (n); 45224764Skarels m = n; 45324764Skarels n = n->m_next; 45424764Skarels len -= m->m_len; 45524764Skarels } else { 45638962Skarels if (len > MHLEN) 45724764Skarels goto bad; 45824764Skarels MGET(m, M_DONTWAIT, n->m_type); 45924764Skarels if (m == 0) 46024764Skarels goto bad; 46124764Skarels m->m_len = 0; 46244969Skarels if (n->m_flags & M_PKTHDR) { 46338962Skarels M_COPY_PKTHDR(m, n); 46444969Skarels n->m_flags &= ~M_PKTHDR; 46544969Skarels } 46624764Skarels } 46738962Skarels space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 4685310Sroot do { 46938962Skarels count = min(min(max(len, max_protohdr), space), n->m_len); 47038962Skarels bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 4716164Ssam (unsigned)count); 4726164Ssam len -= count; 4736164Ssam m->m_len += count; 4746164Ssam n->m_len -= count; 47538962Skarels space -= count; 4765310Sroot if (n->m_len) 47738962Skarels n->m_data += count; 47823816Skarels else 47923816Skarels n = m_free(n); 48024764Skarels } while (len > 0 && n); 48124764Skarels if (len > 0) { 4825310Sroot (void) m_free(m); 4835310Sroot goto bad; 4845310Sroot } 4855310Sroot m->m_next = n; 4865310Sroot return (m); 4875310Sroot bad: 4885732Sroot m_freem(n); 48941999Smckusick MPFail++; 4905228Swnj return (0); 4915228Swnj } 49250941Ssklower 49350941Ssklower /* 49450941Ssklower * Partition an mbuf chain in two pieces, returning the tail -- 49550941Ssklower * all but the first len0 bytes. In case of failure, it returns NULL and 49650941Ssklower * attempts to restore the chain to its original state. 49750941Ssklower */ 49850941Ssklower struct mbuf * 49950941Ssklower m_split(m0, len0, wait) 50050941Ssklower register struct mbuf *m0; 50150941Ssklower int len0; 50250941Ssklower { 50350941Ssklower register struct mbuf *m, *n; 50450941Ssklower unsigned len = len0, remain; 50550941Ssklower 50650941Ssklower for (m = m0; m && len > m->m_len; m = m->m_next) 50750941Ssklower len -= m->m_len; 50850941Ssklower if (m == 0) 50950941Ssklower return (0); 51050941Ssklower remain = m->m_len - len; 51150941Ssklower if (m0->m_flags & M_PKTHDR) { 51250941Ssklower MGETHDR(n, wait, m0->m_type); 51350941Ssklower if (n == 0) 51450941Ssklower return (0); 51550941Ssklower n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 51650941Ssklower n->m_pkthdr.len = m0->m_pkthdr.len - len0; 51750941Ssklower m0->m_pkthdr.len = len0; 51850941Ssklower if (m->m_flags & M_EXT) 51950941Ssklower goto extpacket; 52050941Ssklower if (remain > MHLEN) { 52150941Ssklower /* m can't be the lead packet */ 52250941Ssklower MH_ALIGN(n, 0); 52350941Ssklower n->m_next = m_split(m, len, wait); 52450941Ssklower if (n->m_next == 0) { 52550941Ssklower (void) m_free(n); 52650941Ssklower return (0); 52750941Ssklower } else 52850941Ssklower return (n); 52950941Ssklower } else 53050941Ssklower MH_ALIGN(n, remain); 53150941Ssklower } else if (remain == 0) { 53250941Ssklower n = m->m_next; 53350941Ssklower m->m_next = 0; 53450941Ssklower return (n); 53550941Ssklower } else { 53650941Ssklower MGET(n, wait, m->m_type); 53750941Ssklower if (n == 0) 53850941Ssklower return (0); 53950941Ssklower M_ALIGN(n, remain); 54050941Ssklower } 54150941Ssklower extpacket: 54250941Ssklower if (m->m_flags & M_EXT) { 54350941Ssklower n->m_flags |= M_EXT; 54450941Ssklower n->m_ext = m->m_ext; 54550941Ssklower mclrefcnt[mtocl(m->m_ext.ext_buf)]++; 54650941Ssklower m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ 54750941Ssklower n->m_data = m->m_data + len; 54850941Ssklower } else { 54950941Ssklower bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); 55050941Ssklower } 55150941Ssklower n->m_len = remain; 55250941Ssklower m->m_len = len; 55350941Ssklower n->m_next = m->m_next; 55450941Ssklower m->m_next = 0; 55550941Ssklower return (n); 55650941Ssklower } 55750941Ssklower /* 55850941Ssklower * Routine to copy from device local memory into mbufs. 55950941Ssklower */ 56050941Ssklower struct mbuf * 56150941Ssklower m_devget(buf, totlen, off0, ifp, copy) 56250941Ssklower char *buf; 56350941Ssklower int totlen, off0; 56450941Ssklower struct ifnet *ifp; 56550941Ssklower void (*copy)(); 56650941Ssklower { 56750941Ssklower register struct mbuf *m; 56850941Ssklower struct mbuf *top = 0, **mp = ⊤ 56950941Ssklower register int off = off0, len; 57050941Ssklower register char *cp; 57150941Ssklower char *epkt; 57250941Ssklower 57350941Ssklower cp = buf; 57450941Ssklower epkt = cp + totlen; 57550941Ssklower if (off) { 57650941Ssklower cp += off + 2 * sizeof(u_short); 57750941Ssklower totlen -= 2 * sizeof(u_short); 57850941Ssklower } 57950941Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 58050941Ssklower if (m == 0) 58150941Ssklower return (0); 58250941Ssklower m->m_pkthdr.rcvif = ifp; 58350941Ssklower m->m_pkthdr.len = totlen; 58450941Ssklower m->m_len = MHLEN; 58550941Ssklower 58650941Ssklower while (totlen > 0) { 58750941Ssklower if (top) { 58850941Ssklower MGET(m, M_DONTWAIT, MT_DATA); 58950941Ssklower if (m == 0) { 59050941Ssklower m_freem(top); 59150941Ssklower return (0); 59250941Ssklower } 59350941Ssklower m->m_len = MLEN; 59450941Ssklower } 59550941Ssklower len = min(totlen, epkt - cp); 59650941Ssklower if (len >= MINCLSIZE) { 59750941Ssklower MCLGET(m, M_DONTWAIT); 59850941Ssklower if (m->m_flags & M_EXT) 59950941Ssklower m->m_len = len = min(len, MCLBYTES); 60050941Ssklower else 60150941Ssklower len = m->m_len; 60250941Ssklower } else { 60350941Ssklower /* 60450941Ssklower * Place initial small packet/header at end of mbuf. 60550941Ssklower */ 60650941Ssklower if (len < m->m_len) { 60750941Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 60850941Ssklower m->m_data += max_linkhdr; 60950941Ssklower m->m_len = len; 61050941Ssklower } else 61150941Ssklower len = m->m_len; 61250941Ssklower } 61350941Ssklower if (copy) 61450941Ssklower copy(cp, mtod(m, caddr_t), (unsigned)len); 61550941Ssklower else 61650941Ssklower bcopy(cp, mtod(m, caddr_t), (unsigned)len); 61750941Ssklower cp += len; 61850941Ssklower *mp = m; 61950941Ssklower mp = &m->m_next; 62050941Ssklower totlen -= len; 62150941Ssklower if (cp == epkt) 62250941Ssklower cp = buf; 62350941Ssklower } 62450941Ssklower return (top); 62550941Ssklower } 626