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