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