1 /* 2 * Copyright (C) 2012-2013 Matteo Landi, Luigi Rizzo, Giuseppe Lettieri. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* 27 * $FreeBSD$ 28 * 29 * (New) memory allocator for netmap 30 */ 31 32 /* 33 * This allocator creates three memory pools: 34 * nm_if_pool for the struct netmap_if 35 * nm_ring_pool for the struct netmap_ring 36 * nm_buf_pool for the packet buffers. 37 * 38 * that contain netmap objects. Each pool is made of a number of clusters, 39 * multiple of a page size, each containing an integer number of objects. 40 * The clusters are contiguous in user space but not in the kernel. 41 * Only nm_buf_pool needs to be dma-able, 42 * but for convenience use the same type of allocator for all. 43 * 44 * Once mapped, the three pools are exported to userspace 45 * as a contiguous block, starting from nm_if_pool. Each 46 * cluster (and pool) is an integral number of pages. 47 * [ . . . ][ . . . . . .][ . . . . . . . . . .] 48 * nm_if nm_ring nm_buf 49 * 50 * The userspace areas contain offsets of the objects in userspace. 51 * When (at init time) we write these offsets, we find out the index 52 * of the object, and from there locate the offset from the beginning 53 * of the region. 54 * 55 * The invididual allocators manage a pool of memory for objects of 56 * the same size. 57 * The pool is split into smaller clusters, whose size is a 58 * multiple of the page size. The cluster size is chosen 59 * to minimize the waste for a given max cluster size 60 * (we do it by brute force, as we have relatively few objects 61 * per cluster). 62 * 63 * Objects are aligned to the cache line (64 bytes) rounding up object 64 * sizes when needed. A bitmap contains the state of each object. 65 * Allocation scans the bitmap; this is done only on attach, so we are not 66 * too worried about performance 67 * 68 * For each allocator we can define (thorugh sysctl) the size and 69 * number of each object. Memory is allocated at the first use of a 70 * netmap file descriptor, and can be freed when all such descriptors 71 * have been released (including unmapping the memory). 72 * If memory is scarce, the system tries to get as much as possible 73 * and the sysctl values reflect the actual allocation. 74 * Together with desired values, the sysctl export also absolute 75 * min and maximum values that cannot be overridden. 76 * 77 * struct netmap_if: 78 * variable size, max 16 bytes per ring pair plus some fixed amount. 79 * 1024 bytes should be large enough in practice. 80 * 81 * In the worst case we have one netmap_if per ring in the system. 82 * 83 * struct netmap_ring 84 * variable size, 8 byte per slot plus some fixed amount. 85 * Rings can be large (e.g. 4k slots, or >32Kbytes). 86 * We default to 36 KB (9 pages), and a few hundred rings. 87 * 88 * struct netmap_buffer 89 * The more the better, both because fast interfaces tend to have 90 * many slots, and because we may want to use buffers to store 91 * packets in userspace avoiding copies. 92 * Must contain a full frame (eg 1518, or more for vlans, jumbo 93 * frames etc.) plus be nicely aligned, plus some NICs restrict 94 * the size to multiple of 1K or so. Default to 2K 95 */ 96 97 #define NETMAP_BUF_MAX_NUM 20*4096*2 /* large machine */ 98 99 #ifdef linux 100 #define NMA_LOCK_T struct semaphore 101 #define NMA_LOCK_INIT() sema_init(&nm_mem.nm_mtx, 1) 102 #define NMA_LOCK_DESTROY() 103 #define NMA_LOCK() down(&nm_mem.nm_mtx) 104 #define NMA_UNLOCK() up(&nm_mem.nm_mtx) 105 #else /* !linux */ 106 #define NMA_LOCK_T struct mtx 107 #define NMA_LOCK_INIT() mtx_init(&nm_mem.nm_mtx, "netmap memory allocator lock", NULL, MTX_DEF) 108 #define NMA_LOCK_DESTROY() mtx_destroy(&nm_mem.nm_mtx) 109 #define NMA_LOCK() mtx_lock(&nm_mem.nm_mtx) 110 #define NMA_UNLOCK() mtx_unlock(&nm_mem.nm_mtx) 111 #endif /* linux */ 112 113 enum { 114 NETMAP_IF_POOL = 0, 115 NETMAP_RING_POOL, 116 NETMAP_BUF_POOL, 117 NETMAP_POOLS_NR 118 }; 119 120 121 struct netmap_obj_params { 122 u_int size; 123 u_int num; 124 }; 125 126 127 struct netmap_obj_params netmap_params[NETMAP_POOLS_NR] = { 128 [NETMAP_IF_POOL] = { 129 .size = 1024, 130 .num = 100, 131 }, 132 [NETMAP_RING_POOL] = { 133 .size = 9*PAGE_SIZE, 134 .num = 200, 135 }, 136 [NETMAP_BUF_POOL] = { 137 .size = 2048, 138 .num = NETMAP_BUF_MAX_NUM, 139 }, 140 }; 141 142 143 struct netmap_obj_pool { 144 char name[16]; /* name of the allocator */ 145 u_int objtotal; /* actual total number of objects. */ 146 u_int objfree; /* number of free objects. */ 147 u_int clustentries; /* actual objects per cluster */ 148 149 /* limits */ 150 u_int objminsize; /* minimum object size */ 151 u_int objmaxsize; /* maximum object size */ 152 u_int nummin; /* minimum number of objects */ 153 u_int nummax; /* maximum number of objects */ 154 155 /* the total memory space is _numclusters*_clustsize */ 156 u_int _numclusters; /* how many clusters */ 157 u_int _clustsize; /* cluster size */ 158 u_int _objsize; /* actual object size */ 159 160 u_int _memtotal; /* _numclusters*_clustsize */ 161 struct lut_entry *lut; /* virt,phys addresses, objtotal entries */ 162 uint32_t *bitmap; /* one bit per buffer, 1 means free */ 163 uint32_t bitmap_slots; /* number of uint32 entries in bitmap */ 164 }; 165 166 167 struct netmap_mem_d { 168 NMA_LOCK_T nm_mtx; /* protect the allocator */ 169 u_int nm_totalsize; /* shorthand */ 170 171 int finalized; /* !=0 iff preallocation done */ 172 int lasterr; /* last error for curr config */ 173 int refcount; /* existing priv structures */ 174 /* the three allocators */ 175 struct netmap_obj_pool pools[NETMAP_POOLS_NR]; 176 }; 177 178 /* 179 * nm_mem is the memory allocator used for all physical interfaces 180 * running in netmap mode. 181 * Virtual (VALE) ports will have each its own allocator. 182 */ 183 static struct netmap_mem_d nm_mem = { /* Our memory allocator. */ 184 .pools = { 185 [NETMAP_IF_POOL] = { 186 .name = "netmap_if", 187 .objminsize = sizeof(struct netmap_if), 188 .objmaxsize = 4096, 189 .nummin = 10, /* don't be stingy */ 190 .nummax = 10000, /* XXX very large */ 191 }, 192 [NETMAP_RING_POOL] = { 193 .name = "netmap_ring", 194 .objminsize = sizeof(struct netmap_ring), 195 .objmaxsize = 32*PAGE_SIZE, 196 .nummin = 2, 197 .nummax = 1024, 198 }, 199 [NETMAP_BUF_POOL] = { 200 .name = "netmap_buf", 201 .objminsize = 64, 202 .objmaxsize = 65536, 203 .nummin = 4, 204 .nummax = 1000000, /* one million! */ 205 }, 206 }, 207 }; 208 209 // XXX logically belongs to nm_mem 210 struct lut_entry *netmap_buffer_lut; /* exported */ 211 212 /* memory allocator related sysctls */ 213 214 #define STRINGIFY(x) #x 215 216 #define DECLARE_SYSCTLS(id, name) \ 217 SYSCTL_INT(_dev_netmap, OID_AUTO, name##_size, \ 218 CTLFLAG_RW, &netmap_params[id].size, 0, "Requested size of netmap " STRINGIFY(name) "s"); \ 219 SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_size, \ 220 CTLFLAG_RD, &nm_mem.pools[id]._objsize, 0, "Current size of netmap " STRINGIFY(name) "s"); \ 221 SYSCTL_INT(_dev_netmap, OID_AUTO, name##_num, \ 222 CTLFLAG_RW, &netmap_params[id].num, 0, "Requested number of netmap " STRINGIFY(name) "s"); \ 223 SYSCTL_INT(_dev_netmap, OID_AUTO, name##_curr_num, \ 224 CTLFLAG_RD, &nm_mem.pools[id].objtotal, 0, "Current number of netmap " STRINGIFY(name) "s") 225 226 DECLARE_SYSCTLS(NETMAP_IF_POOL, if); 227 DECLARE_SYSCTLS(NETMAP_RING_POOL, ring); 228 DECLARE_SYSCTLS(NETMAP_BUF_POOL, buf); 229 230 /* 231 * Convert a userspace offset to a physical address. 232 * XXX only called in the FreeBSD's netmap_mmap() 233 * because in linux we map everything at once. 234 * 235 * First, find the allocator that contains the requested offset, 236 * then locate the cluster through a lookup table. 237 */ 238 static inline vm_paddr_t 239 netmap_ofstophys(vm_offset_t offset) 240 { 241 int i; 242 vm_offset_t o = offset; 243 struct netmap_obj_pool *p = nm_mem.pools; 244 245 for (i = 0; i < NETMAP_POOLS_NR; offset -= p[i]._memtotal, i++) { 246 if (offset >= p[i]._memtotal) 247 continue; 248 // now lookup the cluster's address 249 return p[i].lut[offset / p[i]._objsize].paddr + 250 offset % p[i]._objsize; 251 } 252 /* this is only in case of errors */ 253 D("invalid ofs 0x%x out of 0x%x 0x%x 0x%x", (u_int)o, 254 p[NETMAP_IF_POOL]._memtotal, 255 p[NETMAP_IF_POOL]._memtotal 256 + p[NETMAP_RING_POOL]._memtotal, 257 p[NETMAP_IF_POOL]._memtotal 258 + p[NETMAP_RING_POOL]._memtotal 259 + p[NETMAP_BUF_POOL]._memtotal); 260 return 0; // XXX bad address 261 } 262 263 /* 264 * we store objects by kernel address, need to find the offset 265 * within the pool to export the value to userspace. 266 * Algorithm: scan until we find the cluster, then add the 267 * actual offset in the cluster 268 */ 269 static ssize_t 270 netmap_obj_offset(struct netmap_obj_pool *p, const void *vaddr) 271 { 272 int i, k = p->clustentries, n = p->objtotal; 273 ssize_t ofs = 0; 274 275 for (i = 0; i < n; i += k, ofs += p->_clustsize) { 276 const char *base = p->lut[i].vaddr; 277 ssize_t relofs = (const char *) vaddr - base; 278 279 if (relofs < 0 || relofs >= p->_clustsize) 280 continue; 281 282 ofs = ofs + relofs; 283 ND("%s: return offset %d (cluster %d) for pointer %p", 284 p->name, ofs, i, vaddr); 285 return ofs; 286 } 287 D("address %p is not contained inside any cluster (%s)", 288 vaddr, p->name); 289 return 0; /* An error occurred */ 290 } 291 292 /* Helper functions which convert virtual addresses to offsets */ 293 #define netmap_if_offset(v) \ 294 netmap_obj_offset(&nm_mem.pools[NETMAP_IF_POOL], (v)) 295 296 #define netmap_ring_offset(v) \ 297 (nm_mem.pools[NETMAP_IF_POOL]._memtotal + \ 298 netmap_obj_offset(&nm_mem.pools[NETMAP_RING_POOL], (v))) 299 300 #define netmap_buf_offset(v) \ 301 (nm_mem.pools[NETMAP_IF_POOL]._memtotal + \ 302 nm_mem.pools[NETMAP_RING_POOL]._memtotal + \ 303 netmap_obj_offset(&nm_mem.pools[NETMAP_BUF_POOL], (v))) 304 305 306 /* 307 * report the index, and use start position as a hint, 308 * otherwise buffer allocation becomes terribly expensive. 309 */ 310 static void * 311 netmap_obj_malloc(struct netmap_obj_pool *p, int len, uint32_t *start, uint32_t *index) 312 { 313 uint32_t i = 0; /* index in the bitmap */ 314 uint32_t mask, j; /* slot counter */ 315 void *vaddr = NULL; 316 317 if (len > p->_objsize) { 318 D("%s request size %d too large", p->name, len); 319 // XXX cannot reduce the size 320 return NULL; 321 } 322 323 if (p->objfree == 0) { 324 D("%s allocator: run out of memory", p->name); 325 return NULL; 326 } 327 if (start) 328 i = *start; 329 330 /* termination is guaranteed by p->free, but better check bounds on i */ 331 while (vaddr == NULL && i < p->bitmap_slots) { 332 uint32_t cur = p->bitmap[i]; 333 if (cur == 0) { /* bitmask is fully used */ 334 i++; 335 continue; 336 } 337 /* locate a slot */ 338 for (j = 0, mask = 1; (cur & mask) == 0; j++, mask <<= 1) 339 ; 340 341 p->bitmap[i] &= ~mask; /* mark object as in use */ 342 p->objfree--; 343 344 vaddr = p->lut[i * 32 + j].vaddr; 345 if (index) 346 *index = i * 32 + j; 347 } 348 ND("%s allocator: allocated object @ [%d][%d]: vaddr %p", i, j, vaddr); 349 350 if (start) 351 *start = i; 352 return vaddr; 353 } 354 355 356 /* 357 * free by index, not by address. This is slow, but is only used 358 * for a small number of objects (rings, nifp) 359 */ 360 static void 361 netmap_obj_free(struct netmap_obj_pool *p, uint32_t j) 362 { 363 if (j >= p->objtotal) { 364 D("invalid index %u, max %u", j, p->objtotal); 365 return; 366 } 367 p->bitmap[j / 32] |= (1 << (j % 32)); 368 p->objfree++; 369 return; 370 } 371 372 static void 373 netmap_obj_free_va(struct netmap_obj_pool *p, void *vaddr) 374 { 375 int i, j, n = p->_memtotal / p->_clustsize; 376 377 for (i = 0, j = 0; i < n; i++, j += p->clustentries) { 378 void *base = p->lut[i * p->clustentries].vaddr; 379 ssize_t relofs = (ssize_t) vaddr - (ssize_t) base; 380 381 /* Given address, is out of the scope of the current cluster.*/ 382 if (vaddr < base || relofs > p->_clustsize) 383 continue; 384 385 j = j + relofs / p->_objsize; 386 KASSERT(j != 0, ("Cannot free object 0")); 387 netmap_obj_free(p, j); 388 return; 389 } 390 D("address %p is not contained inside any cluster (%s)", 391 vaddr, p->name); 392 } 393 394 #define netmap_if_malloc(len) netmap_obj_malloc(&nm_mem.pools[NETMAP_IF_POOL], len, NULL, NULL) 395 #define netmap_if_free(v) netmap_obj_free_va(&nm_mem.pools[NETMAP_IF_POOL], (v)) 396 #define netmap_ring_malloc(len) netmap_obj_malloc(&nm_mem.pools[NETMAP_RING_POOL], len, NULL, NULL) 397 #define netmap_ring_free(v) netmap_obj_free_va(&nm_mem.pools[NETMAP_RING_POOL], (v)) 398 #define netmap_buf_malloc(_pos, _index) \ 399 netmap_obj_malloc(&nm_mem.pools[NETMAP_BUF_POOL], NETMAP_BUF_SIZE, _pos, _index) 400 401 402 /* Return the index associated to the given packet buffer */ 403 #define netmap_buf_index(v) \ 404 (netmap_obj_offset(&nm_mem.pools[NETMAP_BUF_POOL], (v)) / nm_mem.pools[NETMAP_BUF_POOL]._objsize) 405 406 407 /* Return nonzero on error */ 408 static int 409 netmap_new_bufs(struct netmap_if *nifp, 410 struct netmap_slot *slot, u_int n) 411 { 412 struct netmap_obj_pool *p = &nm_mem.pools[NETMAP_BUF_POOL]; 413 int i = 0; /* slot counter */ 414 uint32_t pos = 0; /* slot in p->bitmap */ 415 uint32_t index = 0; /* buffer index */ 416 417 (void)nifp; /* UNUSED */ 418 for (i = 0; i < n; i++) { 419 void *vaddr = netmap_buf_malloc(&pos, &index); 420 if (vaddr == NULL) { 421 D("unable to locate empty packet buffer"); 422 goto cleanup; 423 } 424 slot[i].buf_idx = index; 425 slot[i].len = p->_objsize; 426 /* XXX setting flags=NS_BUF_CHANGED forces a pointer reload 427 * in the NIC ring. This is a hack that hides missing 428 * initializations in the drivers, and should go away. 429 */ 430 // slot[i].flags = NS_BUF_CHANGED; 431 } 432 433 ND("allocated %d buffers, %d available, first at %d", n, p->objfree, pos); 434 return (0); 435 436 cleanup: 437 while (i > 0) { 438 i--; 439 netmap_obj_free(p, slot[i].buf_idx); 440 } 441 bzero(slot, n * sizeof(slot[0])); 442 return (ENOMEM); 443 } 444 445 446 static void 447 netmap_free_buf(struct netmap_if *nifp, uint32_t i) 448 { 449 struct netmap_obj_pool *p = &nm_mem.pools[NETMAP_BUF_POOL]; 450 451 if (i < 2 || i >= p->objtotal) { 452 D("Cannot free buf#%d: should be in [2, %d[", i, p->objtotal); 453 return; 454 } 455 netmap_obj_free(p, i); 456 } 457 458 static void 459 netmap_reset_obj_allocator(struct netmap_obj_pool *p) 460 { 461 if (p == NULL) 462 return; 463 if (p->bitmap) 464 free(p->bitmap, M_NETMAP); 465 p->bitmap = NULL; 466 if (p->lut) { 467 int i; 468 for (i = 0; i < p->objtotal; i += p->clustentries) { 469 if (p->lut[i].vaddr) 470 contigfree(p->lut[i].vaddr, p->_clustsize, M_NETMAP); 471 } 472 bzero(p->lut, sizeof(struct lut_entry) * p->objtotal); 473 #ifdef linux 474 vfree(p->lut); 475 #else 476 free(p->lut, M_NETMAP); 477 #endif 478 } 479 p->lut = NULL; 480 } 481 482 /* 483 * Free all resources related to an allocator. 484 */ 485 static void 486 netmap_destroy_obj_allocator(struct netmap_obj_pool *p) 487 { 488 if (p == NULL) 489 return; 490 netmap_reset_obj_allocator(p); 491 } 492 493 /* 494 * We receive a request for objtotal objects, of size objsize each. 495 * Internally we may round up both numbers, as we allocate objects 496 * in small clusters multiple of the page size. 497 * In the allocator we don't need to store the objsize, 498 * but we do need to keep track of objtotal' and clustentries, 499 * as they are needed when freeing memory. 500 * 501 * XXX note -- userspace needs the buffers to be contiguous, 502 * so we cannot afford gaps at the end of a cluster. 503 */ 504 505 506 /* call with NMA_LOCK held */ 507 static int 508 netmap_config_obj_allocator(struct netmap_obj_pool *p, u_int objtotal, u_int objsize) 509 { 510 int i, n; 511 u_int clustsize; /* the cluster size, multiple of page size */ 512 u_int clustentries; /* how many objects per entry */ 513 514 #define MAX_CLUSTSIZE (1<<17) 515 #define LINE_ROUND 64 516 if (objsize >= MAX_CLUSTSIZE) { 517 /* we could do it but there is no point */ 518 D("unsupported allocation for %d bytes", objsize); 519 goto error; 520 } 521 /* make sure objsize is a multiple of LINE_ROUND */ 522 i = (objsize & (LINE_ROUND - 1)); 523 if (i) { 524 D("XXX aligning object by %d bytes", LINE_ROUND - i); 525 objsize += LINE_ROUND - i; 526 } 527 if (objsize < p->objminsize || objsize > p->objmaxsize) { 528 D("requested objsize %d out of range [%d, %d]", 529 objsize, p->objminsize, p->objmaxsize); 530 goto error; 531 } 532 if (objtotal < p->nummin || objtotal > p->nummax) { 533 D("requested objtotal %d out of range [%d, %d]", 534 objtotal, p->nummin, p->nummax); 535 goto error; 536 } 537 /* 538 * Compute number of objects using a brute-force approach: 539 * given a max cluster size, 540 * we try to fill it with objects keeping track of the 541 * wasted space to the next page boundary. 542 */ 543 for (clustentries = 0, i = 1;; i++) { 544 u_int delta, used = i * objsize; 545 if (used > MAX_CLUSTSIZE) 546 break; 547 delta = used % PAGE_SIZE; 548 if (delta == 0) { // exact solution 549 clustentries = i; 550 break; 551 } 552 if (delta > ( (clustentries*objsize) % PAGE_SIZE) ) 553 clustentries = i; 554 } 555 // D("XXX --- ouch, delta %d (bad for buffers)", delta); 556 /* compute clustsize and round to the next page */ 557 clustsize = clustentries * objsize; 558 i = (clustsize & (PAGE_SIZE - 1)); 559 if (i) 560 clustsize += PAGE_SIZE - i; 561 if (netmap_verbose) 562 D("objsize %d clustsize %d objects %d", 563 objsize, clustsize, clustentries); 564 565 /* 566 * The number of clusters is n = ceil(objtotal/clustentries) 567 * objtotal' = n * clustentries 568 */ 569 p->clustentries = clustentries; 570 p->_clustsize = clustsize; 571 n = (objtotal + clustentries - 1) / clustentries; 572 p->_numclusters = n; 573 p->objtotal = n * clustentries; 574 p->objfree = p->objtotal - 2; /* obj 0 and 1 are reserved */ 575 p->_memtotal = p->_numclusters * p->_clustsize; 576 p->_objsize = objsize; 577 578 return 0; 579 580 error: 581 p->_objsize = objsize; 582 p->objtotal = objtotal; 583 584 return EINVAL; 585 } 586 587 588 /* call with NMA_LOCK held */ 589 static int 590 netmap_finalize_obj_allocator(struct netmap_obj_pool *p) 591 { 592 int i, n; 593 594 n = sizeof(struct lut_entry) * p->objtotal; 595 #ifdef linux 596 p->lut = vmalloc(n); 597 #else 598 p->lut = malloc(n, M_NETMAP, M_NOWAIT | M_ZERO); 599 #endif 600 if (p->lut == NULL) { 601 D("Unable to create lookup table (%d bytes) for '%s'", n, p->name); 602 goto clean; 603 } 604 605 /* Allocate the bitmap */ 606 n = (p->objtotal + 31) / 32; 607 p->bitmap = malloc(sizeof(uint32_t) * n, M_NETMAP, M_NOWAIT | M_ZERO); 608 if (p->bitmap == NULL) { 609 D("Unable to create bitmap (%d entries) for allocator '%s'", n, 610 p->name); 611 goto clean; 612 } 613 p->bitmap_slots = n; 614 615 /* 616 * Allocate clusters, init pointers and bitmap 617 */ 618 for (i = 0; i < p->objtotal;) { 619 int lim = i + p->clustentries; 620 char *clust; 621 622 clust = contigmalloc(p->_clustsize, M_NETMAP, M_NOWAIT | M_ZERO, 623 0, -1UL, PAGE_SIZE, 0); 624 if (clust == NULL) { 625 /* 626 * If we get here, there is a severe memory shortage, 627 * so halve the allocated memory to reclaim some. 628 * XXX check boundaries 629 */ 630 D("Unable to create cluster at %d for '%s' allocator", 631 i, p->name); 632 lim = i / 2; 633 for (i--; i >= lim; i--) { 634 p->bitmap[ (i>>5) ] &= ~( 1 << (i & 31) ); 635 if (i % p->clustentries == 0 && p->lut[i].vaddr) 636 contigfree(p->lut[i].vaddr, 637 p->_clustsize, M_NETMAP); 638 } 639 p->objtotal = i; 640 p->objfree = p->objtotal - 2; 641 p->_numclusters = i / p->clustentries; 642 p->_memtotal = p->_numclusters * p->_clustsize; 643 break; 644 } 645 for (; i < lim; i++, clust += p->_objsize) { 646 p->bitmap[ (i>>5) ] |= ( 1 << (i & 31) ); 647 p->lut[i].vaddr = clust; 648 p->lut[i].paddr = vtophys(clust); 649 } 650 } 651 p->bitmap[0] = ~3; /* objs 0 and 1 is always busy */ 652 if (netmap_verbose) 653 D("Pre-allocated %d clusters (%d/%dKB) for '%s'", 654 p->_numclusters, p->_clustsize >> 10, 655 p->_memtotal >> 10, p->name); 656 657 return 0; 658 659 clean: 660 netmap_reset_obj_allocator(p); 661 return ENOMEM; 662 } 663 664 /* call with lock held */ 665 static int 666 netmap_memory_config_changed(void) 667 { 668 int i; 669 670 for (i = 0; i < NETMAP_POOLS_NR; i++) { 671 if (nm_mem.pools[i]._objsize != netmap_params[i].size || 672 nm_mem.pools[i].objtotal != netmap_params[i].num) 673 return 1; 674 } 675 return 0; 676 } 677 678 679 /* call with lock held */ 680 static int 681 netmap_memory_config(void) 682 { 683 int i; 684 685 if (!netmap_memory_config_changed()) 686 goto out; 687 688 D("reconfiguring"); 689 690 if (nm_mem.finalized) { 691 /* reset previous allocation */ 692 for (i = 0; i < NETMAP_POOLS_NR; i++) { 693 netmap_reset_obj_allocator(&nm_mem.pools[i]); 694 } 695 nm_mem.finalized = 0; 696 } 697 698 for (i = 0; i < NETMAP_POOLS_NR; i++) { 699 nm_mem.lasterr = netmap_config_obj_allocator(&nm_mem.pools[i], 700 netmap_params[i].num, netmap_params[i].size); 701 if (nm_mem.lasterr) 702 goto out; 703 } 704 705 D("Have %d KB for interfaces, %d KB for rings and %d MB for buffers", 706 nm_mem.pools[NETMAP_IF_POOL]._memtotal >> 10, 707 nm_mem.pools[NETMAP_RING_POOL]._memtotal >> 10, 708 nm_mem.pools[NETMAP_BUF_POOL]._memtotal >> 20); 709 710 out: 711 712 return nm_mem.lasterr; 713 } 714 715 /* call with lock held */ 716 static int 717 netmap_memory_finalize(void) 718 { 719 int i; 720 u_int totalsize = 0; 721 722 nm_mem.refcount++; 723 if (nm_mem.refcount > 1) { 724 ND("busy (refcount %d)", nm_mem.refcount); 725 goto out; 726 } 727 728 /* update configuration if changed */ 729 if (netmap_memory_config()) 730 goto out; 731 732 if (nm_mem.finalized) { 733 /* may happen if config is not changed */ 734 ND("nothing to do"); 735 goto out; 736 } 737 738 for (i = 0; i < NETMAP_POOLS_NR; i++) { 739 nm_mem.lasterr = netmap_finalize_obj_allocator(&nm_mem.pools[i]); 740 if (nm_mem.lasterr) 741 goto cleanup; 742 totalsize += nm_mem.pools[i]._memtotal; 743 } 744 nm_mem.nm_totalsize = totalsize; 745 746 /* backward compatibility */ 747 netmap_buf_size = nm_mem.pools[NETMAP_BUF_POOL]._objsize; 748 netmap_total_buffers = nm_mem.pools[NETMAP_BUF_POOL].objtotal; 749 750 netmap_buffer_lut = nm_mem.pools[NETMAP_BUF_POOL].lut; 751 netmap_buffer_base = nm_mem.pools[NETMAP_BUF_POOL].lut[0].vaddr; 752 753 nm_mem.finalized = 1; 754 nm_mem.lasterr = 0; 755 756 /* make sysctl values match actual values in the pools */ 757 for (i = 0; i < NETMAP_POOLS_NR; i++) { 758 netmap_params[i].size = nm_mem.pools[i]._objsize; 759 netmap_params[i].num = nm_mem.pools[i].objtotal; 760 } 761 762 out: 763 if (nm_mem.lasterr) 764 nm_mem.refcount--; 765 766 return nm_mem.lasterr; 767 768 cleanup: 769 for (i = 0; i < NETMAP_POOLS_NR; i++) { 770 netmap_reset_obj_allocator(&nm_mem.pools[i]); 771 } 772 nm_mem.refcount--; 773 774 return nm_mem.lasterr; 775 } 776 777 static int 778 netmap_memory_init(void) 779 { 780 NMA_LOCK_INIT(); 781 return (0); 782 } 783 784 static void 785 netmap_memory_fini(void) 786 { 787 int i; 788 789 for (i = 0; i < NETMAP_POOLS_NR; i++) { 790 netmap_destroy_obj_allocator(&nm_mem.pools[i]); 791 } 792 NMA_LOCK_DESTROY(); 793 } 794 795 static void 796 netmap_free_rings(struct netmap_adapter *na) 797 { 798 int i; 799 if (!na->tx_rings) 800 return; 801 for (i = 0; i < na->num_tx_rings + 1; i++) { 802 netmap_ring_free(na->tx_rings[i].ring); 803 na->tx_rings[i].ring = NULL; 804 } 805 for (i = 0; i < na->num_rx_rings + 1; i++) { 806 netmap_ring_free(na->rx_rings[i].ring); 807 na->rx_rings[i].ring = NULL; 808 } 809 free(na->tx_rings, M_DEVBUF); 810 na->tx_rings = na->rx_rings = NULL; 811 } 812 813 814 815 /* call with NMA_LOCK held */ 816 /* 817 * Allocate the per-fd structure netmap_if. 818 * If this is the first instance, also allocate the krings, rings etc. 819 */ 820 static void * 821 netmap_if_new(const char *ifname, struct netmap_adapter *na) 822 { 823 struct netmap_if *nifp; 824 struct netmap_ring *ring; 825 ssize_t base; /* handy for relative offsets between rings and nifp */ 826 u_int i, len, ndesc, ntx, nrx; 827 struct netmap_kring *kring; 828 829 if (netmap_update_config(na)) { 830 /* configuration mismatch, report and fail */ 831 return NULL; 832 } 833 ntx = na->num_tx_rings + 1; /* shorthand, include stack ring */ 834 nrx = na->num_rx_rings + 1; /* shorthand, include stack ring */ 835 /* 836 * the descriptor is followed inline by an array of offsets 837 * to the tx and rx rings in the shared memory region. 838 */ 839 len = sizeof(struct netmap_if) + (nrx + ntx) * sizeof(ssize_t); 840 nifp = netmap_if_malloc(len); 841 if (nifp == NULL) { 842 return NULL; 843 } 844 845 /* initialize base fields -- override const */ 846 *(int *)(uintptr_t)&nifp->ni_tx_rings = na->num_tx_rings; 847 *(int *)(uintptr_t)&nifp->ni_rx_rings = na->num_rx_rings; 848 strncpy(nifp->ni_name, ifname, IFNAMSIZ); 849 850 (na->refcount)++; /* XXX atomic ? we are under lock */ 851 if (na->refcount > 1) { /* already setup, we are done */ 852 goto final; 853 } 854 855 len = (ntx + nrx) * sizeof(struct netmap_kring); 856 na->tx_rings = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 857 if (na->tx_rings == NULL) { 858 D("Cannot allocate krings for %s", ifname); 859 goto cleanup; 860 } 861 na->rx_rings = na->tx_rings + ntx; 862 863 /* 864 * First instance, allocate netmap rings and buffers for this card 865 * The rings are contiguous, but have variable size. 866 */ 867 for (i = 0; i < ntx; i++) { /* Transmit rings */ 868 kring = &na->tx_rings[i]; 869 ndesc = na->num_tx_desc; 870 bzero(kring, sizeof(*kring)); 871 len = sizeof(struct netmap_ring) + 872 ndesc * sizeof(struct netmap_slot); 873 ring = netmap_ring_malloc(len); 874 if (ring == NULL) { 875 D("Cannot allocate tx_ring[%d] for %s", i, ifname); 876 goto cleanup; 877 } 878 ND("txring[%d] at %p ofs %d", i, ring); 879 kring->na = na; 880 kring->ring = ring; 881 *(int *)(uintptr_t)&ring->num_slots = kring->nkr_num_slots = ndesc; 882 *(ssize_t *)(uintptr_t)&ring->buf_ofs = 883 (nm_mem.pools[NETMAP_IF_POOL]._memtotal + 884 nm_mem.pools[NETMAP_RING_POOL]._memtotal) - 885 netmap_ring_offset(ring); 886 887 /* 888 * IMPORTANT: 889 * Always keep one slot empty, so we can detect new 890 * transmissions comparing cur and nr_hwcur (they are 891 * the same only if there are no new transmissions). 892 */ 893 ring->avail = kring->nr_hwavail = ndesc - 1; 894 ring->cur = kring->nr_hwcur = 0; 895 *(int *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE; 896 ND("initializing slots for txring[%d]", i); 897 if (netmap_new_bufs(nifp, ring->slot, ndesc)) { 898 D("Cannot allocate buffers for tx_ring[%d] for %s", i, ifname); 899 goto cleanup; 900 } 901 } 902 903 for (i = 0; i < nrx; i++) { /* Receive rings */ 904 kring = &na->rx_rings[i]; 905 ndesc = na->num_rx_desc; 906 bzero(kring, sizeof(*kring)); 907 len = sizeof(struct netmap_ring) + 908 ndesc * sizeof(struct netmap_slot); 909 ring = netmap_ring_malloc(len); 910 if (ring == NULL) { 911 D("Cannot allocate rx_ring[%d] for %s", i, ifname); 912 goto cleanup; 913 } 914 ND("rxring[%d] at %p ofs %d", i, ring); 915 916 kring->na = na; 917 kring->ring = ring; 918 *(int *)(uintptr_t)&ring->num_slots = kring->nkr_num_slots = ndesc; 919 *(ssize_t *)(uintptr_t)&ring->buf_ofs = 920 (nm_mem.pools[NETMAP_IF_POOL]._memtotal + 921 nm_mem.pools[NETMAP_RING_POOL]._memtotal) - 922 netmap_ring_offset(ring); 923 924 ring->cur = kring->nr_hwcur = 0; 925 ring->avail = kring->nr_hwavail = 0; /* empty */ 926 *(int *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE; 927 ND("initializing slots for rxring[%d]", i); 928 if (netmap_new_bufs(nifp, ring->slot, ndesc)) { 929 D("Cannot allocate buffers for rx_ring[%d] for %s", i, ifname); 930 goto cleanup; 931 } 932 } 933 #ifdef linux 934 // XXX initialize the selrecord structs. 935 for (i = 0; i < ntx; i++) 936 init_waitqueue_head(&na->tx_rings[i].si); 937 for (i = 0; i < nrx; i++) 938 init_waitqueue_head(&na->rx_rings[i].si); 939 init_waitqueue_head(&na->tx_si); 940 init_waitqueue_head(&na->rx_si); 941 #endif 942 final: 943 /* 944 * fill the slots for the rx and tx rings. They contain the offset 945 * between the ring and nifp, so the information is usable in 946 * userspace to reach the ring from the nifp. 947 */ 948 base = netmap_if_offset(nifp); 949 for (i = 0; i < ntx; i++) { 950 *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] = 951 netmap_ring_offset(na->tx_rings[i].ring) - base; 952 } 953 for (i = 0; i < nrx; i++) { 954 *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+ntx] = 955 netmap_ring_offset(na->rx_rings[i].ring) - base; 956 } 957 return (nifp); 958 cleanup: 959 netmap_free_rings(na); 960 netmap_if_free(nifp); 961 (na->refcount)--; 962 return NULL; 963 } 964 965 /* call with NMA_LOCK held */ 966 static void 967 netmap_memory_deref(void) 968 { 969 nm_mem.refcount--; 970 if (netmap_verbose) 971 D("refcount = %d", nm_mem.refcount); 972 } 973