1 /* 2 * Copyright (c) 3 * 1982, 1986, 1988, 1993 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 * 8 * @(#)mbuf.h 8.1 (Berkeley) 06/04/93 9 */ 10 11 #ifndef M_WAITOK 12 #include "malloc.h" 13 #endif 14 15 /* 16 * Mbufs are of a single size, MSIZE (machine/machparam.h), which 17 * includes overhead. An mbuf may add a single "mbuf cluster" of size 18 * MCLBYTES (also in machine/machparam.h), which has no additional overhead 19 * and is used instead of the internal data area; this is done when 20 * at least MINCLSIZE of data must be stored. 21 */ 22 23 #define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ 24 #define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ 25 26 #define MINCLSIZE (MHLEN + MLEN) /* smallest amount to put in cluster */ 27 #define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ 28 29 /* 30 * Macros for type conversion 31 * mtod(m,t) - convert mbuf pointer to data pointer of correct type 32 * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX) 33 * mtocl(x) - convert pointer within cluster to cluster index # 34 * cltom(x) - convert cluster # to ptr to beginning of cluster 35 */ 36 #define mtod(m,t) ((t)((m)->m_data)) 37 #define dtom(x) ((struct mbuf *)((int)(x) & ~(MSIZE-1))) 38 #define mtocl(x) (((u_int)(x) - (u_int)mbutl) >> MCLSHIFT) 39 #define cltom(x) ((caddr_t)((u_int)mbutl + ((u_int)(x) << MCLSHIFT))) 40 41 /* header at beginning of each mbuf: */ 42 struct m_hdr { 43 struct mbuf *mh_next; /* next buffer in chain */ 44 struct mbuf *mh_nextpkt; /* next chain in queue/record */ 45 int mh_len; /* amount of data in this mbuf */ 46 caddr_t mh_data; /* location of data */ 47 short mh_type; /* type of data in this mbuf */ 48 short mh_flags; /* flags; see below */ 49 }; 50 51 /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ 52 struct pkthdr { 53 int len; /* total packet length */ 54 struct ifnet *rcvif; /* rcv interface */ 55 }; 56 57 /* description of external storage mapped into mbuf, valid if M_EXT set */ 58 struct m_ext { 59 caddr_t ext_buf; /* start of buffer */ 60 void (*ext_free)(); /* free routine if not the usual */ 61 u_int ext_size; /* size of buffer, for ext_free */ 62 }; 63 64 struct mbuf { 65 struct m_hdr m_hdr; 66 union { 67 struct { 68 struct pkthdr MH_pkthdr; /* M_PKTHDR set */ 69 union { 70 struct m_ext MH_ext; /* M_EXT set */ 71 char MH_databuf[MHLEN]; 72 } MH_dat; 73 } MH; 74 char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ 75 } M_dat; 76 }; 77 #define m_next m_hdr.mh_next 78 #define m_len m_hdr.mh_len 79 #define m_data m_hdr.mh_data 80 #define m_type m_hdr.mh_type 81 #define m_flags m_hdr.mh_flags 82 #define m_nextpkt m_hdr.mh_nextpkt 83 #define m_act m_nextpkt 84 #define m_pkthdr M_dat.MH.MH_pkthdr 85 #define m_ext M_dat.MH.MH_dat.MH_ext 86 #define m_pktdat M_dat.MH.MH_dat.MH_databuf 87 #define m_dat M_dat.M_databuf 88 89 /* mbuf flags */ 90 #define M_EXT 0x0001 /* has associated external storage */ 91 #define M_PKTHDR 0x0002 /* start of record */ 92 #define M_EOR 0x0004 /* end of record */ 93 94 /* mbuf pkthdr flags, also in m_flags */ 95 #define M_BCAST 0x0100 /* send/received as link-level broadcast */ 96 #define M_MCAST 0x0200 /* send/received as link-level multicast */ 97 98 /* flags copied when copying m_pkthdr */ 99 #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_BCAST|M_MCAST) 100 101 /* mbuf types */ 102 #define MT_FREE 0 /* should be on free list */ 103 #define MT_DATA 1 /* dynamic (data) allocation */ 104 #define MT_HEADER 2 /* packet header */ 105 #define MT_SOCKET 3 /* socket structure */ 106 #define MT_PCB 4 /* protocol control block */ 107 #define MT_RTABLE 5 /* routing tables */ 108 #define MT_HTABLE 6 /* IMP host tables */ 109 #define MT_ATABLE 7 /* address resolution tables */ 110 #define MT_SONAME 8 /* socket name */ 111 #define MT_SOOPTS 10 /* socket options */ 112 #define MT_FTABLE 11 /* fragment reassembly header */ 113 #define MT_RIGHTS 12 /* access rights */ 114 #define MT_IFADDR 13 /* interface address */ 115 #define MT_CONTROL 14 /* extra-data protocol message */ 116 #define MT_OOBDATA 15 /* expedited data */ 117 118 /* flags to m_get/MGET */ 119 #define M_DONTWAIT M_NOWAIT 120 #define M_WAIT M_WAITOK 121 122 /* 123 * mbuf utility macros: 124 * 125 * MBUFLOCK(code) 126 * prevents a section of code from from being interrupted by network 127 * drivers. 128 */ 129 #define MBUFLOCK(code) \ 130 { int ms = splimp(); \ 131 { code } \ 132 splx(ms); \ 133 } 134 135 /* 136 * mbuf allocation/deallocation macros: 137 * 138 * MGET(struct mbuf *m, int how, int type) 139 * allocates an mbuf and initializes it to contain internal data. 140 * 141 * MGETHDR(struct mbuf *m, int how, int type) 142 * allocates an mbuf and initializes it to contain a packet header 143 * and internal data. 144 */ 145 #define MGET(m, how, type) { \ 146 MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \ 147 if (m) { \ 148 (m)->m_type = (type); \ 149 MBUFLOCK(mbstat.m_mtypes[type]++;) \ 150 (m)->m_next = (struct mbuf *)NULL; \ 151 (m)->m_nextpkt = (struct mbuf *)NULL; \ 152 (m)->m_data = (m)->m_dat; \ 153 (m)->m_flags = 0; \ 154 } else \ 155 (m) = m_retry((how), (type)); \ 156 } 157 158 #define MGETHDR(m, how, type) { \ 159 MALLOC((m), struct mbuf *, MSIZE, mbtypes[type], (how)); \ 160 if (m) { \ 161 (m)->m_type = (type); \ 162 MBUFLOCK(mbstat.m_mtypes[type]++;) \ 163 (m)->m_next = (struct mbuf *)NULL; \ 164 (m)->m_nextpkt = (struct mbuf *)NULL; \ 165 (m)->m_data = (m)->m_pktdat; \ 166 (m)->m_flags = M_PKTHDR; \ 167 } else \ 168 (m) = m_retryhdr((how), (type)); \ 169 } 170 171 /* 172 * Mbuf cluster macros. 173 * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster. 174 * MCLGET adds such clusters to a normal mbuf; 175 * the flag M_EXT is set upon success. 176 * MCLFREE releases a reference to a cluster allocated by MCLALLOC, 177 * freeing the cluster if the reference count has reached 0. 178 * 179 * Normal mbuf clusters are normally treated as character arrays 180 * after allocation, but use the first word of the buffer as a free list 181 * pointer while on the free list. 182 */ 183 union mcluster { 184 union mcluster *mcl_next; 185 char mcl_buf[MCLBYTES]; 186 }; 187 188 #define MCLALLOC(p, how) \ 189 MBUFLOCK( \ 190 if (mclfree == 0) \ 191 (void)m_clalloc(1, (how)); \ 192 if ((p) = (caddr_t)mclfree) { \ 193 ++mclrefcnt[mtocl(p)]; \ 194 mbstat.m_clfree--; \ 195 mclfree = ((union mcluster *)(p))->mcl_next; \ 196 } \ 197 ) 198 199 #define MCLGET(m, how) \ 200 { MCLALLOC((m)->m_ext.ext_buf, (how)); \ 201 if ((m)->m_ext.ext_buf != NULL) { \ 202 (m)->m_data = (m)->m_ext.ext_buf; \ 203 (m)->m_flags |= M_EXT; \ 204 (m)->m_ext.ext_size = MCLBYTES; \ 205 } \ 206 } 207 208 #define MCLFREE(p) \ 209 MBUFLOCK ( \ 210 if (--mclrefcnt[mtocl(p)] == 0) { \ 211 ((union mcluster *)(p))->mcl_next = mclfree; \ 212 mclfree = (union mcluster *)(p); \ 213 mbstat.m_clfree++; \ 214 } \ 215 ) 216 217 /* 218 * MFREE(struct mbuf *m, struct mbuf *n) 219 * Free a single mbuf and associated external storage. 220 * Place the successor, if any, in n. 221 */ 222 #ifdef notyet 223 #define MFREE(m, n) \ 224 { MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--;) \ 225 if ((m)->m_flags & M_EXT) { \ 226 if ((m)->m_ext.ext_free) \ 227 (*((m)->m_ext.ext_free))((m)->m_ext.ext_buf, \ 228 (m)->m_ext.ext_size); \ 229 else \ 230 MCLFREE((m)->m_ext.ext_buf); \ 231 } \ 232 (n) = (m)->m_next; \ 233 FREE((m), mbtypes[(m)->m_type]); \ 234 } 235 #else /* notyet */ 236 #define MFREE(m, nn) \ 237 { MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--;) \ 238 if ((m)->m_flags & M_EXT) { \ 239 MCLFREE((m)->m_ext.ext_buf); \ 240 } \ 241 (nn) = (m)->m_next; \ 242 FREE((m), mbtypes[(m)->m_type]); \ 243 } 244 #endif 245 246 /* 247 * Copy mbuf pkthdr from from to to. 248 * from must have M_PKTHDR set, and to must be empty. 249 */ 250 #define M_COPY_PKTHDR(to, from) { \ 251 (to)->m_pkthdr = (from)->m_pkthdr; \ 252 (to)->m_flags = (from)->m_flags & M_COPYFLAGS; \ 253 (to)->m_data = (to)->m_pktdat; \ 254 } 255 256 /* 257 * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place 258 * an object of the specified size at the end of the mbuf, longword aligned. 259 */ 260 #define M_ALIGN(m, len) \ 261 { (m)->m_data += (MLEN - (len)) &~ (sizeof(long) - 1); } 262 /* 263 * As above, for mbufs allocated with m_gethdr/MGETHDR 264 * or initialized by M_COPY_PKTHDR. 265 */ 266 #define MH_ALIGN(m, len) \ 267 { (m)->m_data += (MHLEN - (len)) &~ (sizeof(long) - 1); } 268 269 /* 270 * Compute the amount of space available 271 * before the current start of data in an mbuf. 272 */ 273 #define M_LEADINGSPACE(m) \ 274 ((m)->m_flags & M_EXT ? /* (m)->m_data - (m)->m_ext.ext_buf */ 0 : \ 275 (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \ 276 (m)->m_data - (m)->m_dat) 277 278 /* 279 * Compute the amount of space available 280 * after the end of data in an mbuf. 281 */ 282 #define M_TRAILINGSPACE(m) \ 283 ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size - \ 284 ((m)->m_data + (m)->m_len) : \ 285 &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len)) 286 287 /* 288 * Arrange to prepend space of size plen to mbuf m. 289 * If a new mbuf must be allocated, how specifies whether to wait. 290 * If how is M_DONTWAIT and allocation fails, the original mbuf chain 291 * is freed and m is set to NULL. 292 */ 293 #define M_PREPEND(m, plen, how) { \ 294 if (M_LEADINGSPACE(m) >= (plen)) { \ 295 (m)->m_data -= (plen); \ 296 (m)->m_len += (plen); \ 297 } else \ 298 (m) = m_prepend((m), (plen), (how)); \ 299 if ((m) && (m)->m_flags & M_PKTHDR) \ 300 (m)->m_pkthdr.len += (plen); \ 301 } 302 303 /* change mbuf to new type */ 304 #define MCHTYPE(m, t) { \ 305 MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;) \ 306 (m)->m_type = t;\ 307 } 308 309 /* length to m_copy to copy all */ 310 #define M_COPYALL 1000000000 311 312 /* compatiblity with 4.3 */ 313 #define m_copy(m, o, l) m_copym((m), (o), (l), M_DONTWAIT) 314 315 /* 316 * Mbuf statistics. 317 */ 318 struct mbstat { 319 u_long m_mbufs; /* mbufs obtained from page pool */ 320 u_long m_clusters; /* clusters obtained from page pool */ 321 u_long m_spare; /* spare field */ 322 u_long m_clfree; /* free clusters */ 323 u_long m_drops; /* times failed to find space */ 324 u_long m_wait; /* times waited for space */ 325 u_long m_drain; /* times drained protocols for space */ 326 u_short m_mtypes[256]; /* type specific mbuf allocations */ 327 }; 328 329 #ifdef KERNEL 330 extern struct mbuf *mbutl; /* virtual address of mclusters */ 331 extern char *mclrefcnt; /* cluster reference counts */ 332 struct mbstat mbstat; 333 extern int nmbclusters; 334 union mcluster *mclfree; 335 int max_linkhdr; /* largest link-level header */ 336 int max_protohdr; /* largest protocol header */ 337 int max_hdr; /* largest link+protocol header */ 338 int max_datalen; /* MHLEN - max_hdr */ 339 extern int mbtypes[]; /* XXX */ 340 341 struct mbuf *m_copym __P((struct mbuf *, int, int, int)); 342 struct mbuf *m_free __P((struct mbuf *)); 343 struct mbuf *m_get __P((int, int)); 344 struct mbuf *m_getclr __P((int, int)); 345 struct mbuf *m_gethdr __P((int, int)); 346 struct mbuf *m_prepend __P((struct mbuf *, int, int)); 347 struct mbuf *m_pullup __P((struct mbuf *, int)); 348 struct mbuf *m_retry __P((int, int)); 349 struct mbuf *m_retryhdr __P((int, int)); 350 int m_clalloc __P((int, int)); 351 void m_copyback __P((struct mbuf *, int, int, caddr_t)); 352 void m_freem __P((struct mbuf *)); 353 354 #ifdef MBTYPES 355 int mbtypes[] = { /* XXX */ 356 M_FREE, /* MT_FREE 0 should be on free list */ 357 M_MBUF, /* MT_DATA 1 dynamic (data) allocation */ 358 M_MBUF, /* MT_HEADER 2 packet header */ 359 M_SOCKET, /* MT_SOCKET 3 socket structure */ 360 M_PCB, /* MT_PCB 4 protocol control block */ 361 M_RTABLE, /* MT_RTABLE 5 routing tables */ 362 M_HTABLE, /* MT_HTABLE 6 IMP host tables */ 363 0, /* MT_ATABLE 7 address resolution tables */ 364 M_MBUF, /* MT_SONAME 8 socket name */ 365 0, /* 9 */ 366 M_SOOPTS, /* MT_SOOPTS 10 socket options */ 367 M_FTABLE, /* MT_FTABLE 11 fragment reassembly header */ 368 M_MBUF, /* MT_RIGHTS 12 access rights */ 369 M_IFADDR, /* MT_IFADDR 13 interface address */ 370 M_MBUF, /* MT_CONTROL 14 extra-data protocol message */ 371 M_MBUF, /* MT_OOBDATA 15 expedited data */ 372 #ifdef DATAKIT 373 25, 26, 27, 28, 29, 30, 31, 32 /* datakit ugliness */ 374 #endif 375 }; 376 #endif 377 #endif 378