netmap.c (228845) | netmap.c (229939) |
---|---|
1/* 2 * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. 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. --- 10 unchanged lines hidden (view full) --- 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/* | 1/* 2 * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. 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. --- 10 unchanged lines hidden (view full) --- 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: head/sys/dev/netmap/netmap.c 228845 2011-12-23 16:03:57Z luigi $ | 27 * $FreeBSD: head/sys/dev/netmap/netmap.c 229939 2012-01-10 19:57:23Z luigi $ |
28 * $Id: netmap.c 9795 2011-12-02 11:39:08Z luigi $ 29 * 30 * This module supports memory mapped access to network devices, 31 * see netmap(4). 32 * 33 * The module uses a large, memory pool allocated by the kernel 34 * and accessible as mmapped memory by multiple userspace threads/processes. 35 * The memory pool contains packet buffers and "netmap rings", --- 15 unchanged lines hidden (view full) --- 51 * of the queue with the actual status in the kernel. This includes both 52 * receiving the notification of new packets, and transmitting new 53 * packets on the output interface. 54 * 6. select() or poll() can be used to wait for events on individual 55 * transmit or receive queues (or all queues for a given interface). 56 */ 57 58#include <sys/cdefs.h> /* prerequisite */ | 28 * $Id: netmap.c 9795 2011-12-02 11:39:08Z luigi $ 29 * 30 * This module supports memory mapped access to network devices, 31 * see netmap(4). 32 * 33 * The module uses a large, memory pool allocated by the kernel 34 * and accessible as mmapped memory by multiple userspace threads/processes. 35 * The memory pool contains packet buffers and "netmap rings", --- 15 unchanged lines hidden (view full) --- 51 * of the queue with the actual status in the kernel. This includes both 52 * receiving the notification of new packets, and transmitting new 53 * packets on the output interface. 54 * 6. select() or poll() can be used to wait for events on individual 55 * transmit or receive queues (or all queues for a given interface). 56 */ 57 58#include <sys/cdefs.h> /* prerequisite */ |
59__FBSDID("$FreeBSD: head/sys/dev/netmap/netmap.c 228845 2011-12-23 16:03:57Z luigi $"); | 59__FBSDID("$FreeBSD: head/sys/dev/netmap/netmap.c 229939 2012-01-10 19:57:23Z luigi $"); |
60 61#include <sys/types.h> 62#include <sys/module.h> 63#include <sys/errno.h> 64#include <sys/param.h> /* defines used in kernel.h */ 65#include <sys/jail.h> 66#include <sys/kernel.h> /* types used in module initialization */ 67#include <sys/conf.h> /* cdevsw struct */ --- 31 unchanged lines hidden (view full) --- 99 * according to what is avalable when the module is loaded. 100 * At the moment the block is contiguous, but we can easily 101 * restrict our demand to smaller units (16..64k) 102 */ 103#define NETMAP_MEMORY_SIZE (64 * 1024 * PAGE_SIZE) 104static void * netmap_malloc(size_t size, const char *msg); 105static void netmap_free(void *addr, const char *msg); 106 | 60 61#include <sys/types.h> 62#include <sys/module.h> 63#include <sys/errno.h> 64#include <sys/param.h> /* defines used in kernel.h */ 65#include <sys/jail.h> 66#include <sys/kernel.h> /* types used in module initialization */ 67#include <sys/conf.h> /* cdevsw struct */ --- 31 unchanged lines hidden (view full) --- 99 * according to what is avalable when the module is loaded. 100 * At the moment the block is contiguous, but we can easily 101 * restrict our demand to smaller units (16..64k) 102 */ 103#define NETMAP_MEMORY_SIZE (64 * 1024 * PAGE_SIZE) 104static void * netmap_malloc(size_t size, const char *msg); 105static void netmap_free(void *addr, const char *msg); 106 |
107#define netmap_if_malloc(len) netmap_malloc(len, "nifp") 108#define netmap_if_free(v) netmap_free((v), "nifp") 109 110#define netmap_ring_malloc(len) netmap_malloc(len, "ring") 111#define netmap_free_rings(na) \ 112 netmap_free((na)->tx_rings[0].ring, "shadow rings"); 113 |
|
107/* 108 * Allocator for a pool of packet buffers. For each buffer we have 109 * one entry in the bitmap to signal the state. Allocation scans 110 * the bitmap, but since this is done only on attach, we are not 111 * too worried about performance 112 * XXX if we need to allocate small blocks, a translation 113 * table is used both for kernel virtual address and physical 114 * addresses. 115 */ 116struct netmap_buf_pool { 117 u_int total_buffers; /* total buffers. */ 118 u_int free; 119 u_int bufsize; 120 char *base; /* buffer base address */ 121 uint32_t *bitmap; /* one bit per buffer, 1 means free */ 122}; 123struct netmap_buf_pool nm_buf_pool; 124/* XXX move these two vars back into netmap_buf_pool */ 125u_int netmap_total_buffers; | 114/* 115 * Allocator for a pool of packet buffers. For each buffer we have 116 * one entry in the bitmap to signal the state. Allocation scans 117 * the bitmap, but since this is done only on attach, we are not 118 * too worried about performance 119 * XXX if we need to allocate small blocks, a translation 120 * table is used both for kernel virtual address and physical 121 * addresses. 122 */ 123struct netmap_buf_pool { 124 u_int total_buffers; /* total buffers. */ 125 u_int free; 126 u_int bufsize; 127 char *base; /* buffer base address */ 128 uint32_t *bitmap; /* one bit per buffer, 1 means free */ 129}; 130struct netmap_buf_pool nm_buf_pool; 131/* XXX move these two vars back into netmap_buf_pool */ 132u_int netmap_total_buffers; |
126char *netmap_buffer_base; | 133char *netmap_buffer_base; /* address of an invalid buffer */ |
127 128/* user-controlled variables */ 129int netmap_verbose; 130 131static int no_timestamp; /* don't timestamp on rxsync */ 132 133SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args"); 134SYSCTL_INT(_dev_netmap, OID_AUTO, verbose, --- 93 unchanged lines hidden (view full) --- 228 struct netmap_if *np_nifp; /* netmap interface descriptor. */ 229 230 struct ifnet *np_ifp; /* device for which we hold a reference */ 231 int np_ringid; /* from the ioctl */ 232 u_int np_qfirst, np_qlast; /* range of rings to scan */ 233 uint16_t np_txpoll; 234}; 235 | 134 135/* user-controlled variables */ 136int netmap_verbose; 137 138static int no_timestamp; /* don't timestamp on rxsync */ 139 140SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args"); 141SYSCTL_INT(_dev_netmap, OID_AUTO, verbose, --- 93 unchanged lines hidden (view full) --- 235 struct netmap_if *np_nifp; /* netmap interface descriptor. */ 236 237 struct ifnet *np_ifp; /* device for which we hold a reference */ 238 int np_ringid; /* from the ioctl */ 239 u_int np_qfirst, np_qlast; /* range of rings to scan */ 240 uint16_t np_txpoll; 241}; 242 |
243/* Shorthand to compute a netmap interface offset. */ 244#define netmap_if_offset(v) \ 245 ((char *) (v) - (char *) netmap_mem_d->nm_buffer) 246/* .. and get a physical address given a memory offset */ 247#define netmap_ofstophys(o) \ 248 (vtophys(netmap_mem_d->nm_buffer) + (o)) |
|
236 237static struct cdev *netmap_dev; /* /dev/netmap character device. */ 238static struct netmap_mem_d *netmap_mem_d; /* Our memory allocator. */ 239 240 241static d_mmap_t netmap_mmap; 242static d_ioctl_t netmap_ioctl; 243static d_poll_t netmap_poll; --- 148 unchanged lines hidden (view full) --- 392 ND("rx queue %d", i); 393 ring = na->rx_rings[i].ring; 394 lim = na->rx_rings[i].nkr_num_slots; 395 for (j = 0; j < lim; j++) 396 netmap_free_buf(&nm_buf_pool, 397 ring->slot[j].buf_idx); 398 } 399 NMA_UNLOCK(); | 249 250static struct cdev *netmap_dev; /* /dev/netmap character device. */ 251static struct netmap_mem_d *netmap_mem_d; /* Our memory allocator. */ 252 253 254static d_mmap_t netmap_mmap; 255static d_ioctl_t netmap_ioctl; 256static d_poll_t netmap_poll; --- 148 unchanged lines hidden (view full) --- 405 ND("rx queue %d", i); 406 ring = na->rx_rings[i].ring; 407 lim = na->rx_rings[i].nkr_num_slots; 408 for (j = 0; j < lim; j++) 409 netmap_free_buf(&nm_buf_pool, 410 ring->slot[j].buf_idx); 411 } 412 NMA_UNLOCK(); |
400 netmap_free(na->tx_rings[0].ring, "shadow rings"); | 413 netmap_free_rings(na); |
401 wakeup(na); 402 } | 414 wakeup(na); 415 } |
403 netmap_free(nifp, "nifp"); | 416 netmap_if_free(nifp); |
404 405 na->nm_lock(ifp->if_softc, NETMAP_CORE_UNLOCK, 0); 406 407 if_rele(ifp); 408 409 bzero(priv, sizeof(*priv)); /* XXX for safety */ 410 free(priv, M_DEVBUF); 411} --- 15 unchanged lines hidden (view full) --- 427 u_int i, len, ofs; 428 u_int n = na->num_queues + 1; /* shorthand, include stack queue */ 429 430 /* 431 * the descriptor is followed inline by an array of offsets 432 * to the tx and rx rings in the shared memory region. 433 */ 434 len = sizeof(struct netmap_if) + 2 * n * sizeof(ssize_t); | 417 418 na->nm_lock(ifp->if_softc, NETMAP_CORE_UNLOCK, 0); 419 420 if_rele(ifp); 421 422 bzero(priv, sizeof(*priv)); /* XXX for safety */ 423 free(priv, M_DEVBUF); 424} --- 15 unchanged lines hidden (view full) --- 440 u_int i, len, ofs; 441 u_int n = na->num_queues + 1; /* shorthand, include stack queue */ 442 443 /* 444 * the descriptor is followed inline by an array of offsets 445 * to the tx and rx rings in the shared memory region. 446 */ 447 len = sizeof(struct netmap_if) + 2 * n * sizeof(ssize_t); |
435 nifp = netmap_malloc(len, "nifp"); | 448 nifp = netmap_if_malloc(len); |
436 if (nifp == NULL) 437 return (NULL); 438 439 /* initialize base fields */ 440 *(int *)(uintptr_t)&nifp->ni_num_queues = na->num_queues; 441 strncpy(nifp->ni_name, ifname, IFNAMSIZ); 442 443 (na->refcount)++; /* XXX atomic ? we are under lock */ --- 6 unchanged lines hidden (view full) --- 450 * The rings are contiguous, but have variable size. 451 * The entire block is reachable at 452 * na->tx_rings[0].ring 453 */ 454 455 len = n * (2 * sizeof(struct netmap_ring) + 456 (na->num_tx_desc + na->num_rx_desc) * 457 sizeof(struct netmap_slot) ); | 449 if (nifp == NULL) 450 return (NULL); 451 452 /* initialize base fields */ 453 *(int *)(uintptr_t)&nifp->ni_num_queues = na->num_queues; 454 strncpy(nifp->ni_name, ifname, IFNAMSIZ); 455 456 (na->refcount)++; /* XXX atomic ? we are under lock */ --- 6 unchanged lines hidden (view full) --- 463 * The rings are contiguous, but have variable size. 464 * The entire block is reachable at 465 * na->tx_rings[0].ring 466 */ 467 468 len = n * (2 * sizeof(struct netmap_ring) + 469 (na->num_tx_desc + na->num_rx_desc) * 470 sizeof(struct netmap_slot) ); |
458 buff = netmap_malloc(len, "shadow rings"); | 471 buff = netmap_ring_malloc(len); |
459 if (buff == NULL) { 460 D("failed to allocate %d bytes for %s shadow ring", 461 len, ifname); 462error: 463 (na->refcount)--; | 472 if (buff == NULL) { 473 D("failed to allocate %d bytes for %s shadow ring", 474 len, ifname); 475error: 476 (na->refcount)--; |
464 netmap_free(nifp, "nifp, rings failed"); | 477 netmap_if_free(nifp); |
465 return (NULL); 466 } 467 /* do we have the bufers ? we are in need of num_tx_desc buffers for 468 * each tx ring and num_tx_desc buffers for each rx ring. */ 469 len = n * (na->num_tx_desc + na->num_rx_desc); 470 NMA_LOCK(); 471 if (nm_buf_pool.free < len) { 472 NMA_UNLOCK(); --- 429 unchanged lines hidden (view full) --- 902 /* Otherwise set the card in netmap mode 903 * and make it use the shared buffers. 904 */ 905 error = na->nm_register(ifp, 1); /* mode on */ 906 if (error) { 907 /* 908 * do something similar to netmap_dtor(). 909 */ | 478 return (NULL); 479 } 480 /* do we have the bufers ? we are in need of num_tx_desc buffers for 481 * each tx ring and num_tx_desc buffers for each rx ring. */ 482 len = n * (na->num_tx_desc + na->num_rx_desc); 483 NMA_LOCK(); 484 if (nm_buf_pool.free < len) { 485 NMA_UNLOCK(); --- 429 unchanged lines hidden (view full) --- 915 /* Otherwise set the card in netmap mode 916 * and make it use the shared buffers. 917 */ 918 error = na->nm_register(ifp, 1); /* mode on */ 919 if (error) { 920 /* 921 * do something similar to netmap_dtor(). 922 */ |
910 netmap_free(na->tx_rings[0].ring, "rings, reg.failed"); 911 free(na->tx_rings, M_DEVBUF); | 923 netmap_free_rings(na); 924 // XXX tx_rings is inline, must not be freed. 925 // free(na->tx_rings, M_DEVBUF); // XXX wrong ? |
912 na->tx_rings = na->rx_rings = NULL; 913 na->refcount--; | 926 na->tx_rings = na->rx_rings = NULL; 927 na->refcount--; |
914 netmap_free(nifp, "nifp, rings failed"); | 928 netmap_if_free(nifp); |
915 nifp = NULL; 916 } 917 } 918 919 if (error) { /* reg. failed, release priv and ref */ 920error: 921 na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); 922 free(priv, M_DEVBUF); --- 460 unchanged lines hidden (view full) --- 1383{ 1384} 1385 1386/* unload a bus_dmamap and create a new one. Used when the 1387 * buffer in the slot is changed. 1388 * XXX buflen is probably not needed, buffers have constant size. 1389 */ 1390void | 929 nifp = NULL; 930 } 931 } 932 933 if (error) { /* reg. failed, release priv and ref */ 934error: 935 na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); 936 free(priv, M_DEVBUF); --- 460 unchanged lines hidden (view full) --- 1397{ 1398} 1399 1400/* unload a bus_dmamap and create a new one. Used when the 1401 * buffer in the slot is changed. 1402 * XXX buflen is probably not needed, buffers have constant size. 1403 */ 1404void |
1391netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, 1392 void *buf, bus_size_t buflen) | 1405netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) |
1393{ | 1406{ |
1394 bus_addr_t paddr; | |
1395 bus_dmamap_unload(tag, map); | 1407 bus_dmamap_unload(tag, map); |
1396 bus_dmamap_load(tag, map, buf, buflen, ns_dmamap_cb, &paddr, 1397 BUS_DMA_NOWAIT); | 1408 bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, ns_dmamap_cb, 1409 NULL, BUS_DMA_NOWAIT); |
1398} 1399 1400void | 1410} 1411 1412void |
1401netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, 1402 void *buf, bus_size_t buflen) | 1413netmap_load_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) |
1403{ | 1414{ |
1404 bus_addr_t paddr; 1405 bus_dmamap_load(tag, map, buf, buflen, ns_dmamap_cb, &paddr, 1406 BUS_DMA_NOWAIT); | 1415 bus_dmamap_load(tag, map, buf, NETMAP_BUF_SIZE, ns_dmamap_cb, 1416 NULL, BUS_DMA_NOWAIT); |
1407} 1408 1409/*------ netmap memory allocator -------*/ 1410/* 1411 * Request for a chunk of memory. 1412 * 1413 * Memory objects are arranged into a list, hence we need to walk this 1414 * list until we find an object with the needed amount of data free. --- 291 unchanged lines hidden --- | 1417} 1418 1419/*------ netmap memory allocator -------*/ 1420/* 1421 * Request for a chunk of memory. 1422 * 1423 * Memory objects are arranged into a list, hence we need to walk this 1424 * list until we find an object with the needed amount of data free. --- 291 unchanged lines hidden --- |