1 /* 2 * Copyright 2007, Hugo Santos. All Rights Reserved. 3 * Copyright 2004, Marcus Overhagen. All Rights Reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "device.h" 9 10 #include <stdint.h> 11 #include <string.h> 12 #include <slab/Slab.h> 13 14 #include <compat/sys/malloc.h> 15 #include <compat/sys/mbuf.h> 16 #include <compat/sys/kernel.h> 17 18 19 static object_cache *sMBufCache; 20 static object_cache *sChunkCache; 21 static object_cache *sJumbo9ChunkCache; 22 static object_cache *sJumboPageSizeCache; 23 24 25 int max_linkhdr = 16; 26 int max_protohdr = 40 + 20; /* ip6 + tcp */ 27 28 /* max_linkhdr + max_protohdr, but that's not allowed by gcc. */ 29 int max_hdr = 16 + 40 + 20; 30 31 /* MHLEN - max_hdr */ 32 int max_datalen = MHLEN - (16 + 40 + 20); 33 34 35 static int 36 m_to_oc_flags(int how) 37 { 38 if (how & M_NOWAIT) 39 return CACHE_DONT_WAIT_FOR_MEMORY; 40 41 return 0; 42 } 43 44 45 static int 46 construct_mbuf(struct mbuf *memoryBuffer, short type, int flags) 47 { 48 memoryBuffer->m_next = NULL; 49 memoryBuffer->m_nextpkt = NULL; 50 memoryBuffer->m_len = 0; 51 memoryBuffer->m_flags = flags; 52 memoryBuffer->m_type = type; 53 54 if (flags & M_PKTHDR) { 55 memoryBuffer->m_data = memoryBuffer->m_pktdat; 56 memset(&memoryBuffer->m_pkthdr, 0, sizeof(memoryBuffer->m_pkthdr)); 57 SLIST_INIT(&memoryBuffer->m_pkthdr.tags); 58 } else { 59 memoryBuffer->m_data = memoryBuffer->m_dat; 60 } 61 62 return 0; 63 } 64 65 66 static int 67 construct_ext_sized_mbuf(struct mbuf *memoryBuffer, int how, int size) 68 { 69 object_cache *cache; 70 int extType; 71 if (size != MCLBYTES && size != MJUM9BYTES && size != MJUMPAGESIZE) 72 panic("unsupported size"); 73 74 if (size == MCLBYTES) { 75 cache = sChunkCache; 76 extType = EXT_CLUSTER; 77 } else if (size == MJUM9BYTES) { 78 cache = sJumbo9ChunkCache; 79 extType = EXT_JUMBO9; 80 } else { 81 cache = sJumboPageSizeCache; 82 extType = EXT_JUMBOP; 83 } 84 85 memoryBuffer->m_ext.ext_buf = object_cache_alloc(cache, m_to_oc_flags(how)); 86 if (memoryBuffer->m_ext.ext_buf == NULL) 87 return B_NO_MEMORY; 88 89 memoryBuffer->m_data = memoryBuffer->m_ext.ext_buf; 90 memoryBuffer->m_flags |= M_EXT; 91 /* mb->m_ext.ext_free = NULL; */ 92 /* mb->m_ext.ext_args = NULL; */ 93 memoryBuffer->m_ext.ext_size = size; 94 memoryBuffer->m_ext.ext_type = extType; 95 /* mb->m_ext.ref_cnt = NULL; */ 96 97 return 0; 98 } 99 100 101 static inline int 102 construct_ext_mbuf(struct mbuf *memoryBuffer, int how) 103 { 104 return construct_ext_sized_mbuf(memoryBuffer, how, MCLBYTES); 105 } 106 107 108 static int 109 construct_pkt_mbuf(int how, struct mbuf *memoryBuffer, short type, int flags) 110 { 111 construct_mbuf(memoryBuffer, type, flags); 112 if (construct_ext_mbuf(memoryBuffer, how) < 0) 113 return -1; 114 memoryBuffer->m_ext.ext_type = EXT_CLUSTER; 115 return 0; 116 } 117 118 119 struct mbuf * 120 m_getcl(int how, short type, int flags) 121 { 122 struct mbuf *memoryBuffer = 123 (struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how)); 124 if (memoryBuffer == NULL) 125 return NULL; 126 127 if (construct_pkt_mbuf(how, memoryBuffer, type, flags) < 0) { 128 object_cache_free(sMBufCache, memoryBuffer, 0); 129 return NULL; 130 } 131 132 return memoryBuffer; 133 } 134 135 136 static struct mbuf * 137 _m_get(int how, short type, int flags) 138 { 139 struct mbuf *memoryBuffer = 140 (struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how)); 141 if (memoryBuffer == NULL) 142 return NULL; 143 144 construct_mbuf(memoryBuffer, type, flags); 145 146 return memoryBuffer; 147 } 148 149 150 struct mbuf * 151 m_get(int how, short type) 152 { 153 return _m_get(how, type, 0); 154 } 155 156 157 struct mbuf * 158 m_gethdr(int how, short type) 159 { 160 return _m_get(how, type, M_PKTHDR); 161 } 162 163 164 struct mbuf * 165 m_getjcl(int how, short type, int flags, int size) 166 { 167 struct mbuf *memoryBuffer = 168 (struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how)); 169 if (memoryBuffer == NULL) 170 return NULL; 171 construct_mbuf(memoryBuffer, type, flags); 172 if (construct_ext_sized_mbuf(memoryBuffer, how, size) < 0) { 173 object_cache_free(sMBufCache, memoryBuffer, 0); 174 return NULL; 175 } 176 return memoryBuffer; 177 } 178 179 180 void 181 m_clget(struct mbuf *memoryBuffer, int how) 182 { 183 memoryBuffer->m_ext.ext_buf = NULL; 184 /* called checks for errors by looking for M_EXT */ 185 construct_ext_mbuf(memoryBuffer, how); 186 } 187 188 189 void * 190 m_cljget(struct mbuf *memoryBuffer, int how, int size) 191 { 192 if (memoryBuffer == NULL) 193 panic("m_cljget doesn't support allocate mbuf"); 194 memoryBuffer->m_ext.ext_buf = NULL; 195 construct_ext_sized_mbuf(memoryBuffer, how, size); 196 /* shouldn't be used */ 197 return NULL; 198 } 199 200 201 void 202 m_freem(struct mbuf *memoryBuffer) 203 { 204 while (memoryBuffer) 205 memoryBuffer = m_free(memoryBuffer); 206 } 207 208 209 static void 210 mb_free_ext(struct mbuf *memoryBuffer) 211 { 212 /* 213 if (m->m_ext.ref_count != NULL) 214 panic("unsupported"); 215 */ 216 217 object_cache *cache = NULL; 218 219 if (memoryBuffer->m_ext.ext_type == EXT_CLUSTER) 220 cache = sChunkCache; 221 else if (memoryBuffer->m_ext.ext_type == EXT_JUMBO9) 222 cache = sJumbo9ChunkCache; 223 else if (memoryBuffer->m_ext.ext_type == EXT_JUMBOP) 224 cache = sJumboPageSizeCache; 225 else 226 panic("unknown type"); 227 228 object_cache_free(cache, memoryBuffer->m_ext.ext_buf, 0); 229 memoryBuffer->m_ext.ext_buf = NULL; 230 object_cache_free(sMBufCache, memoryBuffer, 0); 231 } 232 233 234 struct mbuf * 235 m_free(struct mbuf *memoryBuffer) 236 { 237 struct mbuf *next = memoryBuffer->m_next; 238 239 if (memoryBuffer->m_flags & M_EXT) 240 mb_free_ext(memoryBuffer); 241 else 242 object_cache_free(sMBufCache, memoryBuffer, 0); 243 244 return next; 245 } 246 247 248 void 249 m_extadd(struct mbuf *memoryBuffer, caddr_t buffer, u_int size, 250 void (*freeHook)(void *, void *), void *arg1, void *arg2, int flags, int type) 251 { 252 // TODO: implement? 253 panic("m_extadd() called."); 254 } 255 256 257 status_t 258 init_mbufs() 259 { 260 sMBufCache = create_object_cache("mbufs", MSIZE, 8, NULL, NULL, NULL); 261 if (sMBufCache == NULL) 262 goto clean; 263 sChunkCache = create_object_cache("mbuf chunks", MCLBYTES, 0, NULL, NULL, 264 NULL); 265 if (sChunkCache == NULL) 266 goto clean; 267 sJumbo9ChunkCache = create_object_cache("mbuf jumbo9 chunks", MJUM9BYTES, 0, 268 NULL, NULL, NULL); 269 if (sJumbo9ChunkCache == NULL) 270 goto clean; 271 sJumboPageSizeCache = create_object_cache("mbuf jumbo page size chunks", 272 MJUMPAGESIZE, 0, NULL, NULL, NULL); 273 if (sJumboPageSizeCache == NULL) 274 goto clean; 275 return B_OK; 276 277 clean: 278 if (sJumbo9ChunkCache != NULL) 279 delete_object_cache(sJumbo9ChunkCache); 280 if (sChunkCache != NULL) 281 delete_object_cache(sChunkCache); 282 if (sMBufCache != NULL) 283 delete_object_cache(sMBufCache); 284 return B_NO_MEMORY; 285 } 286 287 288 void 289 uninit_mbufs() 290 { 291 delete_object_cache(sMBufCache); 292 delete_object_cache(sChunkCache); 293 delete_object_cache(sJumbo9ChunkCache); 294 delete_object_cache(sJumboPageSizeCache); 295 } 296