mbuf.h revision 59382
1193323Sed/* 2193323Sed * Copyright (c) 1982, 1986, 1988, 1993 3193323Sed * The Regents of the University of California. All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 3. All advertising materials mentioning features or use of this software 14193323Sed * must display the following acknowledgement: 15193323Sed * This product includes software developed by the University of 16198090Srdivacky * California, Berkeley and its contributors. 17198090Srdivacky * 4. Neither the name of the University nor the names of its contributors 18193323Sed * may be used to endorse or promote products derived from this software 19193323Sed * without specific prior written permission. 20193323Sed * 21198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22218893Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25198090Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31193323Sed * SUCH DAMAGE. 32223017Sdim * 33193323Sed * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 34193323Sed * $FreeBSD: head/sys/sys/mbuf.h 59382 2000-04-19 01:24:26Z peter $ 35193323Sed */ 36193323Sed 37193323Sed#ifndef _SYS_MBUF_H_ 38193323Sed#define _SYS_MBUF_H_ 39193323Sed 40203954Srdivacky/* 41203954Srdivacky * Mbufs are of a single size, MSIZE (machine/param.h), which 42203954Srdivacky * includes overhead. An mbuf may add a single "mbuf cluster" of size 43203954Srdivacky * MCLBYTES (also in machine/param.h), which has no additional overhead 44203954Srdivacky * and is used instead of the internal data area; this is done when 45203954Srdivacky * at least MINCLSIZE of data must be stored. 46223017Sdim */ 47218893Sdim 48218893Sdim#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ 49218893Sdim#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ 50218893Sdim 51218893Sdim#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */ 52218893Sdim#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ 53223017Sdim 54203954Srdivacky/* 55198090Srdivacky * Macros for type conversion 56193323Sed * mtod(m, t) - convert mbuf pointer to data pointer of correct type 57203954Srdivacky * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX) 58198090Srdivacky * mtocl(x) - convert pointer within cluster to cluster index # 59218893Sdim * cltom(x) - convert cluster # to ptr to beginning of cluster 60218893Sdim */ 61218893Sdim#define mtod(m, t) ((t)((m)->m_data)) 62198892Srdivacky#define dtom(x) ((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1))) 63193323Sed#define mtocl(x) (((uintptr_t)(x) - (uintptr_t)mbutl) >> MCLSHIFT) 64193323Sed#define cltom(x) ((caddr_t)((uintptr_t)mbutl + \ 65203954Srdivacky ((uintptr_t)(x) << MCLSHIFT))) 66203954Srdivacky 67193323Sed/* header at beginning of each mbuf: */ 68193323Sedstruct m_hdr { 69193323Sed struct mbuf *mh_next; /* next buffer in chain */ 70193323Sed struct mbuf *mh_nextpkt; /* next chain in queue/record */ 71193323Sed caddr_t mh_data; /* location of data */ 72193323Sed int mh_len; /* amount of data in this mbuf */ 73193323Sed short mh_type; /* type of data in this mbuf */ 74193323Sed short mh_flags; /* flags; see below */ 75218893Sdim}; 76218893Sdim 77221345Sdim/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ 78221345Sdimstruct pkthdr { 79221345Sdim struct ifnet *rcvif; /* rcv interface */ 80221345Sdim int len; /* total packet length */ 81218893Sdim /* variables for ip and tcp reassembly */ 82218893Sdim caddr_t header; /* pointer to packet header */ 83218893Sdim /* variables for hardware checksum */ 84218893Sdim int csum_flags; /* flags regarding checksum */ 85206083Srdivacky int csum_data; /* data field used by csum routines */ 86218893Sdim}; 87218893Sdim 88206083Srdivacky/* description of external storage mapped into mbuf, valid if M_EXT set */ 89206083Srdivackystruct m_ext { 90206083Srdivacky caddr_t ext_buf; /* start of buffer */ 91206083Srdivacky void (*ext_free) /* free routine if not the usual */ 92206083Srdivacky __P((caddr_t, u_int)); 93218893Sdim u_int ext_size; /* size of buffer, for ext_free */ 94218893Sdim void (*ext_ref) /* add a reference to the ext object */ 95206083Srdivacky __P((caddr_t, u_int)); 96206083Srdivacky}; 97206083Srdivacky 98206083Srdivackystruct mbuf { 99206083Srdivacky struct m_hdr m_hdr; 100206083Srdivacky union { 101206083Srdivacky struct { 102206083Srdivacky struct pkthdr MH_pkthdr; /* M_PKTHDR set */ 103206083Srdivacky union { 104206083Srdivacky struct m_ext MH_ext; /* M_EXT set */ 105206083Srdivacky char MH_databuf[MHLEN]; 106206083Srdivacky } MH_dat; 107206083Srdivacky } MH; 108206083Srdivacky char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ 109206083Srdivacky } M_dat; 110206083Srdivacky}; 111206083Srdivacky#define m_next m_hdr.mh_next 112206083Srdivacky#define m_len m_hdr.mh_len 113206083Srdivacky#define m_data m_hdr.mh_data 114206083Srdivacky#define m_type m_hdr.mh_type 115206083Srdivacky#define m_flags m_hdr.mh_flags 116218893Sdim#define m_nextpkt m_hdr.mh_nextpkt 117206083Srdivacky#define m_act m_nextpkt 118193323Sed#define m_pkthdr M_dat.MH.MH_pkthdr 119193323Sed#define m_ext M_dat.MH.MH_dat.MH_ext 120203954Srdivacky#define m_pktdat M_dat.MH.MH_dat.MH_databuf 121218893Sdim#define m_dat M_dat.M_databuf 122193323Sed 123203954Srdivacky/* mbuf flags */ 124203954Srdivacky#define M_EXT 0x0001 /* has associated external storage */ 125193323Sed#define M_PKTHDR 0x0002 /* start of record */ 126203954Srdivacky#define M_EOR 0x0004 /* end of record */ 127203954Srdivacky#define M_PROTO1 0x0008 /* protocol-specific */ 128193323Sed#define M_PROTO2 0x0010 /* protocol-specific */ 129193323Sed#define M_PROTO3 0x0020 /* protocol-specific */ 130203954Srdivacky#define M_PROTO4 0x0040 /* protocol-specific */ 131193323Sed#define M_PROTO5 0x0080 /* protocol-specific */ 132193323Sed 133193323Sed/* mbuf pkthdr flags, also in m_flags */ 134193323Sed#define M_BCAST 0x0100 /* send/received as link-level broadcast */ 135203954Srdivacky#define M_MCAST 0x0200 /* send/received as link-level multicast */ 136193323Sed#define M_FRAG 0x0400 /* packet is a fragment of a larger packet */ 137193323Sed#define M_FIRSTFRAG 0x0800 /* packet is first fragment */ 138193323Sed#define M_LASTFRAG 0x1000 /* packet is last fragment */ 139193323Sed 140193323Sed/* flags copied when copying m_pkthdr */ 141193323Sed#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \ 142218893Sdim M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|M_FRAG) 143218893Sdim 144198892Srdivacky/* flags indicating hw checksum support and sw checksum requirements */ 145198090Srdivacky#define CSUM_IP 0x0001 /* will csum IP */ 146218893Sdim#define CSUM_TCP 0x0002 /* will csum TCP */ 147218893Sdim#define CSUM_UDP 0x0004 /* will csum UDP */ 148218893Sdim#define CSUM_IP_FRAGS 0x0008 /* will csum IP fragments */ 149198090Srdivacky#define CSUM_FRAGMENT 0x0010 /* will do IP fragmentation */ 150198090Srdivacky 151198090Srdivacky#define CSUM_IP_CHECKED 0x0100 /* did csum IP */ 152198090Srdivacky#define CSUM_IP_VALID 0x0200 /* ... the csum is valid */ 153198090Srdivacky#define CSUM_DATA_VALID 0x0400 /* csum_data field is valid */ 154198090Srdivacky#define CSUM_PSEUDO_HDR 0x0800 /* csum_data has pseudo hdr */ 155198090Srdivacky 156198090Srdivacky#define CSUM_DELAY_DATA (CSUM_TCP | CSUM_UDP) 157198090Srdivacky#define CSUM_DELAY_IP (CSUM_IP) /* XXX add ipv6 here too? */ 158198090Srdivacky 159198090Srdivacky/* mbuf types */ 160193323Sed#define MT_FREE 0 /* should be on free list */ 161193323Sed#define MT_DATA 1 /* dynamic (data) allocation */ 162193323Sed#define MT_HEADER 2 /* packet header */ 163218893Sdim#if 0 164198090Srdivacky#define MT_SOCKET 3 /* socket structure */ 165198892Srdivacky#define MT_PCB 4 /* protocol control block */ 166193323Sed#define MT_RTABLE 5 /* routing tables */ 167193323Sed#define MT_HTABLE 6 /* IMP host tables */ 168218893Sdim#define MT_ATABLE 7 /* address resolution tables */ 169218893Sdim#endif 170198090Srdivacky#define MT_SONAME 8 /* socket name */ 171198090Srdivacky#if 0 172198090Srdivacky#define MT_SOOPTS 10 /* socket options */ 173193323Sed#endif 174193323Sed#define MT_FTABLE 11 /* fragment reassembly header */ 175193323Sed#if 0 176193323Sed#define MT_RIGHTS 12 /* access rights */ 177193323Sed#define MT_IFADDR 13 /* interface address */ 178193323Sed#endif 179193323Sed#define MT_CONTROL 14 /* extra-data protocol message */ 180218893Sdim#define MT_OOBDATA 15 /* expedited data */ 181198090Srdivacky 182198090Srdivacky/* 183193323Sed * mbuf statistics 184193323Sed */ 185193323Sedstruct mbstat { 186193323Sed u_long m_mbufs; /* mbufs obtained from page pool */ 187218893Sdim u_long m_clusters; /* clusters obtained from page pool */ 188218893Sdim u_long m_spare; /* spare field */ 189198090Srdivacky u_long m_clfree; /* free clusters */ 190218893Sdim u_long m_drops; /* times failed to find space */ 191218893Sdim u_long m_wait; /* times waited for space */ 192198090Srdivacky u_long m_drain; /* times drained protocols for space */ 193193323Sed u_short m_mtypes[256]; /* type specific mbuf allocations */ 194193323Sed u_long m_mcfail; /* times m_copym failed */ 195193323Sed u_long m_mpfail; /* times m_pullup failed */ 196193323Sed u_long m_msize; /* length of an mbuf */ 197193323Sed u_long m_mclbytes; /* length of an mbuf cluster */ 198198892Srdivacky u_long m_minclsize; /* min length of data to allocate a cluster */ 199198090Srdivacky u_long m_mlen; /* length of data in an mbuf */ 200193323Sed u_long m_mhlen; /* length of data in a header mbuf */ 201193323Sed}; 202218893Sdim 203198090Srdivacky/* flags to m_get/MGET */ 204218893Sdim#define M_DONTWAIT 1 205198892Srdivacky#define M_WAIT 0 206193323Sed 207193323Sed/* Freelists: 208198090Srdivacky * 209198090Srdivacky * Normal mbuf clusters are normally treated as character arrays 210193323Sed * after allocation, but use the first word of the buffer as a free list 211218893Sdim * pointer while on the free list. 212218893Sdim */ 213198090Srdivackyunion mcluster { 214198090Srdivacky union mcluster *mcl_next; 215198090Srdivacky char mcl_buf[MCLBYTES]; 216193323Sed}; 217193323Sed 218193323Sed 219193323Sed/* 220193323Sed * These are identifying numbers passed to the m_mballoc_wait function, 221193323Sed * allowing us to determine whether the call came from an MGETHDR or 222193323Sed * an MGET. 223193323Sed */ 224218893Sdim#define MGETHDR_C 1 225198892Srdivacky#define MGET_C 2 226198892Srdivacky 227198090Srdivacky/* 228193323Sed * Wake up the next instance (if any) of m_mballoc_wait() which is 229193323Sed * waiting for an mbuf to be freed. This should be called at splimp(). 230193323Sed * 231193323Sed * XXX: If there is another free mbuf, this routine will be called [again] 232193323Sed * from the m_mballoc_wait routine in order to wake another sleep instance. 233193323Sed */ 234198090Srdivacky#define MMBWAKEUP() do { \ 235198892Srdivacky if (m_mballoc_wid) { \ 236198090Srdivacky m_mballoc_wid--; \ 237198090Srdivacky wakeup_one(&m_mballoc_wid); \ 238218893Sdim } \ 239218893Sdim} while (0) 240193323Sed 241193323Sed/* 242198090Srdivacky * Same as above, but for mbuf cluster(s). 243198090Srdivacky */ 244198090Srdivacky#define MCLWAKEUP() do { \ 245193323Sed if (m_clalloc_wid) { \ 246193323Sed m_clalloc_wid--; \ 247206083Srdivacky wakeup_one(&m_clalloc_wid); \ 248206083Srdivacky } \ 249206083Srdivacky} while (0) 250206083Srdivacky 251206083Srdivacky/* 252206083Srdivacky * mbuf utility macros: 253206083Srdivacky * 254206083Srdivacky * MBUFLOCK(code) 255206083Srdivacky * prevents a section of code from from being interrupted by network 256206083Srdivacky * drivers. 257206083Srdivacky */ 258206083Srdivacky#define MBUFLOCK(code) do { \ 259206083Srdivacky int _ms = splimp(); \ 260206083Srdivacky \ 261206083Srdivacky { code } \ 262206083Srdivacky splx(_ms); \ 263206083Srdivacky} while (0) 264206083Srdivacky 265206083Srdivacky/* 266206083Srdivacky * mbuf allocation/deallocation macros: 267206083Srdivacky * 268206083Srdivacky * MGET(struct mbuf *m, int how, int type) 269206083Srdivacky * allocates an mbuf and initializes it to contain internal data. 270206083Srdivacky * 271193323Sed * MGETHDR(struct mbuf *m, int how, int type) 272206083Srdivacky * allocates an mbuf and initializes it to contain a packet header 273193323Sed * and internal data. 274206083Srdivacky */ 275198090Srdivacky#define MGET(m, how, type) do { \ 276193323Sed struct mbuf *_mm; \ 277193323Sed int _mhow = (how); \ 278193323Sed int _mtype = (type); \ 279193323Sed int _ms = splimp(); \ 280206083Srdivacky \ 281202375Srdivacky if (mmbfree == NULL) \ 282193323Sed (void)m_mballoc(1, _mhow); \ 283193323Sed _mm = mmbfree; \ 284193323Sed if (_mm != NULL) { \ 285193323Sed mmbfree = _mm->m_next; \ 286206083Srdivacky mbstat.m_mtypes[MT_FREE]--; \ 287206083Srdivacky _mm->m_type = _mtype; \ 288193323Sed mbstat.m_mtypes[_mtype]++; \ 289193323Sed _mm->m_next = NULL; \ 290193323Sed _mm->m_nextpkt = NULL; \ 291193323Sed _mm->m_data = _mm->m_dat; \ 292193323Sed _mm->m_flags = 0; \ 293206083Srdivacky (m) = _mm; \ 294193323Sed splx(_ms); \ 295206083Srdivacky } else { \ 296193323Sed splx(_ms); \ 297193323Sed _mm = m_retry(_mhow, _mtype); \ 298198090Srdivacky if (_mm == NULL && _mhow == M_WAIT) \ 299198090Srdivacky (m) = m_mballoc_wait(MGET_C, _mtype); \ 300193323Sed else \ 301218893Sdim (m) = _mm; \ 302193323Sed } \ 303218893Sdim} while (0) 304218893Sdim 305218893Sdim#define MGETHDR(m, how, type) do { \ 306218893Sdim struct mbuf *_mm; \ 307218893Sdim int _mhow = (how); \ 308218893Sdim int _mtype = (type); \ 309221345Sdim int _ms = splimp(); \ 310218893Sdim \ 311221345Sdim if (mmbfree == NULL) \ 312221345Sdim (void)m_mballoc(1, _mhow); \ 313221345Sdim _mm = mmbfree; \ 314218893Sdim if (_mm != NULL) { \ 315221345Sdim mmbfree = _mm->m_next; \ 316221345Sdim mbstat.m_mtypes[MT_FREE]--; \ 317221345Sdim _mm->m_type = _mtype; \ 318218893Sdim mbstat.m_mtypes[_mtype]++; \ 319218893Sdim _mm->m_next = NULL; \ 320218893Sdim _mm->m_nextpkt = NULL; \ 321221345Sdim _mm->m_data = _mm->m_pktdat; \ 322218893Sdim _mm->m_flags = M_PKTHDR; \ 323218893Sdim _mm->m_pkthdr.rcvif = NULL; \ 324218893Sdim _mm->m_pkthdr.csum_flags = 0; \ 325218893Sdim (m) = _mm; \ 326218893Sdim splx(_ms); \ 327218893Sdim } else { \ 328218893Sdim splx(_ms); \ 329218893Sdim _mm = m_retryhdr(_mhow, _mtype); \ 330218893Sdim if (_mm == NULL && _mhow == M_WAIT) \ 331218893Sdim (m) = m_mballoc_wait(MGETHDR_C, _mtype); \ 332218893Sdim else \ 333218893Sdim (m) = _mm; \ 334218893Sdim } \ 335218893Sdim} while (0) 336193323Sed 337193323Sed/* 338193323Sed * Mbuf cluster macros. 339193323Sed * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster. 340218893Sdim * MCLGET adds such clusters to a normal mbuf; 341218893Sdim * the flag M_EXT is set upon success. 342193323Sed * MCLFREE releases a reference to a cluster allocated by MCLALLOC, 343193323Sed * freeing the cluster if the reference count has reached 0. 344193323Sed */ 345193323Sed#define MCLALLOC(p, how) do { \ 346193323Sed caddr_t _mp; \ 347193323Sed int _mhow = (how); \ 348193323Sed int _ms = splimp(); \ 349193323Sed \ 350193323Sed if (mclfree == NULL) \ 351193323Sed (void)m_clalloc(1, _mhow); \ 352193323Sed _mp = (caddr_t)mclfree; \ 353193323Sed if (_mp != NULL) { \ 354193323Sed mclrefcnt[mtocl(_mp)]++; \ 355193323Sed mbstat.m_clfree--; \ 356193323Sed mclfree = ((union mcluster *)_mp)->mcl_next; \ 357193323Sed (p) = _mp; \ 358193323Sed splx(_ms); \ 359193323Sed } else { \ 360193323Sed splx(_ms); \ 361193323Sed if (_mhow == M_WAIT) \ 362193323Sed (p) = m_clalloc_wait(); \ 363193323Sed else \ 364193323Sed (p) = NULL; \ 365202375Srdivacky } \ 366218893Sdim} while (0) 367218893Sdim 368218893Sdim#define MCLGET(m, how) do { \ 369218893Sdim struct mbuf *_mm = (m); \ 370218893Sdim \ 371218893Sdim MCLALLOC(_mm->m_ext.ext_buf, (how)); \ 372218893Sdim if (_mm->m_ext.ext_buf != NULL) { \ 373218893Sdim _mm->m_data = _mm->m_ext.ext_buf; \ 374218893Sdim _mm->m_flags |= M_EXT; \ 375218893Sdim _mm->m_ext.ext_free = NULL; \ 376218893Sdim _mm->m_ext.ext_ref = NULL; \ 377218893Sdim _mm->m_ext.ext_size = MCLBYTES; \ 378218893Sdim } \ 379218893Sdim} while (0) 380206083Srdivacky 381206083Srdivacky#define MCLFREE1(p) do { \ 382193323Sed union mcluster *_mp = (union mcluster *)(p); \ 383193323Sed \ 384193323Sed if (--mclrefcnt[mtocl(_mp)] == 0) { \ 385198090Srdivacky _mp->mcl_next = mclfree; \ 386206083Srdivacky mclfree = _mp; \ 387193323Sed mbstat.m_clfree++; \ 388193323Sed MCLWAKEUP(); \ 389193323Sed } \ 390193323Sed} while (0) 391193323Sed 392193323Sed#define MCLFREE(p) MBUFLOCK( \ 393198090Srdivacky MCLFREE1(p); \ 394206083Srdivacky) 395193323Sed 396193323Sed#define MEXTFREE1(m) do { \ 397193323Sed struct mbuf *_mm = (m); \ 398218893Sdim \ 399193323Sed if (_mm->m_ext.ext_free != NULL) \ 400193323Sed (*_mm->m_ext.ext_free)(_mm->m_ext.ext_buf, \ 401193323Sed _mm->m_ext.ext_size); \ 402203954Srdivacky else \ 403193323Sed MCLFREE1(_mm->m_ext.ext_buf); \ 404193323Sed} while (0) 405198090Srdivacky 406198090Srdivacky#define MEXTFREE(m) MBUFLOCK( \ 407203954Srdivacky MEXTFREE1(m); \ 408198090Srdivacky) 409198090Srdivacky 410198090Srdivacky/* 411198090Srdivacky * MFREE(struct mbuf *m, struct mbuf *n) 412198090Srdivacky * Free a single mbuf and associated external storage. 413198090Srdivacky * Place the successor, if any, in n. 414198090Srdivacky */ 415198090Srdivacky#define MFREE(m, n) MBUFLOCK( \ 416193323Sed struct mbuf *_mm = (m); \ 417223017Sdim \ 418223017Sdim mbstat.m_mtypes[_mm->m_type]--; \ 419223017Sdim if (_mm->m_flags & M_EXT) \ 420223017Sdim MEXTFREE1(m); \ 421223017Sdim (n) = _mm->m_next; \ 422223017Sdim _mm->m_type = MT_FREE; \ 423223017Sdim mbstat.m_mtypes[MT_FREE]++; \ 424223017Sdim _mm->m_next = mmbfree; \ 425223017Sdim mmbfree = _mm; \ 426223017Sdim MMBWAKEUP(); \ 427223017Sdim) 428223017Sdim 429223017Sdim/* 430223017Sdim * Copy mbuf pkthdr from "from" to "to". 431223017Sdim * from must have M_PKTHDR set, and to must be empty. 432223017Sdim */ 433223017Sdim#define M_COPY_PKTHDR(to, from) do { \ 434223017Sdim struct mbuf *_mfrom = (from); \ 435223017Sdim struct mbuf *_mto = (to); \ 436223017Sdim \ 437223017Sdim _mto->m_data = _mto->m_pktdat; \ 438223017Sdim _mto->m_flags = _mfrom->m_flags & M_COPYFLAGS; \ 439223017Sdim _mto->m_pkthdr = _mfrom->m_pkthdr; \ 440223017Sdim} while (0) 441223017Sdim 442223017Sdim/* 443223017Sdim * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place 444223017Sdim * an object of the specified size at the end of the mbuf, longword aligned. 445223017Sdim */ 446198090Srdivacky#define M_ALIGN(m, len) do { \ 447193323Sed (m)->m_data += (MLEN - (len)) & ~(sizeof(long) - 1); \ 448193323Sed} while (0) 449193323Sed 450193323Sed/* 451193323Sed * As above, for mbufs allocated with m_gethdr/MGETHDR 452198090Srdivacky * or initialized by M_COPY_PKTHDR. 453198090Srdivacky */ 454198090Srdivacky#define MH_ALIGN(m, len) do { \ 455198090Srdivacky (m)->m_data += (MHLEN - (len)) & ~(sizeof(long) - 1); \ 456198090Srdivacky} while (0) 457198090Srdivacky 458198090Srdivacky/* 459198090Srdivacky * Compute the amount of space available 460198090Srdivacky * before the current start of data in an mbuf. 461198090Srdivacky */ 462198090Srdivacky#define M_LEADINGSPACE(m) \ 463198090Srdivacky ((m)->m_flags & M_EXT ? \ 464193323Sed /* (m)->m_data - (m)->m_ext.ext_buf */ 0 : \ 465198090Srdivacky (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \ 466198090Srdivacky (m)->m_data - (m)->m_dat) 467198090Srdivacky 468223017Sdim/* 469223017Sdim * Compute the amount of space available 470223017Sdim * after the end of data in an mbuf. 471223017Sdim */ 472223017Sdim#define M_TRAILINGSPACE(m) \ 473223017Sdim ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + \ 474223017Sdim (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len) : \ 475223017Sdim &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len)) 476223017Sdim 477223017Sdim/* 478223017Sdim * Arrange to prepend space of size plen to mbuf m. 479223017Sdim * If a new mbuf must be allocated, how specifies whether to wait. 480223017Sdim * If how is M_DONTWAIT and allocation fails, the original mbuf chain 481223017Sdim * is freed and m is set to NULL. 482223017Sdim */ 483198090Srdivacky#define M_PREPEND(m, plen, how) do { \ 484198090Srdivacky struct mbuf **_mmp = &(m); \ 485193323Sed struct mbuf *_mm = *_mmp; \ 486198090Srdivacky int _mplen = (plen); \ 487198090Srdivacky int __mhow = (how); \ 488198090Srdivacky \ 489198090Srdivacky if (_mm == NULL) { \ 490203954Srdivacky MGET(_mm, __mhow, MT_DATA); \ 491198090Srdivacky if (_mm == NULL) \ 492198090Srdivacky break; \ 493198090Srdivacky } \ 494198090Srdivacky if (M_LEADINGSPACE(_mm) >= _mplen) { \ 495193323Sed _mm->m_data -= _mplen; \ 496198090Srdivacky _mm->m_len += _mplen; \ 497198090Srdivacky } else \ 498198090Srdivacky _mm = m_prepend(_mm, _mplen, __mhow); \ 499218893Sdim if (_mm != NULL && _mm->m_flags & M_PKTHDR) \ 500218893Sdim _mm->m_pkthdr.len += _mplen; \ 501198090Srdivacky *_mmp = _mm; \ 502193323Sed} while (0) 503193323Sed 504193323Sed/* change mbuf to new type */ 505193323Sed#define MCHTYPE(m, t) do { \ 506193323Sed struct mbuf *_mm = (m); \ 507193323Sed int _mt = (t); \ 508193323Sed int _ms = splimp(); \ 509218893Sdim \ 510218893Sdim mbstat.m_mtypes[_mm->m_type]--; \ 511193323Sed mbstat.m_mtypes[_mt]++; \ 512193323Sed splx(_ms); \ 513193323Sed _mm->m_type = (_mt); \ 514193323Sed} while (0) 515193323Sed 516193323Sed/* length to m_copy to copy all */ 517198090Srdivacky#define M_COPYALL 1000000000 518218893Sdim 519198892Srdivacky/* compatibility with 4.3 */ 520193323Sed#define m_copy(m, o, l) m_copym((m), (o), (l), M_DONTWAIT) 521193323Sed 522218893Sdim#ifdef _KERNEL 523218893Sdimextern u_int m_clalloc_wid; /* mbuf cluster wait count */ 524193323Sedextern u_int m_mballoc_wid; /* mbuf wait count */ 525193323Sedextern int max_linkhdr; /* largest link-level header */ 526202375Srdivackyextern int max_protohdr; /* largest protocol header */ 527202375Srdivackyextern int max_hdr; /* largest link+protocol header */ 528202375Srdivackyextern int max_datalen; /* MHLEN - max_hdr */ 529202375Srdivackyextern struct mbstat mbstat; 530202375Srdivackyextern int mbuf_wait; /* mbuf sleep time */ 531202375Srdivackyextern struct mbuf *mbutl; /* virtual address of mclusters */ 532202375Srdivackyextern char *mclrefcnt; /* cluster reference counts */ 533202375Srdivackyextern union mcluster *mclfree; 534202375Srdivackyextern struct mbuf *mmbfree; 535202375Srdivackyextern int nmbclusters; 536202375Srdivackyextern int nmbufs; 537202375Srdivackyextern int nsfbufs; 538202375Srdivacky 539202375Srdivackyvoid m_adj __P((struct mbuf *, int)); 540202375Srdivackyvoid m_cat __P((struct mbuf *,struct mbuf *)); 541202375Srdivackyint m_clalloc __P((int, int)); 542193323Sedcaddr_t m_clalloc_wait __P((void)); 543218893Sdimvoid m_copyback __P((struct mbuf *, int, int, caddr_t)); 544193323Sedvoid m_copydata __P((struct mbuf *,int,int,caddr_t)); 545193323Sedstruct mbuf *m_copym __P((struct mbuf *, int, int, int)); 546193323Sedstruct mbuf *m_copypacket __P((struct mbuf *, int)); 547193323Sedstruct mbuf *m_devget __P((char *, int, int, struct ifnet *, 548218893Sdim void (*copy)(char *, caddr_t, u_int))); 549193323Sedstruct mbuf *m_dup __P((struct mbuf *, int)); 550193323Sedstruct mbuf *m_free __P((struct mbuf *)); 551193323Sedvoid m_freem __P((struct mbuf *)); 552193323Sedstruct mbuf *m_get __P((int, int)); 553193323Sedstruct mbuf *m_getclr __P((int, int)); 554193323Sedstruct mbuf *m_gethdr __P((int, int)); 555193323Sedint m_mballoc __P((int, int)); 556193323Sedstruct mbuf *m_mballoc_wait __P((int, int)); 557193323Sedstruct mbuf *m_prepend __P((struct mbuf *,int,int)); 558193323Sedvoid m_print __P((const struct mbuf *m)); 559193323Sedstruct mbuf *m_pullup __P((struct mbuf *, int)); 560193323Sedstruct mbuf *m_retry __P((int, int)); 561193323Sedstruct mbuf *m_retryhdr __P((int, int)); 562193323Sedstruct mbuf *m_split __P((struct mbuf *,int,int)); 563193323Sed#endif /* _KERNEL */ 564193323Sed 565193323Sed#endif /* !_SYS_MBUF_H_ */ 566193323Sed