diff options
| author | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2018-04-12 07:20:50 +0000 |
|---|---|---|
| committer | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2018-04-12 07:20:50 +0000 |
| commit | 2ff91c175eca50b7d0d9da6b31eae4109c034137 (patch) | |
| tree | 15a4f8847a8cabd782f67326125c48fed4fdd27b /sys/net | |
| parent | 66def52613043a86172a2ebe6feab214258fa2fa (diff) | |
Notes
Diffstat (limited to 'sys/net')
| -rw-r--r-- | sys/net/iflib.c | 4 | ||||
| -rw-r--r-- | sys/net/netmap.h | 461 | ||||
| -rw-r--r-- | sys/net/netmap_legacy.h | 264 | ||||
| -rw-r--r-- | sys/net/netmap_user.h | 286 | ||||
| -rw-r--r-- | sys/net/netmap_virt.h | 24 |
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; } |
