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