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