aboutsummaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2018-04-12 07:20:50 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2018-04-12 07:20:50 +0000
commit2ff91c175eca50b7d0d9da6b31eae4109c034137 (patch)
tree15a4f8847a8cabd782f67326125c48fed4fdd27b /sys/net
parent66def52613043a86172a2ebe6feab214258fa2fa (diff)
Notes
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/iflib.c4
-rw-r--r--sys/net/netmap.h461
-rw-r--r--sys/net/netmap_legacy.h264
-rw-r--r--sys/net/netmap_user.h286
-rw-r--r--sys/net/netmap_virt.h24
5 files changed, 579 insertions, 460 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index 336826686d98..4a5b8201cf21 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -1176,7 +1176,7 @@ iflib_netmap_txq_init(if_ctx_t ctx, iflib_txq_t txq)
* netmap_idx_n2k() maps a nic index, i, into the corresponding
* netmap slot index, si
*/
- int si = netmap_idx_n2k(&na->tx_rings[txq->ift_id], i);
+ int si = netmap_idx_n2k(na->tx_rings[txq->ift_id], i);
netmap_load_map(na, txq->ift_desc_tag, txq->ift_sds.ifsd_map[i], NMB(na, slot + si));
}
}
@@ -1185,7 +1185,7 @@ static void
iflib_netmap_rxq_init(if_ctx_t ctx, iflib_rxq_t rxq)
{
struct netmap_adapter *na = NA(ctx->ifc_ifp);
- struct netmap_kring *kring = &na->rx_rings[rxq->ifr_id];
+ struct netmap_kring *kring = na->rx_rings[rxq->ifr_id];
struct netmap_slot *slot;
uint32_t nm_i;
diff --git a/sys/net/netmap.h b/sys/net/netmap.h
index 53f2b41b0687..525b7f05a5e1 100644
--- a/sys/net/netmap.h
+++ b/sys/net/netmap.h
@@ -41,7 +41,7 @@
#ifndef _NET_NETMAP_H_
#define _NET_NETMAP_H_
-#define NETMAP_API 11 /* current API version */
+#define NETMAP_API 12 /* current API version */
#define NETMAP_MIN_API 11 /* min and max versions accepted */
#define NETMAP_MAX_API 15
@@ -326,6 +326,18 @@ struct netmap_ring {
* Enables the NS_FORWARD slot flag for the ring.
*/
+/*
+ * Helper functions for kernel and userspace
+ */
+
+/*
+ * check if space is available in the ring.
+ */
+static inline int
+nm_ring_empty(struct netmap_ring *ring)
+{
+ return (ring->cur == ring->tail);
+}
/*
* Netmap representation of an interface and its queue(s).
@@ -368,86 +380,75 @@ struct netmap_if {
const ssize_t ring_ofs[0];
};
+/* Legacy interface to interact with a netmap control device.
+ * Included for backward compatibility. The user should not include this
+ * file directly. */
+#include "netmap_legacy.h"
-#ifndef NIOCREGIF
/*
- * ioctl names and related fields
+ * New API to control netmap control devices. New applications should only use
+ * nmreq_xyz structs with the NIOCCTRL ioctl() command.
*
- * NIOCTXSYNC, NIOCRXSYNC synchronize tx or rx queues,
- * whose identity is set in NIOCREGIF through nr_ringid.
- * These are non blocking and take no argument.
- *
- * NIOCGINFO takes a struct ifreq, the interface name is the input,
- * the outputs are number of queues and number of descriptor
- * for each queue (useful to set number of threads etc.).
- * The info returned is only advisory and may change before
- * the interface is bound to a file descriptor.
+ * NIOCCTRL takes a nmreq_header struct, which contains the required
+ * API version, the name of a netmap port, a command type, and pointers
+ * to request body and options.
*
- * NIOCREGIF takes an interface name within a struct nmre,
- * and activates netmap mode on the interface (if possible).
+ * nr_name (in)
+ * The name of the port (em0, valeXXX:YYY, eth0{pn1 etc.)
*
- * The argument to NIOCGINFO/NIOCREGIF overlays struct ifreq so we
- * can pass it down to other NIC-related ioctls.
+ * nr_version (in/out)
+ * Must match NETMAP_API as used in the kernel, error otherwise.
+ * Always returns the desired value on output.
*
- * The actual argument (struct nmreq) has a number of options to request
- * different functions.
- * The following are used in NIOCREGIF when nr_cmd == 0:
+ * nr_reqtype (in)
+ * One of the NETMAP_REQ_* command types below
*
- * nr_name (in)
- * The name of the port (em0, valeXXX:YYY, etc.)
- * limited to IFNAMSIZ for backward compatibility.
+ * nr_body (in)
+ * Pointer to a command-specific struct, described by one
+ * of the struct nmreq_xyz below.
*
- * nr_version (in/out)
- * Must match NETMAP_API as used in the kernel, error otherwise.
- * Always returns the desired value on output.
+ * nr_options (in)
+ * Command specific options, if any.
*
- * nr_tx_slots, nr_tx_slots, nr_tx_rings, nr_rx_rings (in/out)
- * On input, non-zero values may be used to reconfigure the port
- * according to the requested values, but this is not guaranteed.
- * On output the actual values in use are reported.
+ * A NETMAP_REQ_REGISTER command activates netmap mode on the netmap
+ * port (e.g. physical interface) specified by nmreq_header.nr_name.
+ * The request body (struct nmreq_register) has several arguments to
+ * specify how the port is to be registered.
*
- * nr_ringid (in)
- * Indicates how rings should be bound to the file descriptors.
- * If nr_flags != 0, then the low bits (in NETMAP_RING_MASK)
- * are used to indicate the ring number, and nr_flags specifies
- * the actual rings to bind. NETMAP_NO_TX_POLL is unaffected.
+ * nr_tx_slots, nr_tx_slots, nr_tx_rings, nr_rx_rings (in/out)
+ * On input, non-zero values may be used to reconfigure the port
+ * according to the requested values, but this is not guaranteed.
+ * On output the actual values in use are reported.
*
- * NOTE: THE FOLLOWING (nr_flags == 0) IS DEPRECATED:
- * If nr_flags == 0, NETMAP_HW_RING and NETMAP_SW_RING control
- * the binding as follows:
- * 0 (default) binds all physical rings
- * NETMAP_HW_RING | ring number binds a single ring pair
- * NETMAP_SW_RING binds only the host tx/rx rings
+ * nr_mode (in)
+ * Indicate what set of rings must be bound to the netmap
+ * device (e.g. all NIC rings, host rings only, NIC and
+ * host rings, ...). Values are in NR_REG_*.
*
- * NETMAP_NO_TX_POLL can be OR-ed to make select()/poll() push
- * packets on tx rings only if POLLOUT is set.
- * The default is to push any pending packet.
+ * nr_ringid (in)
+ * If nr_mode == NR_REG_ONE_NIC (only a single couple of TX/RX
+ * rings), indicate which NIC TX and/or RX ring is to be bound
+ * (0..nr_*x_rings-1).
*
- * NETMAP_DO_RX_POLL can be OR-ed to make select()/poll() release
- * packets on rx rings also when POLLIN is NOT set.
- * The default is to touch the rx ring only with POLLIN.
- * Note that this is the opposite of TX because it
- * reflects the common usage.
+ * nr_flags (in)
+ * Indicate special options for how to open the port.
*
- * NOTE: NETMAP_PRIV_MEM IS DEPRECATED, use nr_arg2 instead.
- * NETMAP_PRIV_MEM is set on return for ports that do not use
- * the global memory allocator.
- * This information is not significant and applications
- * should look at the region id in nr_arg2
+ * NR_NO_TX_POLL can be OR-ed to make select()/poll() push
+ * packets on tx rings only if POLLOUT is set.
+ * The default is to push any pending packet.
*
- * nr_flags is the recommended mode to indicate which rings should
- * be bound to a file descriptor. Values are NR_REG_*
+ * NR_DO_RX_POLL can be OR-ed to make select()/poll() release
+ * packets on rx rings also when POLLIN is NOT set.
+ * The default is to touch the rx ring only with POLLIN.
+ * Note that this is the opposite of TX because it
+ * reflects the common usage.
*
- * nr_arg1 (in) The number of extra rings to be reserved.
- * Especially when allocating a VALE port the system only
- * allocates the amount of memory needed for the port.
- * If more shared memory rings are desired (e.g. for pipes),
- * the first invocation for the same basename/allocator
- * should specify a suitable number. Memory cannot be
- * extended after the first allocation without closing
- * all ports on the same region.
+ * Other options are NR_MONITOR_TX, NR_MONITOR_RX, NR_ZCOPY_MON,
+ * NR_EXCLUSIVE, NR_RX_RINGS_ONLY, NR_TX_RINGS_ONLY and
+ * NR_ACCEPT_VNET_HDR.
*
- * nr_arg2 (in/out) The identity of the memory region used.
+ * nr_mem_id (in/out)
+ * The identity of the memory region used.
* On input, 0 means the system decides autonomously,
* other values may try to select a specific region.
* On return the actual value is reported.
@@ -455,101 +456,92 @@ struct netmap_if {
* by all interfaces. Other values are private regions.
* If two ports the same region zero-copy is possible.
*
- * nr_arg3 (in/out) number of extra buffers to be allocated.
- *
- *
- *
- * nr_cmd (in) if non-zero indicates a special command:
- * NETMAP_BDG_ATTACH and nr_name = vale*:ifname
- * attaches the NIC to the switch; nr_ringid specifies
- * which rings to use. Used by vale-ctl -a ...
- * nr_arg1 = NETMAP_BDG_HOST also attaches the host port
- * as in vale-ctl -h ...
- *
- * NETMAP_BDG_DETACH and nr_name = vale*:ifname
- * disconnects a previously attached NIC.
- * Used by vale-ctl -d ...
- *
- * NETMAP_BDG_LIST
- * list the configuration of VALE switches.
- *
- * NETMAP_BDG_VNET_HDR
- * Set the virtio-net header length used by the client
- * of a VALE switch port.
- *
- * NETMAP_BDG_NEWIF
- * create a persistent VALE port with name nr_name.
- * Used by vale-ctl -n ...
- *
- * NETMAP_BDG_DELIF
- * delete a persistent VALE port. Used by vale-ctl -d ...
- *
- * nr_arg1, nr_arg2, nr_arg3 (in/out) command specific
- *
+ * nr_extra_bufs (in/out)
+ * Number of extra buffers to be allocated.
*
+ * The other NETMAP_REQ_* commands are described below.
*
*/
+/* maximum size of a request, including all options */
+#define NETMAP_REQ_MAXSIZE 4096
+
+/* Header common to all request options. */
+struct nmreq_option {
+ /* Pointer ot the next option. */
+ uint64_t nro_next;
+ /* Option type. */
+ uint32_t nro_reqtype;
+ /* (out) status of the option:
+ * 0: recognized and processed
+ * !=0: errno value
+ */
+ uint32_t nro_status;
+};
+
+/* Header common to all requests. Do not reorder these fields, as we need
+ * the second one (nr_reqtype) to know how much to copy from/to userspace. */
+struct nmreq_header {
+ uint16_t nr_version; /* API version */
+ uint16_t nr_reqtype; /* nmreq type (NETMAP_REQ_*) */
+ uint32_t nr_reserved; /* must be zero */
+#define NETMAP_REQ_IFNAMSIZ 64
+ char nr_name[NETMAP_REQ_IFNAMSIZ]; /* port name */
+ uint64_t nr_options; /* command-specific options */
+ uint64_t nr_body; /* ptr to nmreq_xyz struct */
+};
+
+enum {
+ /* Register a netmap port with the device. */
+ NETMAP_REQ_REGISTER = 1,
+ /* Get information from a netmap port. */
+ NETMAP_REQ_PORT_INFO_GET,
+ /* Attach a netmap port to a VALE switch. */
+ NETMAP_REQ_VALE_ATTACH,
+ /* Detach a netmap port from a VALE switch. */
+ NETMAP_REQ_VALE_DETACH,
+ /* List the ports attached to a VALE switch. */
+ NETMAP_REQ_VALE_LIST,
+ /* Set the port header length (was virtio-net header length). */
+ NETMAP_REQ_PORT_HDR_SET,
+ /* Get the port header length (was virtio-net header length). */
+ NETMAP_REQ_PORT_HDR_GET,
+ /* Create a new persistent VALE port. */
+ NETMAP_REQ_VALE_NEWIF,
+ /* Delete a persistent VALE port. */
+ NETMAP_REQ_VALE_DELIF,
+ /* Enable polling kernel thread(s) on an attached VALE port. */
+ NETMAP_REQ_VALE_POLLING_ENABLE,
+ /* Disable polling kernel thread(s) on an attached VALE port. */
+ NETMAP_REQ_VALE_POLLING_DISABLE,
+ /* Get info about the pools of a memory allocator. */
+ NETMAP_REQ_POOLS_INFO_GET,
+};
+
+enum {
+ /* On NETMAP_REQ_REGISTER, ask netmap to use memory allocated
+ * from user-space allocated memory pools (e.g. hugepages). */
+ NETMAP_REQ_OPT_EXTMEM = 1,
+};
/*
- * struct nmreq overlays a struct ifreq (just the name)
+ * nr_reqtype: NETMAP_REQ_REGISTER
+ * Bind (register) a netmap port to this control device.
*/
-struct nmreq {
- char nr_name[IFNAMSIZ];
- uint32_t nr_version; /* API version */
- uint32_t nr_offset; /* nifp offset in the shared region */
- uint32_t nr_memsize; /* size of the shared region */
+struct nmreq_register {
+ uint64_t nr_offset; /* nifp offset in the shared region */
+ uint64_t nr_memsize; /* size of the shared region */
uint32_t nr_tx_slots; /* slots in tx rings */
uint32_t nr_rx_slots; /* slots in rx rings */
uint16_t nr_tx_rings; /* number of tx rings */
uint16_t nr_rx_rings; /* number of rx rings */
+ uint16_t nr_mem_id; /* id of the memory allocator */
uint16_t nr_ringid; /* ring(s) we care about */
-#define NETMAP_HW_RING 0x4000 /* single NIC ring pair */
-#define NETMAP_SW_RING 0x2000 /* only host ring pair */
-
-#define NETMAP_RING_MASK 0x0fff /* the ring number */
-
-#define NETMAP_NO_TX_POLL 0x1000 /* no automatic txsync on poll */
-
-#define NETMAP_DO_RX_POLL 0x8000 /* DO automatic rxsync on poll */
-
- uint16_t nr_cmd;
-#define NETMAP_BDG_ATTACH 1 /* attach the NIC */
-#define NETMAP_BDG_DETACH 2 /* detach the NIC */
-#define NETMAP_BDG_REGOPS 3 /* register bridge callbacks */
-#define NETMAP_BDG_LIST 4 /* get bridge's info */
-#define NETMAP_BDG_VNET_HDR 5 /* set the port virtio-net-hdr length */
-#define NETMAP_BDG_OFFSET NETMAP_BDG_VNET_HDR /* deprecated alias */
-#define NETMAP_BDG_NEWIF 6 /* create a virtual port */
-#define NETMAP_BDG_DELIF 7 /* destroy a virtual port */
-#define NETMAP_PT_HOST_CREATE 8 /* create ptnetmap kthreads */
-#define NETMAP_PT_HOST_DELETE 9 /* delete ptnetmap kthreads */
-#define NETMAP_BDG_POLLING_ON 10 /* delete polling kthread */
-#define NETMAP_BDG_POLLING_OFF 11 /* delete polling kthread */
-#define NETMAP_VNET_HDR_GET 12 /* get the port virtio-net-hdr length */
-#define NETMAP_POOLS_INFO_GET 13 /* get memory allocator pools info */
-#define NETMAP_POOLS_CREATE 14 /* create a new memory allocator */
- uint16_t nr_arg1; /* reserve extra rings in NIOCREGIF */
-#define NETMAP_BDG_HOST 1 /* attach the host stack on ATTACH */
+ uint32_t nr_mode; /* specify NR_REG_* modes */
- uint16_t nr_arg2;
- uint32_t nr_arg3; /* req. extra buffers in NIOCREGIF */
- uint32_t nr_flags;
- /* various modes, extends nr_ringid */
- uint32_t spare2[1];
-};
-
-#define NR_REG_MASK 0xf /* values for nr_flags */
-enum { NR_REG_DEFAULT = 0, /* backward compat, should not be used. */
- NR_REG_ALL_NIC = 1,
- NR_REG_SW = 2,
- NR_REG_NIC_SW = 3,
- NR_REG_ONE_NIC = 4,
- NR_REG_PIPE_MASTER = 5,
- NR_REG_PIPE_SLAVE = 6,
-};
-/* monitor uses the NR_REG to select the rings to monitor */
+ uint64_t nr_flags; /* additional flags (see below) */
+/* monitors use nr_ringid and nr_mode to select the rings to monitor */
#define NR_MONITOR_TX 0x100
#define NR_MONITOR_RX 0x200
#define NR_ZCOPY_MON 0x400
@@ -566,87 +558,148 @@ enum { NR_REG_DEFAULT = 0, /* backward compat, should not be used. */
* to use those headers. If the flag is set, the application can use the
* NETMAP_VNET_HDR_GET command to figure out the header length. */
#define NR_ACCEPT_VNET_HDR 0x8000
+/* The following two have the same meaning of NETMAP_NO_TX_POLL and
+ * NETMAP_DO_RX_POLL. */
+#define NR_DO_RX_POLL 0x10000
+#define NR_NO_TX_POLL 0x20000
-#define NM_BDG_NAME "vale" /* prefix for bridge port name */
-
-#ifdef _WIN32
-/*
- * Windows does not have _IOWR(). _IO(), _IOW() and _IOR() are defined
- * in ws2def.h but not sure if they are in the form we need.
- * We therefore redefine them in a convenient way to use for DeviceIoControl
- * signatures.
- */
-#undef _IO // ws2def.h
-#define _WIN_NM_IOCTL_TYPE 40000
-#define _IO(_c, _n) CTL_CODE(_WIN_NM_IOCTL_TYPE, ((_n) + 0x800) , \
- METHOD_BUFFERED, FILE_ANY_ACCESS )
-#define _IO_direct(_c, _n) CTL_CODE(_WIN_NM_IOCTL_TYPE, ((_n) + 0x800) , \
- METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
+ uint32_t nr_extra_bufs; /* number of requested extra buffers */
+};
-#define _IOWR(_c, _n, _s) _IO(_c, _n)
+/* Valid values for nmreq_register.nr_mode (see above). */
+enum { NR_REG_DEFAULT = 0, /* backward compat, should not be used. */
+ NR_REG_ALL_NIC = 1,
+ NR_REG_SW = 2,
+ NR_REG_NIC_SW = 3,
+ NR_REG_ONE_NIC = 4,
+ NR_REG_PIPE_MASTER = 5, /* deprecated, use "x{y" port name syntax */
+ NR_REG_PIPE_SLAVE = 6, /* deprecated, use "x}y" port name syntax */
+};
-/* We havesome internal sysctl in addition to the externally visible ones */
-#define NETMAP_MMAP _IO_direct('i', 160) // note METHOD_OUT_DIRECT
-#define NETMAP_POLL _IO('i', 162)
+/* A single ioctl number is shared by all the new API command.
+ * Demultiplexing is done using the nr_hdr.nr_reqtype field.
+ * FreeBSD uses the size value embedded in the _IOWR to determine
+ * how much to copy in/out, so we define the ioctl() command
+ * specifying only nmreq_header, and copyin/copyout the rest. */
+#define NIOCCTRL _IOWR('i', 151, struct nmreq_header)
-/* and also two setsockopt for sysctl emulation */
-#define NETMAP_SETSOCKOPT _IO('i', 140)
-#define NETMAP_GETSOCKOPT _IO('i', 141)
+/* The ioctl commands to sync TX/RX netmap rings.
+ * NIOCTXSYNC, NIOCRXSYNC synchronize tx or rx queues,
+ * whose identity is set in NIOCREGIF through nr_ringid.
+ * These are non blocking and take no argument. */
+#define NIOCTXSYNC _IO('i', 148) /* sync tx queues */
+#define NIOCRXSYNC _IO('i', 149) /* sync rx queues */
+/*
+ * nr_reqtype: NETMAP_REQ_PORT_INFO_GET
+ * Get information about a netmap port, including number of rings.
+ * slots per ring, id of the memory allocator, etc.
+ */
+struct nmreq_port_info_get {
+ uint64_t nr_offset; /* nifp offset in the shared region */
+ uint64_t nr_memsize; /* size of the shared region */
+ uint32_t nr_tx_slots; /* slots in tx rings */
+ uint32_t nr_rx_slots; /* slots in rx rings */
+ uint16_t nr_tx_rings; /* number of tx rings */
+ uint16_t nr_rx_rings; /* number of rx rings */
+ uint16_t nr_mem_id; /* id of the memory allocator */
+};
-//These linknames are for the Netmap Core Driver
-#define NETMAP_NT_DEVICE_NAME L"\\Device\\NETMAP"
-#define NETMAP_DOS_DEVICE_NAME L"\\DosDevices\\netmap"
+#define NM_BDG_NAME "vale" /* prefix for bridge port name */
-//Definition of a structure used to pass a virtual address within an IOCTL
-typedef struct _MEMORY_ENTRY {
- PVOID pUsermodeVirtualAddress;
-} MEMORY_ENTRY, *PMEMORY_ENTRY;
+/*
+ * nr_reqtype: NETMAP_REQ_VALE_ATTACH
+ * Attach a netmap port to a VALE switch. Both the name of the netmap
+ * port and the VALE switch are specified through the nr_name argument.
+ * The attach operation could need to register a port, so at least
+ * the same arguments are available.
+ * port_index will contain the index where the port has been attached.
+ */
+struct nmreq_vale_attach {
+ struct nmreq_register reg;
+ uint32_t port_index;
+};
-typedef struct _POLL_REQUEST_DATA {
- int events;
- int timeout;
- int revents;
-} POLL_REQUEST_DATA;
+/*
+ * nr_reqtype: NETMAP_REQ_VALE_DETACH
+ * Detach a netmap port from a VALE switch. Both the name of the netmap
+ * port and the VALE switch are specified through the nr_name argument.
+ * port_index will contain the index where the port was attached.
+ */
+struct nmreq_vale_detach {
+ uint32_t port_index;
+};
-#endif /* _WIN32 */
+/*
+ * nr_reqtype: NETMAP_REQ_VALE_LIST
+ * List the ports of a VALE switch.
+ */
+struct nmreq_vale_list {
+ /* Name of the VALE port (valeXXX:YYY) or empty. */
+ uint16_t nr_bridge_idx;
+ uint32_t nr_port_idx;
+};
/*
- * FreeBSD uses the size value embedded in the _IOWR to determine
- * how much to copy in/out. So we need it to match the actual
- * data structure we pass. We put some spares in the structure
- * to ease compatibility with other versions
+ * nr_reqtype: NETMAP_REQ_PORT_HDR_SET or NETMAP_REQ_PORT_HDR_GET
+ * Set the port header length.
*/
-#define NIOCGINFO _IOWR('i', 145, struct nmreq) /* return IF info */
-#define NIOCREGIF _IOWR('i', 146, struct nmreq) /* interface register */
-#define NIOCTXSYNC _IO('i', 148) /* sync tx queues */
-#define NIOCRXSYNC _IO('i', 149) /* sync rx queues */
-#define NIOCCONFIG _IOWR('i',150, struct nm_ifreq) /* for ext. modules */
-#endif /* !NIOCREGIF */
+struct nmreq_port_hdr {
+ uint32_t nr_hdr_len;
+};
+/*
+ * nr_reqtype: NETMAP_REQ_VALE_NEWIF
+ * Create a new persistent VALE port.
+ */
+struct nmreq_vale_newif {
+ uint32_t nr_tx_slots; /* slots in tx rings */
+ uint32_t nr_rx_slots; /* slots in rx rings */
+ uint16_t nr_tx_rings; /* number of tx rings */
+ uint16_t nr_rx_rings; /* number of rx rings */
+ uint16_t nr_mem_id; /* id of the memory allocator */
+};
/*
- * Helper functions for kernel and userspace
+ * nr_reqtype: NETMAP_REQ_VALE_POLLING_ENABLE or NETMAP_REQ_VALE_POLLING_DISABLE
+ * Enable or disable polling kthreads on a VALE port.
*/
+struct nmreq_vale_polling {
+ uint32_t nr_mode;
+#define NETMAP_POLLING_MODE_SINGLE_CPU 1
+#define NETMAP_POLLING_MODE_MULTI_CPU 2
+ uint32_t nr_first_cpu_id;
+ uint32_t nr_num_polling_cpus;
+};
/*
- * check if space is available in the ring.
+ * nr_reqtype: NETMAP_REQ_POOLS_INFO_GET
+ * Get info about the pools of the memory allocator of the port bound
+ * to a given netmap control device (used i.e. by a ptnetmap-enabled
+ * hypervisor). The nr_hdr.nr_name field is ignored.
*/
-static inline int
-nm_ring_empty(struct netmap_ring *ring)
-{
- return (ring->cur == ring->tail);
-}
+struct nmreq_pools_info {
+ uint64_t nr_memsize;
+ uint16_t nr_mem_id;
+ uint64_t nr_if_pool_offset;
+ uint32_t nr_if_pool_objtotal;
+ uint32_t nr_if_pool_objsize;
+ uint64_t nr_ring_pool_offset;
+ uint32_t nr_ring_pool_objtotal;
+ uint32_t nr_ring_pool_objsize;
+ uint64_t nr_buf_pool_offset;
+ uint32_t nr_buf_pool_objtotal;
+ uint32_t nr_buf_pool_objsize;
+};
/*
- * Opaque structure that is passed to an external kernel
- * module via ioctl(fd, NIOCCONFIG, req) for a user-owned
- * bridge port (at this point ephemeral VALE interface).
+ * data for NETMAP_REQ_OPT_* options
*/
-#define NM_IFRDATA_LEN 256
-struct nm_ifreq {
- char nifr_name[IFNAMSIZ];
- char data[NM_IFRDATA_LEN];
+
+struct nmreq_opt_extmem {
+ struct nmreq_option nro_opt; /* common header */
+ uint64_t nro_usrptr; /* (in) ptr to usr memory */
+ struct nmreq_pools_info nro_info; /* (in/out) */
};
#endif /* _NET_NETMAP_H_ */
diff --git a/sys/net/netmap_legacy.h b/sys/net/netmap_legacy.h
new file mode 100644
index 000000000000..c7b0dffde173
--- /dev/null
+++ b/sys/net/netmap_legacy.h
@@ -0,0 +1,264 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (C) 2011-2014 Matteo Landi, Luigi Rizzo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``S IS''AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NET_NETMAP_LEGACY_H_
+#define _NET_NETMAP_LEGACY_H_
+
+/*
+ * $FreeBSD$
+ *
+ * ioctl names and related fields
+ *
+ * NIOCTXSYNC, NIOCRXSYNC synchronize tx or rx queues,
+ * whose identity is set in NIOCREGIF through nr_ringid.
+ * These are non blocking and take no argument.
+ *
+ * NIOCGINFO takes a struct ifreq, the interface name is the input,
+ * the outputs are number of queues and number of descriptor
+ * for each queue (useful to set number of threads etc.).
+ * The info returned is only advisory and may change before
+ * the interface is bound to a file descriptor.
+ *
+ * NIOCREGIF takes an interface name within a struct nmre,
+ * and activates netmap mode on the interface (if possible).
+ *
+ * The argument to NIOCGINFO/NIOCREGIF overlays struct ifreq so we
+ * can pass it down to other NIC-related ioctls.
+ *
+ * The actual argument (struct nmreq) has a number of options to request
+ * different functions.
+ * The following are used in NIOCREGIF when nr_cmd == 0:
+ *
+ * nr_name (in)
+ * The name of the port (em0, valeXXX:YYY, etc.)
+ * limited to IFNAMSIZ for backward compatibility.
+ *
+ * nr_version (in/out)
+ * Must match NETMAP_API as used in the kernel, error otherwise.
+ * Always returns the desired value on output.
+ *
+ * nr_tx_slots, nr_tx_slots, nr_tx_rings, nr_rx_rings (in/out)
+ * On input, non-zero values may be used to reconfigure the port
+ * according to the requested values, but this is not guaranteed.
+ * On output the actual values in use are reported.
+ *
+ * nr_ringid (in)
+ * Indicates how rings should be bound to the file descriptors.
+ * If nr_flags != 0, then the low bits (in NETMAP_RING_MASK)
+ * are used to indicate the ring number, and nr_flags specifies
+ * the actual rings to bind. NETMAP_NO_TX_POLL is unaffected.
+ *
+ * NOTE: THE FOLLOWING (nr_flags == 0) IS DEPRECATED:
+ * If nr_flags == 0, NETMAP_HW_RING and NETMAP_SW_RING control
+ * the binding as follows:
+ * 0 (default) binds all physical rings
+ * NETMAP_HW_RING | ring number binds a single ring pair
+ * NETMAP_SW_RING binds only the host tx/rx rings
+ *
+ * NETMAP_NO_TX_POLL can be OR-ed to make select()/poll() push
+ * packets on tx rings only if POLLOUT is set.
+ * The default is to push any pending packet.
+ *
+ * NETMAP_DO_RX_POLL can be OR-ed to make select()/poll() release
+ * packets on rx rings also when POLLIN is NOT set.
+ * The default is to touch the rx ring only with POLLIN.
+ * Note that this is the opposite of TX because it
+ * reflects the common usage.
+ *
+ * NOTE: NETMAP_PRIV_MEM IS DEPRECATED, use nr_arg2 instead.
+ * NETMAP_PRIV_MEM is set on return for ports that do not use
+ * the global memory allocator.
+ * This information is not significant and applications
+ * should look at the region id in nr_arg2
+ *
+ * nr_flags is the recommended mode to indicate which rings should
+ * be bound to a file descriptor. Values are NR_REG_*
+ *
+ * nr_arg1 (in) The number of extra rings to be reserved.
+ * Especially when allocating a VALE port the system only
+ * allocates the amount of memory needed for the port.
+ * If more shared memory rings are desired (e.g. for pipes),
+ * the first invocation for the same basename/allocator
+ * should specify a suitable number. Memory cannot be
+ * extended after the first allocation without closing
+ * all ports on the same region.
+ *
+ * nr_arg2 (in/out) The identity of the memory region used.
+ * On input, 0 means the system decides autonomously,
+ * other values may try to select a specific region.
+ * On return the actual value is reported.
+ * Region '1' is the global allocator, normally shared
+ * by all interfaces. Other values are private regions.
+ * If two ports the same region zero-copy is possible.
+ *
+ * nr_arg3 (in/out) number of extra buffers to be allocated.
+ *
+ *
+ *
+ * nr_cmd (in) if non-zero indicates a special command:
+ * NETMAP_BDG_ATTACH and nr_name = vale*:ifname
+ * attaches the NIC to the switch; nr_ringid specifies
+ * which rings to use. Used by vale-ctl -a ...
+ * nr_arg1 = NETMAP_BDG_HOST also attaches the host port
+ * as in vale-ctl -h ...
+ *
+ * NETMAP_BDG_DETACH and nr_name = vale*:ifname
+ * disconnects a previously attached NIC.
+ * Used by vale-ctl -d ...
+ *
+ * NETMAP_BDG_LIST
+ * list the configuration of VALE switches.
+ *
+ * NETMAP_BDG_VNET_HDR
+ * Set the virtio-net header length used by the client
+ * of a VALE switch port.
+ *
+ * NETMAP_BDG_NEWIF
+ * create a persistent VALE port with name nr_name.
+ * Used by vale-ctl -n ...
+ *
+ * NETMAP_BDG_DELIF
+ * delete a persistent VALE port. Used by vale-ctl -d ...
+ *
+ * nr_arg1, nr_arg2, nr_arg3 (in/out) command specific
+ *
+ *
+ *
+ */
+
+
+/*
+ * struct nmreq overlays a struct ifreq (just the name)
+ */
+struct nmreq {
+ char nr_name[IFNAMSIZ];
+ uint32_t nr_version; /* API version */
+ uint32_t nr_offset; /* nifp offset in the shared region */
+ uint32_t nr_memsize; /* size of the shared region */
+ uint32_t nr_tx_slots; /* slots in tx rings */
+ uint32_t nr_rx_slots; /* slots in rx rings */
+ uint16_t nr_tx_rings; /* number of tx rings */
+ uint16_t nr_rx_rings; /* number of rx rings */
+
+ uint16_t nr_ringid; /* ring(s) we care about */
+#define NETMAP_HW_RING 0x4000 /* single NIC ring pair */
+#define NETMAP_SW_RING 0x2000 /* only host ring pair */
+
+#define NETMAP_RING_MASK 0x0fff /* the ring number */
+
+#define NETMAP_NO_TX_POLL 0x1000 /* no automatic txsync on poll */
+
+#define NETMAP_DO_RX_POLL 0x8000 /* DO automatic rxsync on poll */
+
+ uint16_t nr_cmd;
+#define NETMAP_BDG_ATTACH 1 /* attach the NIC */
+#define NETMAP_BDG_DETACH 2 /* detach the NIC */
+#define NETMAP_BDG_REGOPS 3 /* register bridge callbacks */
+#define NETMAP_BDG_LIST 4 /* get bridge's info */
+#define NETMAP_BDG_VNET_HDR 5 /* set the port virtio-net-hdr length */
+#define NETMAP_BDG_NEWIF 6 /* create a virtual port */
+#define NETMAP_BDG_DELIF 7 /* destroy a virtual port */
+#define NETMAP_PT_HOST_CREATE 8 /* create ptnetmap kthreads */
+#define NETMAP_PT_HOST_DELETE 9 /* delete ptnetmap kthreads */
+#define NETMAP_BDG_POLLING_ON 10 /* delete polling kthread */
+#define NETMAP_BDG_POLLING_OFF 11 /* delete polling kthread */
+#define NETMAP_VNET_HDR_GET 12 /* get the port virtio-net-hdr length */
+ uint16_t nr_arg1; /* reserve extra rings in NIOCREGIF */
+#define NETMAP_BDG_HOST 1 /* nr_arg1 value for NETMAP_BDG_ATTACH */
+
+ uint16_t nr_arg2; /* id of the memory allocator */
+ uint32_t nr_arg3; /* req. extra buffers in NIOCREGIF */
+ uint32_t nr_flags; /* specify NR_REG_* mode and other flags */
+#define NR_REG_MASK 0xf /* to extract NR_REG_* mode from nr_flags */
+ /* various modes, extends nr_ringid */
+ uint32_t spare2[1];
+};
+
+#ifdef _WIN32
+/*
+ * Windows does not have _IOWR(). _IO(), _IOW() and _IOR() are defined
+ * in ws2def.h but not sure if they are in the form we need.
+ * We therefore redefine them in a convenient way to use for DeviceIoControl
+ * signatures.
+ */
+#undef _IO // ws2def.h
+#define _WIN_NM_IOCTL_TYPE 40000
+#define _IO(_c, _n) CTL_CODE(_WIN_NM_IOCTL_TYPE, ((_n) + 0x800) , \
+ METHOD_BUFFERED, FILE_ANY_ACCESS )
+#define _IO_direct(_c, _n) CTL_CODE(_WIN_NM_IOCTL_TYPE, ((_n) + 0x800) , \
+ METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
+
+#define _IOWR(_c, _n, _s) _IO(_c, _n)
+
+/* We havesome internal sysctl in addition to the externally visible ones */
+#define NETMAP_MMAP _IO_direct('i', 160) // note METHOD_OUT_DIRECT
+#define NETMAP_POLL _IO('i', 162)
+
+/* and also two setsockopt for sysctl emulation */
+#define NETMAP_SETSOCKOPT _IO('i', 140)
+#define NETMAP_GETSOCKOPT _IO('i', 141)
+
+
+/* These linknames are for the Netmap Core Driver */
+#define NETMAP_NT_DEVICE_NAME L"\\Device\\NETMAP"
+#define NETMAP_DOS_DEVICE_NAME L"\\DosDevices\\netmap"
+
+/* Definition of a structure used to pass a virtual address within an IOCTL */
+typedef struct _MEMORY_ENTRY {
+ PVOID pUsermodeVirtualAddress;
+} MEMORY_ENTRY, *PMEMORY_ENTRY;
+
+typedef struct _POLL_REQUEST_DATA {
+ int events;
+ int timeout;
+ int revents;
+} POLL_REQUEST_DATA;
+#endif /* _WIN32 */
+
+/*
+ * Opaque structure that is passed to an external kernel
+ * module via ioctl(fd, NIOCCONFIG, req) for a user-owned
+ * bridge port (at this point ephemeral VALE interface).
+ */
+#define NM_IFRDATA_LEN 256
+struct nm_ifreq {
+ char nifr_name[IFNAMSIZ];
+ char data[NM_IFRDATA_LEN];
+};
+
+/*
+ * FreeBSD uses the size value embedded in the _IOWR to determine
+ * how much to copy in/out. So we need it to match the actual
+ * data structure we pass. We put some spares in the structure
+ * to ease compatibility with other versions
+ */
+#define NIOCGINFO _IOWR('i', 145, struct nmreq) /* return IF info */
+#define NIOCREGIF _IOWR('i', 146, struct nmreq) /* interface register */
+#define NIOCCONFIG _IOWR('i',150, struct nm_ifreq) /* for ext. modules */
+
+#endif /* _NET_NETMAP_LEGACY_H_ */
diff --git a/sys/net/netmap_user.h b/sys/net/netmap_user.h
index 2c8d91a63b63..a314ca02b81c 100644
--- a/sys/net/netmap_user.h
+++ b/sys/net/netmap_user.h
@@ -100,7 +100,6 @@
#endif /* likely and unlikely */
#include <net/netmap.h>
-#include <net/netmap_virt.h> /* nmreq_pointer_get() */
/* helper macro */
#define _NETMAP_OFFSET(type, ptr, offset) \
@@ -115,7 +114,7 @@
nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] )
#define NETMAP_BUF(ring, index) \
- ((char *)(ring) + (ring)->buf_ofs + ((long)(index)*(ring)->nr_buf_size))
+ ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size))
#define NETMAP_BUF_IDX(ring, buf) \
( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \
@@ -225,7 +224,7 @@ struct nm_desc {
struct nm_desc *self; /* point to self if netmap. */
int fd;
void *mem;
- uint64_t memsize;
+ uint32_t memsize;
int done_mmap; /* set if mem is the result of mmap */
struct netmap_if * const nifp;
uint16_t first_tx_ring, last_tx_ring, cur_tx_ring;
@@ -351,7 +350,6 @@ enum {
NM_OPEN_ARG2 = 0x200000,
NM_OPEN_ARG3 = 0x400000,
NM_OPEN_RING_CFG = 0x800000, /* tx|rx rings|slots */
- NM_OPEN_EXTMEM = 0x1000000,
};
@@ -613,28 +611,9 @@ nm_is_identifier(const char *s, const char *e)
return 1;
}
-static void
-nm_init_offsets(struct nm_desc *d)
-{
- struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
- struct netmap_ring *r = NETMAP_RXRING(nifp, d->first_rx_ring);
- if ((void *)r == (void *)nifp) {
- /* the descriptor is open for TX only */
- r = NETMAP_TXRING(nifp, d->first_tx_ring);
- }
-
- *(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
- *(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
- *(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
- *(void **)(uintptr_t)&d->buf_end =
- (char *)d->mem + d->memsize;
-}
-
#define MAXERRMSG 80
-#define NM_PARSE_OK 0
-#define NM_PARSE_MEMID 1
static int
-nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
+nm_parse(const char *ifname, struct nm_desc *d, char *err)
{
int is_vale;
const char *port = NULL;
@@ -648,13 +627,6 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
errno = 0;
- if (strncmp(ifname, "netmap:", 7) &&
- strncmp(ifname, NM_BDG_NAME, strlen(NM_BDG_NAME))) {
- snprintf(errmsg, MAXERRMSG, "invalid port name: %s", ifname);
- errno = EINVAL;
- goto fail;
- }
-
is_vale = (ifname[0] == 'v');
if (is_vale) {
port = index(ifname, ':');
@@ -685,13 +657,12 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
}
namelen = port - ifname;
- if (namelen >= sizeof(d->nr_name)) {
+ if (namelen >= sizeof(d->req.nr_name)) {
snprintf(errmsg, MAXERRMSG, "name too long");
goto fail;
}
- memcpy(d->nr_name, ifname, namelen);
- d->nr_name[namelen] = '\0';
- D("name %s", d->nr_name);
+ memcpy(d->req.nr_name, ifname, namelen);
+ d->req.nr_name[namelen] = '\0';
p_state = P_START;
nr_flags = NR_REG_ALL_NIC; /* default for no suffix */
@@ -789,28 +760,21 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
p_state = P_FLAGSOK;
break;
case P_MEMID:
- if (!memid_allowed) {
+ if (nr_arg2 != 0) {
snprintf(errmsg, MAXERRMSG, "double setting of memid");
goto fail;
}
num = strtol(port, (char **)&port, 10);
if (num <= 0) {
- ND("non-numeric memid %s (out = %p)", port, out);
- if (out == NULL)
- goto fail;
- *out = (char *)port;
- while (*port)
- port++;
- } else {
- nr_arg2 = num;
- memid_allowed = 0;
- p_state = P_RNGSFXOK;
+ snprintf(errmsg, MAXERRMSG, "invalid memid %ld, must be >0", num);
+ goto fail;
}
+ nr_arg2 = num;
+ p_state = P_RNGSFXOK;
break;
}
}
- if (p_state != P_START && p_state != P_RNGSFXOK &&
- p_state != P_FLAGSOK && p_state != P_MEMID) {
+ if (p_state != P_START && p_state != P_RNGSFXOK && p_state != P_FLAGSOK) {
snprintf(errmsg, MAXERRMSG, "unexpected end of port name");
goto fail;
}
@@ -820,117 +784,28 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
(nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "",
(nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "");
- d->nr_flags |= nr_flags;
- d->nr_ringid |= nr_ringid;
- d->nr_arg2 = nr_arg2;
+ d->req.nr_flags |= nr_flags;
+ d->req.nr_ringid |= nr_ringid;
+ d->req.nr_arg2 = nr_arg2;
+
+ d->self = d;
- return (p_state == P_MEMID) ? NM_PARSE_MEMID : NM_PARSE_OK;
+ return 0;
fail:
if (!errno)
errno = EINVAL;
- if (out)
- *out = strdup(errmsg);
+ if (err)
+ strncpy(err, errmsg, MAXERRMSG);
return -1;
}
-static int
-nm_interp_memid(const char *memid, struct nmreq *req, char **err)
-{
- int fd = -1;
- char errmsg[MAXERRMSG] = "";
- struct nmreq greq;
- off_t mapsize;
- struct netmap_pools_info *pi;
-
- /* first, try to look for a netmap port with this name */
- fd = open("/dev/netmap", O_RDONLY);
- if (fd < 0) {
- snprintf(errmsg, MAXERRMSG, "cannot open /dev/netmap: %s", strerror(errno));
- goto fail;
- }
- memset(&greq, 0, sizeof(greq));
- if (nm_parse_one(memid, &greq, err, 0) == NM_PARSE_OK) {
- greq.nr_version = NETMAP_API;
- if (ioctl(fd, NIOCGINFO, &greq) < 0) {
- if (errno == ENOENT || errno == ENXIO)
- goto try_external;
- snprintf(errmsg, MAXERRMSG, "cannot getinfo for %s: %s", memid, strerror(errno));
- goto fail;
- }
- req->nr_arg2 = greq.nr_arg2;
- close(fd);
- return 0;
- }
-try_external:
- D("trying with external memory");
- close(fd);
- fd = open(memid, O_RDWR);
- if (fd < 0) {
- snprintf(errmsg, MAXERRMSG, "cannot open %s: %s", memid, strerror(errno));
- goto fail;
- }
- mapsize = lseek(fd, 0, SEEK_END);
- if (mapsize < 0) {
- snprintf(errmsg, MAXERRMSG, "failed to obtain filesize of %s: %s", memid, strerror(errno));
- goto fail;
- }
- pi = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (pi == MAP_FAILED) {
- snprintf(errmsg, MAXERRMSG, "cannot map %s: %s", memid, strerror(errno));
- goto fail;
- }
- req->nr_cmd = NETMAP_POOLS_CREATE;
- pi->memsize = mapsize;
- nmreq_pointer_put(req, pi);
- D("mapped %zu bytes at %p from file %s", mapsize, pi, memid);
- return 0;
-
-fail:
- D("%s", errmsg);
- close(fd);
- if (err && !*err)
- *err = strdup(errmsg);
- return errno;
-}
-
-static int
-nm_parse(const char *ifname, struct nm_desc *d, char *errmsg)
-{
- char *err;
- switch (nm_parse_one(ifname, &d->req, &err, 1)) {
- case NM_PARSE_OK:
- D("parse OK");
- break;
- case NM_PARSE_MEMID:
- D("memid: %s", err);
- errno = nm_interp_memid(err, &d->req, &err);
- D("errno = %d", errno);
- if (!errno)
- break;
- /* fallthrough */
- default:
- D("error");
- strncpy(errmsg, err, MAXERRMSG);
- errmsg[MAXERRMSG-1] = '\0';
- free(err);
- return -1;
- }
- D("parsed name: %s", d->req.nr_name);
- d->self = d;
- return 0;
-}
-
/*
* Try to open, return descriptor if successful, NULL otherwise.
* An invalid netmap name will return errno = 0;
* You can pass a pointer to a pre-filled nm_desc to add special
* parameters. Flags is used as follows
- * NM_OPEN_NO_MMAP use the memory from arg, only
+ * NM_OPEN_NO_MMAP use the memory from arg, only XXX avoid mmap
* if the nr_arg2 (memory block) matches.
- * Special case: if arg is NULL, skip the
- * mmap entirely (maybe because you are going
- * to do it by yourself, or you plan to call
- * nm_mmap() only later)
* NM_OPEN_ARG1 use req.nr_arg1 from arg
* NM_OPEN_ARG2 use req.nr_arg2 from arg
* NM_OPEN_RING_CFG user ring config from arg
@@ -943,7 +818,6 @@ nm_open(const char *ifname, const struct nmreq *req,
const struct nm_desc *parent = arg;
char errmsg[MAXERRMSG] = "";
uint32_t nr_reg;
- struct netmap_pools_info *pi = NULL;
if (strncmp(ifname, "netmap:", 7) &&
strncmp(ifname, NM_BDG_NAME, strlen(NM_BDG_NAME))) {
@@ -964,60 +838,12 @@ nm_open(const char *ifname, const struct nmreq *req,
goto fail;
}
- if (req) {
+ if (req)
d->req = *req;
- } else {
- d->req.nr_arg1 = 4;
- d->req.nr_arg2 = 0;
- d->req.nr_arg3 = 0;
- }
if (!(new_flags & NM_OPEN_IFNAME)) {
- char *err;
- switch (nm_parse_one(ifname, &d->req, &err, 1)) {
- case NM_PARSE_OK:
- break;
- case NM_PARSE_MEMID:
- if ((new_flags & NM_OPEN_NO_MMAP) &&
- IS_NETMAP_DESC(parent)) {
- /* ignore the memid setting, since we are
- * going to use the parent's one
- */
- break;
- }
- errno = nm_interp_memid(err, &d->req, &err);
- if (!errno)
- break;
- /* fallthrough */
- default:
- strncpy(errmsg, err, MAXERRMSG);
- errmsg[MAXERRMSG-1] = '\0';
- free(err);
+ if (nm_parse(ifname, d, errmsg) < 0)
goto fail;
- }
- d->self = d;
- }
-
- /* compatibility checks for POOL_SCREATE and NM_OPEN flags
- * the first check may be dropped once we have a larger nreq
- */
- if (d->req.nr_cmd == NETMAP_POOLS_CREATE) {
- if (IS_NETMAP_DESC(parent)) {
- if (new_flags & (NM_OPEN_ARG1 | NM_OPEN_ARG2 | NM_OPEN_ARG3)) {
- snprintf(errmsg, MAXERRMSG,
- "POOLS_CREATE is incompatibile "
- "with NM_OPEN_ARG? flags");
- errno = EINVAL;
- goto fail;
- }
- if (new_flags & NM_OPEN_NO_MMAP) {
- snprintf(errmsg, MAXERRMSG,
- "POOLS_CREATE is incompatible "
- "with NM_OPEN_NO_MMAP flag");
- errno = EINVAL;
- goto fail;
- }
- }
}
d->req.nr_version = NETMAP_API;
@@ -1025,26 +851,18 @@ nm_open(const char *ifname, const struct nmreq *req,
/* optionally import info from parent */
if (IS_NETMAP_DESC(parent) && new_flags) {
- if (new_flags & NM_OPEN_EXTMEM) {
- if (parent->req.nr_cmd == NETMAP_POOLS_CREATE) {
- d->req.nr_cmd = NETMAP_POOLS_CREATE;
- nmreq_pointer_put(&d->req, nmreq_pointer_get(&parent->req));
- D("Warning: not overriding arg[1-3] since external memory is being used");
- new_flags &= ~(NM_OPEN_ARG1 | NM_OPEN_ARG2 | NM_OPEN_ARG3);
- }
- }
- if (new_flags & NM_OPEN_ARG1) {
+ if (new_flags & NM_OPEN_ARG1)
D("overriding ARG1 %d", parent->req.nr_arg1);
- d->req.nr_arg1 = parent->req.nr_arg1;
- }
- if (new_flags & (NM_OPEN_ARG2 | NM_OPEN_NO_MMAP)) {
+ d->req.nr_arg1 = new_flags & NM_OPEN_ARG1 ?
+ parent->req.nr_arg1 : 4;
+ if (new_flags & NM_OPEN_ARG2) {
D("overriding ARG2 %d", parent->req.nr_arg2);
- d->req.nr_arg2 = parent->req.nr_arg2;
+ d->req.nr_arg2 = parent->req.nr_arg2;
}
- if (new_flags & NM_OPEN_ARG3) {
+ if (new_flags & NM_OPEN_ARG3)
D("overriding ARG3 %d", parent->req.nr_arg3);
- d->req.nr_arg3 = parent->req.nr_arg3;
- }
+ d->req.nr_arg3 = new_flags & NM_OPEN_ARG3 ?
+ parent->req.nr_arg3 : 0;
if (new_flags & NM_OPEN_RING_CFG) {
D("overriding RING_CFG");
d->req.nr_tx_slots = parent->req.nr_tx_slots;
@@ -1065,28 +883,11 @@ nm_open(const char *ifname, const struct nmreq *req,
/* add the *XPOLL flags */
d->req.nr_ringid |= new_flags & (NETMAP_NO_TX_POLL | NETMAP_DO_RX_POLL);
- if (d->req.nr_cmd == NETMAP_POOLS_CREATE) {
- pi = nmreq_pointer_get(&d->req);
- }
-
if (ioctl(d->fd, NIOCREGIF, &d->req)) {
snprintf(errmsg, MAXERRMSG, "NIOCREGIF failed: %s", strerror(errno));
goto fail;
}
- if (pi != NULL) {
- d->mem = pi;
- d->memsize = pi->memsize;
- nm_init_offsets(d);
- } else if ((!(new_flags & NM_OPEN_NO_MMAP) || parent)) {
- /* if parent is defined, do nm_mmap() even if NM_OPEN_NO_MMAP is set */
- errno = nm_mmap(d, parent);
- if (errno) {
- snprintf(errmsg, MAXERRMSG, "mmap failed: %s", strerror(errno));
- goto fail;
- }
- }
-
nr_reg = d->req.nr_flags & NR_REG_MASK;
if (nr_reg == NR_REG_SW) { /* host stack */
@@ -1111,6 +912,13 @@ nm_open(const char *ifname, const struct nmreq *req,
d->first_rx_ring = d->last_rx_ring = 0;
}
+ /* if parent is defined, do nm_mmap() even if NM_OPEN_NO_MMAP is set */
+ if ((!(new_flags & NM_OPEN_NO_MMAP) || parent) && nm_mmap(d, parent)) {
+ snprintf(errmsg, MAXERRMSG, "mmap failed: %s", strerror(errno));
+ goto fail;
+ }
+
+
#ifdef DEBUG_NETMAP_USER
{ /* debugging code */
int i;
@@ -1151,8 +959,7 @@ nm_close(struct nm_desc *d)
*/
static void *__xxzt[] __attribute__ ((unused)) =
{ (void *)nm_open, (void *)nm_inject,
- (void *)nm_dispatch, (void *)nm_nextpkt,
- (void *)nm_parse } ;
+ (void *)nm_dispatch, (void *)nm_nextpkt } ;
if (d == NULL || d->self != d)
return EINVAL;
@@ -1189,8 +996,21 @@ nm_mmap(struct nm_desc *d, const struct nm_desc *parent)
}
d->done_mmap = 1;
}
+ {
+ struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
+ struct netmap_ring *r = NETMAP_RXRING(nifp, d->first_rx_ring);
+ if ((void *)r == (void *)nifp) {
+ /* the descriptor is open for TX only */
+ r = NETMAP_TXRING(nifp, d->first_tx_ring);
+ }
+
+ *(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
+ *(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
+ *(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
+ *(void **)(uintptr_t)&d->buf_end =
+ (char *)d->mem + d->memsize;
+ }
- nm_init_offsets(d);
return 0;
fail:
diff --git a/sys/net/netmap_virt.h b/sys/net/netmap_virt.h
index 751ae539d982..1b8b26cc9fd3 100644
--- a/sys/net/netmap_virt.h
+++ b/sys/net/netmap_virt.h
@@ -110,27 +110,9 @@ struct ptnetmap_cfgentry_bhyve {
};
/*
- * Structure filled-in by the kernel when asked for allocator info
- * through NETMAP_POOLS_INFO_GET. Used by hypervisors supporting
- * ptnetmap.
- */
-struct netmap_pools_info {
- uint64_t memsize; /* same as nmr->nr_memsize */
- uint32_t memid; /* same as nmr->nr_arg2 */
- uint32_t if_pool_offset;
- uint32_t if_pool_objtotal;
- uint32_t if_pool_objsize;
- uint32_t ring_pool_offset;
- uint32_t ring_pool_objtotal;
- uint32_t ring_pool_objsize;
- uint32_t buf_pool_offset;
- uint32_t buf_pool_objtotal;
- uint32_t buf_pool_objsize;
-};
-
-/*
* Pass a pointer to a userspace buffer to be passed to kernelspace for write
- * or read. Used by NETMAP_PT_HOST_CREATE and NETMAP_POOLS_INFO_GET.
+ * or read. Used by NETMAP_PT_HOST_CREATE.
+ * XXX deprecated
*/
static inline void
nmreq_pointer_put(struct nmreq *nmr, void *userptr)
@@ -142,7 +124,7 @@ nmreq_pointer_put(struct nmreq *nmr, void *userptr)
static inline void *
nmreq_pointer_get(const struct nmreq *nmr)
{
- const uintptr_t * pp = (const uintptr_t *)&nmr->nr_arg1;
+ const uintptr_t *pp = (const uintptr_t *)&nmr->nr_arg1;
return (void *)*pp;
}