Home | History | Annotate | Line # | Download | only in kern
uipc_mbuf.c revision 1.15.4.1
      1  1.15.4.1       cgd /*	$NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $	*/
      2      1.10       cgd 
      3       1.1       cgd /*
      4       1.9   mycroft  * Copyright (c) 1982, 1986, 1988, 1991, 1993
      5       1.9   mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15       1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16       1.1       cgd  *    must display the following acknowledgement:
     17       1.1       cgd  *	This product includes software developed by the University of
     18       1.1       cgd  *	California, Berkeley and its contributors.
     19       1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20       1.1       cgd  *    may be used to endorse or promote products derived from this software
     21       1.1       cgd  *    without specific prior written permission.
     22       1.1       cgd  *
     23       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.1       cgd  * SUCH DAMAGE.
     34       1.1       cgd  *
     35      1.10       cgd  *	@(#)uipc_mbuf.c	8.2 (Berkeley) 1/4/94
     36       1.1       cgd  */
     37       1.1       cgd 
     38       1.6   mycroft #include <sys/param.h>
     39       1.6   mycroft #include <sys/systm.h>
     40       1.6   mycroft #include <sys/proc.h>
     41       1.6   mycroft #include <sys/malloc.h>
     42       1.9   mycroft #include <sys/map.h>
     43       1.1       cgd #define MBTYPES
     44       1.6   mycroft #include <sys/mbuf.h>
     45       1.6   mycroft #include <sys/kernel.h>
     46       1.6   mycroft #include <sys/syslog.h>
     47       1.6   mycroft #include <sys/domain.h>
     48       1.6   mycroft #include <sys/protosw.h>
     49       1.6   mycroft 
     50       1.6   mycroft #include <vm/vm.h>
     51      1.14  christos 
     52       1.1       cgd extern	vm_map_t mb_map;
     53       1.1       cgd struct	mbuf *mbutl;
     54       1.1       cgd char	*mclrefcnt;
     55       1.1       cgd 
     56       1.4       jtc void
     57       1.1       cgd mbinit()
     58       1.1       cgd {
     59       1.1       cgd 	int s;
     60       1.1       cgd 
     61       1.1       cgd 	s = splimp();
     62      1.12   deraadt 	if (m_clalloc(max(4096/CLBYTES, 1), M_DONTWAIT) == 0)
     63       1.1       cgd 		goto bad;
     64       1.1       cgd 	splx(s);
     65       1.1       cgd 	return;
     66       1.1       cgd bad:
     67       1.1       cgd 	panic("mbinit");
     68       1.1       cgd }
     69       1.1       cgd 
     70       1.1       cgd /*
     71       1.1       cgd  * Allocate some number of mbuf clusters
     72       1.1       cgd  * and place on cluster free list.
     73       1.1       cgd  * Must be called at splimp.
     74       1.1       cgd  */
     75       1.1       cgd /* ARGSUSED */
     76      1.14  christos int
     77       1.5       cgd m_clalloc(ncl, nowait)
     78       1.1       cgd 	register int ncl;
     79       1.9   mycroft 	int nowait;
     80       1.1       cgd {
     81  1.15.4.1       cgd 	volatile static struct timeval lastlogged;
     82  1.15.4.1       cgd 	struct timeval curtime, logdiff;
     83       1.1       cgd 	register caddr_t p;
     84       1.1       cgd 	register int i;
     85  1.15.4.1       cgd 	int npg, s;
     86       1.1       cgd 
     87       1.1       cgd 	npg = ncl * CLSIZE;
     88       1.5       cgd 	p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
     89       1.1       cgd 	if (p == NULL) {
     90  1.15.4.1       cgd 		s = splclock();
     91  1.15.4.1       cgd 		curtime = time;
     92  1.15.4.1       cgd 		splx(s);
     93  1.15.4.1       cgd 		timersub(&curtime, &lastlogged, &logdiff);
     94  1.15.4.1       cgd 		if (logdiff.tv_sec >= 60) {
     95  1.15.4.1       cgd 			lastlogged = curtime;
     96       1.1       cgd 			log(LOG_ERR, "mb_map full\n");
     97       1.1       cgd 		}
     98  1.15.4.1       cgd 		m_reclaim();
     99  1.15.4.1       cgd 		return (mclfree != NULL);
    100       1.1       cgd 	}
    101       1.1       cgd 	ncl = ncl * CLBYTES / MCLBYTES;
    102       1.1       cgd 	for (i = 0; i < ncl; i++) {
    103       1.1       cgd 		((union mcluster *)p)->mcl_next = mclfree;
    104       1.1       cgd 		mclfree = (union mcluster *)p;
    105       1.1       cgd 		p += MCLBYTES;
    106       1.1       cgd 		mbstat.m_clfree++;
    107       1.1       cgd 	}
    108       1.1       cgd 	mbstat.m_clusters += ncl;
    109       1.1       cgd 	return (1);
    110       1.1       cgd }
    111       1.1       cgd 
    112       1.1       cgd /*
    113       1.1       cgd  * When MGET failes, ask protocols to free space when short of memory,
    114       1.1       cgd  * then re-attempt to allocate an mbuf.
    115       1.1       cgd  */
    116       1.1       cgd struct mbuf *
    117       1.1       cgd m_retry(i, t)
    118       1.1       cgd 	int i, t;
    119       1.1       cgd {
    120       1.1       cgd 	register struct mbuf *m;
    121       1.1       cgd 
    122       1.1       cgd 	m_reclaim();
    123       1.1       cgd #define m_retry(i, t)	(struct mbuf *)0
    124       1.1       cgd 	MGET(m, i, t);
    125       1.1       cgd #undef m_retry
    126       1.1       cgd 	return (m);
    127       1.1       cgd }
    128       1.1       cgd 
    129       1.1       cgd /*
    130       1.1       cgd  * As above; retry an MGETHDR.
    131       1.1       cgd  */
    132       1.1       cgd struct mbuf *
    133       1.1       cgd m_retryhdr(i, t)
    134       1.1       cgd 	int i, t;
    135       1.1       cgd {
    136       1.1       cgd 	register struct mbuf *m;
    137       1.1       cgd 
    138       1.1       cgd 	m_reclaim();
    139       1.1       cgd #define m_retryhdr(i, t) (struct mbuf *)0
    140       1.1       cgd 	MGETHDR(m, i, t);
    141       1.1       cgd #undef m_retryhdr
    142       1.1       cgd 	return (m);
    143       1.1       cgd }
    144       1.1       cgd 
    145      1.14  christos void
    146       1.1       cgd m_reclaim()
    147       1.1       cgd {
    148       1.1       cgd 	register struct domain *dp;
    149       1.1       cgd 	register struct protosw *pr;
    150       1.1       cgd 	int s = splimp();
    151       1.1       cgd 
    152       1.1       cgd 	for (dp = domains; dp; dp = dp->dom_next)
    153       1.1       cgd 		for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
    154       1.1       cgd 			if (pr->pr_drain)
    155       1.1       cgd 				(*pr->pr_drain)();
    156       1.1       cgd 	splx(s);
    157       1.1       cgd 	mbstat.m_drain++;
    158       1.1       cgd }
    159       1.1       cgd 
    160       1.1       cgd /*
    161       1.1       cgd  * Space allocation routines.
    162       1.1       cgd  * These are also available as macros
    163       1.1       cgd  * for critical paths.
    164       1.1       cgd  */
    165       1.1       cgd struct mbuf *
    166       1.5       cgd m_get(nowait, type)
    167       1.5       cgd 	int nowait, type;
    168       1.1       cgd {
    169       1.1       cgd 	register struct mbuf *m;
    170       1.1       cgd 
    171       1.5       cgd 	MGET(m, nowait, type);
    172       1.1       cgd 	return (m);
    173       1.1       cgd }
    174       1.1       cgd 
    175       1.1       cgd struct mbuf *
    176       1.5       cgd m_gethdr(nowait, type)
    177       1.5       cgd 	int nowait, type;
    178       1.1       cgd {
    179       1.1       cgd 	register struct mbuf *m;
    180       1.1       cgd 
    181       1.5       cgd 	MGETHDR(m, nowait, type);
    182       1.1       cgd 	return (m);
    183       1.1       cgd }
    184       1.1       cgd 
    185       1.1       cgd struct mbuf *
    186       1.5       cgd m_getclr(nowait, type)
    187       1.5       cgd 	int nowait, type;
    188       1.1       cgd {
    189       1.1       cgd 	register struct mbuf *m;
    190       1.1       cgd 
    191       1.5       cgd 	MGET(m, nowait, type);
    192       1.1       cgd 	if (m == 0)
    193       1.1       cgd 		return (0);
    194       1.1       cgd 	bzero(mtod(m, caddr_t), MLEN);
    195       1.1       cgd 	return (m);
    196       1.1       cgd }
    197       1.1       cgd 
    198       1.1       cgd struct mbuf *
    199       1.1       cgd m_free(m)
    200       1.1       cgd 	struct mbuf *m;
    201       1.1       cgd {
    202       1.1       cgd 	register struct mbuf *n;
    203       1.1       cgd 
    204       1.1       cgd 	MFREE(m, n);
    205       1.1       cgd 	return (n);
    206       1.1       cgd }
    207       1.1       cgd 
    208       1.9   mycroft void
    209       1.1       cgd m_freem(m)
    210       1.1       cgd 	register struct mbuf *m;
    211       1.1       cgd {
    212       1.1       cgd 	register struct mbuf *n;
    213       1.1       cgd 
    214       1.1       cgd 	if (m == NULL)
    215       1.1       cgd 		return;
    216       1.1       cgd 	do {
    217       1.1       cgd 		MFREE(m, n);
    218      1.14  christos 	} while ((m = n) != NULL);
    219       1.1       cgd }
    220       1.1       cgd 
    221       1.1       cgd /*
    222       1.1       cgd  * Mbuffer utility routines.
    223       1.1       cgd  */
    224       1.1       cgd 
    225       1.1       cgd /*
    226       1.1       cgd  * Lesser-used path for M_PREPEND:
    227       1.1       cgd  * allocate new mbuf to prepend to chain,
    228       1.1       cgd  * copy junk along.
    229       1.1       cgd  */
    230       1.1       cgd struct mbuf *
    231       1.9   mycroft m_prepend(m, len, how)
    232       1.1       cgd 	register struct mbuf *m;
    233       1.9   mycroft 	int len, how;
    234       1.1       cgd {
    235       1.1       cgd 	struct mbuf *mn;
    236       1.1       cgd 
    237       1.9   mycroft 	MGET(mn, how, m->m_type);
    238       1.1       cgd 	if (mn == (struct mbuf *)NULL) {
    239       1.1       cgd 		m_freem(m);
    240       1.1       cgd 		return ((struct mbuf *)NULL);
    241       1.1       cgd 	}
    242       1.1       cgd 	if (m->m_flags & M_PKTHDR) {
    243       1.1       cgd 		M_COPY_PKTHDR(mn, m);
    244       1.1       cgd 		m->m_flags &= ~M_PKTHDR;
    245       1.1       cgd 	}
    246       1.1       cgd 	mn->m_next = m;
    247       1.1       cgd 	m = mn;
    248       1.1       cgd 	if (len < MHLEN)
    249       1.1       cgd 		MH_ALIGN(m, len);
    250       1.1       cgd 	m->m_len = len;
    251       1.1       cgd 	return (m);
    252       1.1       cgd }
    253       1.1       cgd 
    254       1.1       cgd /*
    255       1.1       cgd  * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
    256       1.1       cgd  * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
    257       1.1       cgd  * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
    258       1.1       cgd  */
    259       1.1       cgd int MCFail;
    260       1.1       cgd 
    261       1.1       cgd struct mbuf *
    262       1.1       cgd m_copym(m, off0, len, wait)
    263       1.1       cgd 	register struct mbuf *m;
    264       1.1       cgd 	int off0, wait;
    265       1.1       cgd 	register int len;
    266       1.1       cgd {
    267       1.1       cgd 	register struct mbuf *n, **np;
    268       1.1       cgd 	register int off = off0;
    269       1.1       cgd 	struct mbuf *top;
    270       1.1       cgd 	int copyhdr = 0;
    271       1.1       cgd 
    272       1.1       cgd 	if (off < 0 || len < 0)
    273       1.1       cgd 		panic("m_copym");
    274       1.1       cgd 	if (off == 0 && m->m_flags & M_PKTHDR)
    275       1.1       cgd 		copyhdr = 1;
    276       1.1       cgd 	while (off > 0) {
    277       1.1       cgd 		if (m == 0)
    278       1.1       cgd 			panic("m_copym");
    279       1.1       cgd 		if (off < m->m_len)
    280       1.1       cgd 			break;
    281       1.1       cgd 		off -= m->m_len;
    282       1.1       cgd 		m = m->m_next;
    283       1.1       cgd 	}
    284       1.1       cgd 	np = &top;
    285       1.1       cgd 	top = 0;
    286       1.1       cgd 	while (len > 0) {
    287       1.1       cgd 		if (m == 0) {
    288       1.1       cgd 			if (len != M_COPYALL)
    289       1.1       cgd 				panic("m_copym");
    290       1.1       cgd 			break;
    291       1.1       cgd 		}
    292       1.1       cgd 		MGET(n, wait, m->m_type);
    293       1.1       cgd 		*np = n;
    294       1.1       cgd 		if (n == 0)
    295       1.1       cgd 			goto nospace;
    296       1.1       cgd 		if (copyhdr) {
    297       1.1       cgd 			M_COPY_PKTHDR(n, m);
    298       1.1       cgd 			if (len == M_COPYALL)
    299       1.1       cgd 				n->m_pkthdr.len -= off0;
    300       1.1       cgd 			else
    301       1.1       cgd 				n->m_pkthdr.len = len;
    302       1.1       cgd 			copyhdr = 0;
    303       1.1       cgd 		}
    304       1.9   mycroft 		n->m_len = min(len, m->m_len - off);
    305       1.1       cgd 		if (m->m_flags & M_EXT) {
    306       1.1       cgd 			n->m_data = m->m_data + off;
    307       1.1       cgd 			mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
    308       1.1       cgd 			n->m_ext = m->m_ext;
    309       1.1       cgd 			n->m_flags |= M_EXT;
    310       1.1       cgd 		} else
    311       1.1       cgd 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
    312       1.1       cgd 			    (unsigned)n->m_len);
    313       1.1       cgd 		if (len != M_COPYALL)
    314       1.1       cgd 			len -= n->m_len;
    315       1.1       cgd 		off = 0;
    316       1.1       cgd 		m = m->m_next;
    317       1.1       cgd 		np = &n->m_next;
    318       1.1       cgd 	}
    319       1.1       cgd 	if (top == 0)
    320       1.1       cgd 		MCFail++;
    321       1.1       cgd 	return (top);
    322       1.1       cgd nospace:
    323       1.1       cgd 	m_freem(top);
    324       1.1       cgd 	MCFail++;
    325       1.1       cgd 	return (0);
    326       1.1       cgd }
    327       1.1       cgd 
    328       1.1       cgd /*
    329       1.1       cgd  * Copy data from an mbuf chain starting "off" bytes from the beginning,
    330       1.1       cgd  * continuing for "len" bytes, into the indicated buffer.
    331       1.1       cgd  */
    332      1.14  christos void
    333       1.1       cgd m_copydata(m, off, len, cp)
    334       1.1       cgd 	register struct mbuf *m;
    335       1.1       cgd 	register int off;
    336       1.1       cgd 	register int len;
    337       1.1       cgd 	caddr_t cp;
    338       1.1       cgd {
    339       1.1       cgd 	register unsigned count;
    340       1.1       cgd 
    341       1.1       cgd 	if (off < 0 || len < 0)
    342       1.1       cgd 		panic("m_copydata");
    343       1.1       cgd 	while (off > 0) {
    344       1.1       cgd 		if (m == 0)
    345       1.1       cgd 			panic("m_copydata");
    346       1.1       cgd 		if (off < m->m_len)
    347       1.1       cgd 			break;
    348       1.1       cgd 		off -= m->m_len;
    349       1.1       cgd 		m = m->m_next;
    350       1.1       cgd 	}
    351       1.1       cgd 	while (len > 0) {
    352       1.1       cgd 		if (m == 0)
    353       1.1       cgd 			panic("m_copydata");
    354       1.9   mycroft 		count = min(m->m_len - off, len);
    355       1.1       cgd 		bcopy(mtod(m, caddr_t) + off, cp, count);
    356       1.1       cgd 		len -= count;
    357       1.1       cgd 		cp += count;
    358       1.1       cgd 		off = 0;
    359       1.1       cgd 		m = m->m_next;
    360       1.1       cgd 	}
    361       1.1       cgd }
    362       1.1       cgd 
    363       1.1       cgd /*
    364       1.1       cgd  * Concatenate mbuf chain n to m.
    365       1.1       cgd  * Both chains must be of the same type (e.g. MT_DATA).
    366       1.1       cgd  * Any m_pkthdr is not updated.
    367       1.1       cgd  */
    368      1.14  christos void
    369       1.1       cgd m_cat(m, n)
    370       1.1       cgd 	register struct mbuf *m, *n;
    371       1.1       cgd {
    372       1.1       cgd 	while (m->m_next)
    373       1.1       cgd 		m = m->m_next;
    374       1.1       cgd 	while (n) {
    375       1.1       cgd 		if (m->m_flags & M_EXT ||
    376       1.1       cgd 		    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
    377       1.1       cgd 			/* just join the two chains */
    378       1.1       cgd 			m->m_next = n;
    379       1.1       cgd 			return;
    380       1.1       cgd 		}
    381       1.1       cgd 		/* splat the data from one into the other */
    382       1.1       cgd 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
    383       1.1       cgd 		    (u_int)n->m_len);
    384       1.1       cgd 		m->m_len += n->m_len;
    385       1.1       cgd 		n = m_free(n);
    386       1.1       cgd 	}
    387       1.1       cgd }
    388       1.1       cgd 
    389      1.11   mycroft void
    390       1.1       cgd m_adj(mp, req_len)
    391       1.1       cgd 	struct mbuf *mp;
    392       1.8   deraadt 	int req_len;
    393       1.1       cgd {
    394       1.1       cgd 	register int len = req_len;
    395       1.1       cgd 	register struct mbuf *m;
    396       1.1       cgd 	register count;
    397       1.1       cgd 
    398       1.1       cgd 	if ((m = mp) == NULL)
    399       1.1       cgd 		return;
    400       1.1       cgd 	if (len >= 0) {
    401       1.1       cgd 		/*
    402       1.1       cgd 		 * Trim from head.
    403       1.1       cgd 		 */
    404       1.1       cgd 		while (m != NULL && len > 0) {
    405       1.1       cgd 			if (m->m_len <= len) {
    406       1.1       cgd 				len -= m->m_len;
    407       1.1       cgd 				m->m_len = 0;
    408       1.1       cgd 				m = m->m_next;
    409       1.1       cgd 			} else {
    410       1.1       cgd 				m->m_len -= len;
    411       1.1       cgd 				m->m_data += len;
    412       1.1       cgd 				len = 0;
    413       1.1       cgd 			}
    414       1.1       cgd 		}
    415       1.1       cgd 		m = mp;
    416       1.1       cgd 		if (mp->m_flags & M_PKTHDR)
    417       1.1       cgd 			m->m_pkthdr.len -= (req_len - len);
    418       1.1       cgd 	} else {
    419       1.1       cgd 		/*
    420       1.1       cgd 		 * Trim from tail.  Scan the mbuf chain,
    421       1.1       cgd 		 * calculating its length and finding the last mbuf.
    422       1.1       cgd 		 * If the adjustment only affects this mbuf, then just
    423       1.1       cgd 		 * adjust and return.  Otherwise, rescan and truncate
    424       1.1       cgd 		 * after the remaining size.
    425       1.1       cgd 		 */
    426       1.1       cgd 		len = -len;
    427       1.1       cgd 		count = 0;
    428       1.1       cgd 		for (;;) {
    429       1.1       cgd 			count += m->m_len;
    430       1.1       cgd 			if (m->m_next == (struct mbuf *)0)
    431       1.1       cgd 				break;
    432       1.1       cgd 			m = m->m_next;
    433       1.1       cgd 		}
    434       1.1       cgd 		if (m->m_len >= len) {
    435       1.1       cgd 			m->m_len -= len;
    436       1.8   deraadt 			if (mp->m_flags & M_PKTHDR)
    437       1.8   deraadt 				mp->m_pkthdr.len -= len;
    438       1.1       cgd 			return;
    439       1.1       cgd 		}
    440       1.1       cgd 		count -= len;
    441       1.1       cgd 		if (count < 0)
    442       1.1       cgd 			count = 0;
    443       1.1       cgd 		/*
    444       1.1       cgd 		 * Correct length for chain is "count".
    445       1.1       cgd 		 * Find the mbuf with last data, adjust its length,
    446       1.1       cgd 		 * and toss data from remaining mbufs on chain.
    447       1.1       cgd 		 */
    448       1.1       cgd 		m = mp;
    449       1.1       cgd 		if (m->m_flags & M_PKTHDR)
    450       1.1       cgd 			m->m_pkthdr.len = count;
    451       1.1       cgd 		for (; m; m = m->m_next) {
    452       1.1       cgd 			if (m->m_len >= count) {
    453       1.1       cgd 				m->m_len = count;
    454       1.1       cgd 				break;
    455       1.1       cgd 			}
    456       1.1       cgd 			count -= m->m_len;
    457       1.1       cgd 		}
    458      1.14  christos 		while ((m = m->m_next) != NULL)
    459       1.1       cgd 			m->m_len = 0;
    460       1.1       cgd 	}
    461       1.1       cgd }
    462       1.1       cgd 
    463       1.1       cgd /*
    464       1.1       cgd  * Rearange an mbuf chain so that len bytes are contiguous
    465       1.1       cgd  * and in the data area of an mbuf (so that mtod and dtom
    466       1.1       cgd  * will work for a structure of size len).  Returns the resulting
    467       1.1       cgd  * mbuf chain on success, frees it and returns null on failure.
    468       1.1       cgd  * If there is room, it will add up to max_protohdr-len extra bytes to the
    469       1.1       cgd  * contiguous region in an attempt to avoid being called next time.
    470       1.1       cgd  */
    471       1.1       cgd int MPFail;
    472       1.1       cgd 
    473       1.1       cgd struct mbuf *
    474       1.1       cgd m_pullup(n, len)
    475       1.1       cgd 	register struct mbuf *n;
    476       1.1       cgd 	int len;
    477       1.1       cgd {
    478       1.1       cgd 	register struct mbuf *m;
    479       1.1       cgd 	register int count;
    480       1.1       cgd 	int space;
    481       1.1       cgd 
    482       1.1       cgd 	/*
    483       1.1       cgd 	 * If first mbuf has no cluster, and has room for len bytes
    484       1.1       cgd 	 * without shifting current data, pullup into it,
    485       1.1       cgd 	 * otherwise allocate a new mbuf to prepend to the chain.
    486       1.1       cgd 	 */
    487       1.1       cgd 	if ((n->m_flags & M_EXT) == 0 &&
    488       1.1       cgd 	    n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
    489       1.1       cgd 		if (n->m_len >= len)
    490       1.1       cgd 			return (n);
    491       1.1       cgd 		m = n;
    492       1.1       cgd 		n = n->m_next;
    493       1.1       cgd 		len -= m->m_len;
    494       1.1       cgd 	} else {
    495       1.1       cgd 		if (len > MHLEN)
    496       1.1       cgd 			goto bad;
    497       1.1       cgd 		MGET(m, M_DONTWAIT, n->m_type);
    498       1.1       cgd 		if (m == 0)
    499       1.1       cgd 			goto bad;
    500       1.1       cgd 		m->m_len = 0;
    501       1.1       cgd 		if (n->m_flags & M_PKTHDR) {
    502       1.1       cgd 			M_COPY_PKTHDR(m, n);
    503       1.1       cgd 			n->m_flags &= ~M_PKTHDR;
    504       1.1       cgd 		}
    505       1.1       cgd 	}
    506       1.1       cgd 	space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
    507       1.1       cgd 	do {
    508       1.1       cgd 		count = min(min(max(len, max_protohdr), space), n->m_len);
    509       1.1       cgd 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
    510       1.1       cgd 		  (unsigned)count);
    511       1.1       cgd 		len -= count;
    512       1.1       cgd 		m->m_len += count;
    513       1.1       cgd 		n->m_len -= count;
    514       1.1       cgd 		space -= count;
    515       1.1       cgd 		if (n->m_len)
    516       1.1       cgd 			n->m_data += count;
    517       1.1       cgd 		else
    518       1.1       cgd 			n = m_free(n);
    519       1.1       cgd 	} while (len > 0 && n);
    520       1.1       cgd 	if (len > 0) {
    521       1.1       cgd 		(void) m_free(m);
    522       1.1       cgd 		goto bad;
    523       1.1       cgd 	}
    524       1.1       cgd 	m->m_next = n;
    525       1.1       cgd 	return (m);
    526       1.1       cgd bad:
    527       1.1       cgd 	m_freem(n);
    528       1.1       cgd 	MPFail++;
    529       1.1       cgd 	return (0);
    530       1.9   mycroft }
    531       1.9   mycroft 
    532       1.9   mycroft /*
    533       1.9   mycroft  * Partition an mbuf chain in two pieces, returning the tail --
    534       1.9   mycroft  * all but the first len0 bytes.  In case of failure, it returns NULL and
    535       1.9   mycroft  * attempts to restore the chain to its original state.
    536       1.9   mycroft  */
    537       1.9   mycroft struct mbuf *
    538       1.9   mycroft m_split(m0, len0, wait)
    539       1.9   mycroft 	register struct mbuf *m0;
    540       1.9   mycroft 	int len0, wait;
    541       1.9   mycroft {
    542       1.9   mycroft 	register struct mbuf *m, *n;
    543       1.9   mycroft 	unsigned len = len0, remain;
    544       1.9   mycroft 
    545       1.9   mycroft 	for (m = m0; m && len > m->m_len; m = m->m_next)
    546       1.9   mycroft 		len -= m->m_len;
    547       1.9   mycroft 	if (m == 0)
    548       1.9   mycroft 		return (0);
    549       1.9   mycroft 	remain = m->m_len - len;
    550       1.9   mycroft 	if (m0->m_flags & M_PKTHDR) {
    551       1.9   mycroft 		MGETHDR(n, wait, m0->m_type);
    552       1.9   mycroft 		if (n == 0)
    553       1.9   mycroft 			return (0);
    554       1.9   mycroft 		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
    555       1.9   mycroft 		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
    556       1.9   mycroft 		m0->m_pkthdr.len = len0;
    557       1.9   mycroft 		if (m->m_flags & M_EXT)
    558       1.9   mycroft 			goto extpacket;
    559       1.9   mycroft 		if (remain > MHLEN) {
    560       1.9   mycroft 			/* m can't be the lead packet */
    561       1.9   mycroft 			MH_ALIGN(n, 0);
    562       1.9   mycroft 			n->m_next = m_split(m, len, wait);
    563       1.9   mycroft 			if (n->m_next == 0) {
    564       1.9   mycroft 				(void) m_free(n);
    565       1.9   mycroft 				return (0);
    566       1.9   mycroft 			} else
    567       1.9   mycroft 				return (n);
    568       1.9   mycroft 		} else
    569       1.9   mycroft 			MH_ALIGN(n, remain);
    570       1.9   mycroft 	} else if (remain == 0) {
    571       1.9   mycroft 		n = m->m_next;
    572       1.9   mycroft 		m->m_next = 0;
    573       1.9   mycroft 		return (n);
    574       1.9   mycroft 	} else {
    575       1.9   mycroft 		MGET(n, wait, m->m_type);
    576       1.9   mycroft 		if (n == 0)
    577       1.9   mycroft 			return (0);
    578       1.9   mycroft 		M_ALIGN(n, remain);
    579       1.9   mycroft 	}
    580       1.9   mycroft extpacket:
    581       1.9   mycroft 	if (m->m_flags & M_EXT) {
    582       1.9   mycroft 		n->m_flags |= M_EXT;
    583       1.9   mycroft 		n->m_ext = m->m_ext;
    584       1.9   mycroft 		mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
    585       1.9   mycroft 		m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
    586       1.9   mycroft 		n->m_data = m->m_data + len;
    587       1.9   mycroft 	} else {
    588       1.9   mycroft 		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
    589       1.9   mycroft 	}
    590       1.9   mycroft 	n->m_len = remain;
    591       1.9   mycroft 	m->m_len = len;
    592       1.9   mycroft 	n->m_next = m->m_next;
    593       1.9   mycroft 	m->m_next = 0;
    594       1.9   mycroft 	return (n);
    595       1.9   mycroft }
    596       1.9   mycroft /*
    597       1.9   mycroft  * Routine to copy from device local memory into mbufs.
    598       1.9   mycroft  */
    599       1.9   mycroft struct mbuf *
    600       1.9   mycroft m_devget(buf, totlen, off0, ifp, copy)
    601       1.9   mycroft 	char *buf;
    602       1.9   mycroft 	int totlen, off0;
    603       1.9   mycroft 	struct ifnet *ifp;
    604      1.14  christos 	void (*copy) __P((const void *, void *, size_t));
    605       1.9   mycroft {
    606       1.9   mycroft 	register struct mbuf *m;
    607       1.9   mycroft 	struct mbuf *top = 0, **mp = &top;
    608       1.9   mycroft 	register int off = off0, len;
    609       1.9   mycroft 	register char *cp;
    610       1.9   mycroft 	char *epkt;
    611       1.9   mycroft 
    612       1.9   mycroft 	cp = buf;
    613       1.9   mycroft 	epkt = cp + totlen;
    614       1.9   mycroft 	if (off) {
    615      1.13       cgd 		/*
    616      1.13       cgd 		 * If 'off' is non-zero, packet is trailer-encapsulated,
    617      1.13       cgd 		 * so we have to skip the type and length fields.
    618      1.13       cgd 		 */
    619      1.13       cgd 		cp += off + 2 * sizeof(u_int16_t);
    620      1.13       cgd 		totlen -= 2 * sizeof(u_int16_t);
    621       1.9   mycroft 	}
    622       1.9   mycroft 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    623       1.9   mycroft 	if (m == 0)
    624       1.9   mycroft 		return (0);
    625       1.9   mycroft 	m->m_pkthdr.rcvif = ifp;
    626       1.9   mycroft 	m->m_pkthdr.len = totlen;
    627       1.9   mycroft 	m->m_len = MHLEN;
    628       1.9   mycroft 
    629       1.9   mycroft 	while (totlen > 0) {
    630       1.9   mycroft 		if (top) {
    631       1.9   mycroft 			MGET(m, M_DONTWAIT, MT_DATA);
    632       1.9   mycroft 			if (m == 0) {
    633       1.9   mycroft 				m_freem(top);
    634       1.9   mycroft 				return (0);
    635       1.9   mycroft 			}
    636       1.9   mycroft 			m->m_len = MLEN;
    637       1.9   mycroft 		}
    638       1.9   mycroft 		len = min(totlen, epkt - cp);
    639       1.9   mycroft 		if (len >= MINCLSIZE) {
    640       1.9   mycroft 			MCLGET(m, M_DONTWAIT);
    641       1.9   mycroft 			if (m->m_flags & M_EXT)
    642       1.9   mycroft 				m->m_len = len = min(len, MCLBYTES);
    643       1.9   mycroft 			else
    644       1.9   mycroft 				len = m->m_len;
    645       1.9   mycroft 		} else {
    646       1.9   mycroft 			/*
    647       1.9   mycroft 			 * Place initial small packet/header at end of mbuf.
    648       1.9   mycroft 			 */
    649       1.9   mycroft 			if (len < m->m_len) {
    650       1.9   mycroft 				if (top == 0 && len + max_linkhdr <= m->m_len)
    651       1.9   mycroft 					m->m_data += max_linkhdr;
    652       1.9   mycroft 				m->m_len = len;
    653       1.9   mycroft 			} else
    654       1.9   mycroft 				len = m->m_len;
    655       1.9   mycroft 		}
    656       1.9   mycroft 		if (copy)
    657      1.14  christos 			copy(cp, mtod(m, caddr_t), (size_t)len);
    658       1.9   mycroft 		else
    659      1.14  christos 			bcopy(cp, mtod(m, caddr_t), (size_t)len);
    660       1.9   mycroft 		cp += len;
    661       1.9   mycroft 		*mp = m;
    662       1.9   mycroft 		mp = &m->m_next;
    663       1.9   mycroft 		totlen -= len;
    664       1.9   mycroft 		if (cp == epkt)
    665       1.9   mycroft 			cp = buf;
    666       1.9   mycroft 	}
    667       1.9   mycroft 	return (top);
    668       1.1       cgd }
    669