* Re: [PATCH v12] net/tap: new TUN/TAP device PMD
From: Marc @ 2016-12-12 19:13 UTC (permalink / raw)
To: Keith Wiles; +Cc: dev
In-Reply-To: <20161212143838.37269-1-keith.wiles@intel.com>
Keith,
A bit late, but two very high level questions. Do you have performance
numbers compared to KNI? Did you consider using AF_PACKET PACKET_MMAP which
could potentially reduce the number of syscalls to 1 for RX and TX of a
burst?
Marc
On 12 December 2016 at 15:38, Keith Wiles <keith.wiles@intel.com> wrote:
> The PMD allows for DPDK and the host to communicate using a raw
> device interface on the host and in the DPDK application. The device
> created is a Tap device with a L2 packet header.
>
> v12- Fixup minor changes for driver_name and version number
> v11- Add the tap.rst to the nic/index.rst file
> v10- Change the string name used to allow for multiple devices.
> v9 - Fix up the docs to use correct syntax
> v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
> v7 - Reword the comment in common_base and fix the data->name issue
> v6 - fixed the checkpatch issues
> v5 - merge in changes from list review see related emails
> fixed many minor edits
> v4 - merge with latest driver changes
> v3 - fix includes by removing ifdef for other type besides Linux
> Fix the copyright notice in the Makefile
> v2 - merge all of the patches into one patch
> Fix a typo on naming the tap device
> Update the maintainers list
>
> Signed-off-by: Keith Wiles <keith.wiles@intel.com>
> ---
> MAINTAINERS | 5 +
> config/common_base | 9 +
> config/common_linuxapp | 1 +
> doc/guides/nics/index.rst | 1 +
> doc/guides/nics/tap.rst | 136 ++++++
> drivers/net/Makefile | 1 +
> drivers/net/tap/Makefile | 57 +++
> drivers/net/tap/rte_eth_tap.c | 765
> ++++++++++++++++++++++++++++++++
> drivers/net/tap/rte_pmd_tap_version.map | 4 +
> mk/rte.app.mk | 1 +
> 10 files changed, 980 insertions(+)
> create mode 100644 doc/guides/nics/tap.rst
> create mode 100644 drivers/net/tap/Makefile
> create mode 100644 drivers/net/tap/rte_eth_tap.c
> create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 26d9590..842fb6d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -398,6 +398,11 @@ F: doc/guides/nics/pcap_ring.rst
> F: app/test/test_pmd_ring.c
> F: app/test/test_pmd_ring_perf.c
>
> +Tap PMD
> +M: Keith Wiles <keith.wiles@intel.com>
> +F: drivers/net/tap
> +F: doc/guides/nics/tap.rst
> +
> Null Networking PMD
> M: Tetsuya Mukawa <mtetsuyah@gmail.com>
> F: drivers/net/null/
> diff --git a/config/common_base b/config/common_base
> index 652a839..eb51cdb 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> +
> +#
> +# Compile the TAP PMD
> +#
> +# The TAP PMD is currently only built for Linux and the
> +# option is enabled by default in common_linuxapp file,
> +# set to 'n' in the common_base file.
> +#
> +CONFIG_RTE_LIBRTE_PMD_TAP=n
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 2483dfa..782b503 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -44,3 +44,4 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
> CONFIG_RTE_LIBRTE_POWER=y
> CONFIG_RTE_VIRTIO_USER=y
> +CONFIG_RTE_LIBRTE_PMD_TAP=y
> diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
> index 92d56a5..af92529 100644
> --- a/doc/guides/nics/index.rst
> +++ b/doc/guides/nics/index.rst
> @@ -51,6 +51,7 @@ Network Interface Controller Drivers
> nfp
> qede
> szedata2
> + tap
> thunderx
> virtio
> vhost
> diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
> new file mode 100644
> index 0000000..622b9e7
> --- /dev/null
> +++ b/doc/guides/nics/tap.rst
> @@ -0,0 +1,136 @@
> +.. BSD LICENSE
> + Copyright(c) 2016 Intel Corporation. All rights reserved.
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * 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.
> + * Neither the name of Intel Corporation nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + "AS 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 COPYRIGHT
> + OWNER 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.
> +
> +Tun/Tap Poll Mode Driver
> +========================
> +
> +The ``rte_eth_tap.c`` PMD creates a device using TUN/TAP interfaces on the
> +local host. The PMD allows for DPDK and the host to communicate using a
> raw
> +device interface on the host and in the DPDK application.
> +
> +The device created is a TAP device, which sends/receives packet in a raw
> +format with a L2 header. The usage for a TAP PMD is for connectivity to
> the
> +local host using a TAP interface. When the TAP PMD is initialized it will
> +create a number of tap devices in the host accessed via ``ifconfig -a`` or
> +``ip`` command. The commands can be used to assign and query the virtual
> like
> +device.
> +
> +These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK
> +along with being able to be used as a network connection to the DPDK
> +application. The method enable one or more interfaces is to use the
> +``--vdev=net_tap`` option on the DPDK application command line. Each
> +``--vdev=net_tap`` option give will create an interface named dtap0,
> dtap1,
> +and so on.
> +
> +The interfaced name can be changed by adding the ``iface=foo0``, for
> example::
> +
> + --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
> +
> +Also the speed of the interface can be changed from 10G to whatever number
> +needed, but the interface does not enforce that speed, for example::
> +
> + --vdev=net_tap,iface=foo0,speed=25000
> +
> +After the DPDK application is started you can send and receive packets on
> the
> +interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
> +point of view you can use any host tool like tcpdump, Wireshark, ping,
> Pktgen
> +and others to communicate with the DPDK application. The DPDK application
> may
> +not understand network protocols like IPv4/6, UDP or TCP unless the
> +application has been written to understand these protocols.
> +
> +If you need the interface as a real network interface meaning running and
> has
> +a valid IP address then you can do this with the following commands::
> +
> + sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
> + sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
> +
> +Please change the IP addresses as you see fit.
> +
> +If routing is enabled on the host you can also communicate with the DPDK
> App
> +over the internet via a standard socket layer application as long as you
> +account for the protocol handing in the application.
> +
> +If you have a Network Stack in your DPDK application or something like it
> you
> +can utilize that stack to handle the network protocols. Plus you would be
> able
> +to address the interface using an IP address assigned to the internal
> +interface.
> +
> +Example
> +-------
> +
> +The following is a simple example of using the TUN/TAP PMD with the Pktgen
> +packet generator. It requires that the ``socat`` utility is installed on
> the
> +test system.
> +
> +Build DPDK, then pull down Pktgen and build pktgen using the DPDK
> SDK/Target
> +used to build the dpdk you pulled down.
> +
> +Run pktgen from the pktgen directory in a terminal with a commandline
> like the
> +following::
> +
> + sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4
> \
> + --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix
> pg \
> + --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1
> \
> + -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3
> \
> + -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3
> \
> + -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1
> \
> + -f themes/black-yellow.theme
> +
> +.. Note:
> +
> + Change the ``-b`` options to blacklist all of your physical ports. The
> + following command line is all one line.
> +
> + Also, ``-f themes/black-yellow.theme`` is optional if the default
> colors
> + work on your system configuration. See the Pktgen docs for more
> + information.
> +
> +Verify with ``ifconfig -a`` command in a different xterm window, should
> have a
> +``dtap0`` and ``dtap1`` interfaces created.
> +
> +Next set the links for the two interfaces to up via the commands below::
> +
> + sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev
> dtap0
> + sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev
> dtap1
> +
> +Then use socat to create a loopback for the two interfaces::
> +
> + sudo socat interface:dtap0 interface:dtap1
> +
> +Then on the Pktgen command line interface you can start sending packets
> using
> +the commands ``start 0`` and ``start 1`` or you can start both at the same
> +time with ``start all``. The command ``str`` is an alias for ``start
> all`` and
> +``stp`` is an alias for ``stop all``.
> +
> +While running you should see the 64 byte counters increasing to verify the
> +traffic is being looped back. You can use ``set all size XXX`` to change
> the
> +size of the packets after you stop the traffic. Use the pktgen ``help``
> +command to see a list of all commands. You can also use the ``-f`` option
> to
> +load commands at startup.
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index bc93230..e366a85 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
> DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
> DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
> DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
> DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
> DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
> DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
> diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
> new file mode 100644
> index 0000000..e18f30c
> --- /dev/null
> +++ b/drivers/net/tap/Makefile
> @@ -0,0 +1,57 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2016 Intel Corporation. All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * 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.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +# "AS 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 COPYRIGHT
> +# OWNER 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.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_tap.a
> +
> +EXPORT_MAP := rte_pmd_tap_version.map
> +
> +LIBABIVER := 1
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> new file mode 100644
> index 0000000..976f2d9
> --- /dev/null
> +++ b/drivers/net/tap/rte_eth_tap.c
> @@ -0,0 +1,765 @@
> +/*-
> + * BSD LICENSE
> + *
> + * Copyright(c) 2016 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * 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.
> + * * Neither the name of Intel Corporation nor the names of its
> + * contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS 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 COPYRIGHT
> + * OWNER 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.
> + */
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_vdev.h>
> +#include <rte_kvargs.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/socket.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <unistd.h>
> +#include <poll.h>
> +#include <arpa/inet.h>
> +#include <linux/if.h>
> +#include <linux/if_tun.h>
> +#include <linux/if_ether.h>
> +#include <fcntl.h>
> +
> +/* Linux based path to the TUN device */
> +#define TUN_TAP_DEV_PATH "/dev/net/tun"
> +#define DEFAULT_TAP_NAME "dtap"
> +
> +#define ETH_TAP_IFACE_ARG "iface"
> +#define ETH_TAP_SPEED_ARG "speed"
> +
> +#define RTE_PMD_TAP_MAX_QUEUES 16
> +
> +static struct rte_vdev_driver pmd_tap_drv;
> +
> +static const char *valid_arguments[] = {
> + ETH_TAP_IFACE_ARG,
> + ETH_TAP_SPEED_ARG,
> + NULL
> +};
> +
> +static int tap_unit;
> +
> +static struct rte_eth_link pmd_link = {
> + .link_speed = ETH_SPEED_NUM_10G,
> + .link_duplex = ETH_LINK_FULL_DUPLEX,
> + .link_status = ETH_LINK_DOWN,
> + .link_autoneg = ETH_LINK_SPEED_AUTONEG
> +};
> +
> +struct pkt_stats {
> + uint64_t opackets; /* Number of output packets */
> + uint64_t ipackets; /* Number of input packets */
> + uint64_t obytes; /* Number of bytes on output */
> + uint64_t ibytes; /* Number of bytes on input */
> + uint64_t errs; /* Number of error packets */
> +};
> +
> +struct rx_queue {
> + struct rte_mempool *mp; /* Mempool for RX packets */
> + uint16_t in_port; /* Port ID */
> + int fd;
> +
> + struct pkt_stats stats; /* Stats for this RX queue */
> +};
> +
> +struct tx_queue {
> + int fd;
> + struct pkt_stats stats; /* Stats for this TX queue */
> +};
> +
> +struct pmd_internals {
> + char name[RTE_ETH_NAME_MAX_LEN]; /* Internal Tap device
> name */
> + uint16_t nb_queues; /* Number of queues supported */
> + struct ether_addr eth_addr; /* Mac address of the device port
> */
> +
> + int if_index; /* IF_INDEX for the port */
> + int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
> +
> + struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX
> queues */
> + struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX
> queues */
> +};
> +
> +/* Tun/Tap allocation routine
> + *
> + * name is the number of the interface to use, unless NULL to take the
> host
> + * supplied name.
> + */
> +static int
> +tun_alloc(char *name)
> +{
> + struct ifreq ifr;
> + unsigned int features;
> + int fd;
> +
> + memset(&ifr, 0, sizeof(struct ifreq));
> +
> + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
> + if (name && name[0])
> + strncpy(ifr.ifr_name, name, IFNAMSIZ);
> +
> + fd = open(TUN_TAP_DEV_PATH, O_RDWR);
> + if (fd < 0) {
> + RTE_LOG(ERR, PMD, "Unable to create TAP interface");
> + goto error;
> + }
> +
> + /* Grab the TUN features to verify we can work */
> + if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
> + goto error;
> + }
> + RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
> +
> + if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1))
> {
> + RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
> + goto error;
> + } else if ((features & IFF_ONE_QUEUE) &&
> + (RTE_PMD_TAP_MAX_QUEUES == 1)) {
> + ifr.ifr_flags |= IFF_ONE_QUEUE;
> + RTE_LOG(DEBUG, PMD, "Single queue only support\n");
> + } else {
> + ifr.ifr_flags |= IFF_MULTI_QUEUE;
> + RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
> + RTE_PMD_TAP_MAX_QUEUES);
> + }
> +
> + /* Set the TUN/TAP configuration and get the name if needed */
> + if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
> + ifr.ifr_name);
> + perror("TUNSETIFF");
> + goto error;
> + }
> +
> + /* Always set the file descriptor to non-blocking */
> + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
> + perror("F_SETFL, NONBLOCK");
> + goto error;
> + }
> +
> + /* If the name is different that new name as default */
> + if (name && strcmp(name, ifr.ifr_name))
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s",
> ifr.ifr_name);
> +
> + return fd;
> +
> +error:
> + if (fd > 0)
> + close(fd);
> + return -1;
> +}
> +
> +/* Callback to handle the rx burst of packets to the correct interface and
> + * file descriptor(s) in a multi-queue setup.
> + */
> +static uint16_t
> +pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> +{
> + int len;
> + struct rte_mbuf *mbuf;
> + struct rx_queue *rxq = queue;
> + uint16_t num_rx;
> + unsigned long num_rx_bytes = 0;
> +
> + for (num_rx = 0; num_rx < nb_pkts; ) {
> + /* allocate the next mbuf */
> + mbuf = rte_pktmbuf_alloc(rxq->mp);
> + if (unlikely(!mbuf)) {
> + RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
> + break;
> + }
> +
> + len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
> + rte_pktmbuf_tailroom(mbuf));
> + if (len <= 0) {
> + rte_pktmbuf_free(mbuf);
> + break;
> + }
> +
> + mbuf->data_len = len;
> + mbuf->pkt_len = len;
> + mbuf->port = rxq->in_port;
> +
> + /* account for the receive frame */
> + bufs[num_rx++] = mbuf;
> + num_rx_bytes += mbuf->pkt_len;
> + }
> + rxq->stats.ipackets += num_rx;
> + rxq->stats.ibytes += num_rx_bytes;
> +
> + return num_rx;
> +}
> +
> +/* Callback to handle sending packets from the tap interface
> + */
> +static uint16_t
> +pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> +{
> + struct rte_mbuf *mbuf;
> + struct tx_queue *txq = queue;
> + struct pollfd pfd;
> + uint16_t num_tx = 0;
> + unsigned long num_tx_bytes = 0;
> + int i, n;
> +
> + if (unlikely(nb_pkts == 0))
> + return 0;
> +
> + pfd.events = POLLOUT;
> + pfd.fd = txq->fd;
> + for (i = 0; i < nb_pkts; i++) {
> + n = poll(&pfd, 1, 0);
> +
> + if (n <= 0)
> + break;
> +
> + if (pfd.revents & POLLOUT) {
> + /* copy the tx frame data */
> + mbuf = bufs[num_tx];
> + n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
> + rte_pktmbuf_pkt_len(mbuf));
> + if (n <= 0)
> + break;
> +
> + num_tx++;
> + num_tx_bytes += mbuf->pkt_len;
> + rte_pktmbuf_free(mbuf);
> + }
> + }
> +
> + txq->stats.opackets += num_tx;
> + txq->stats.errs += nb_pkts - num_tx;
> + txq->stats.obytes += num_tx_bytes;
> +
> + return num_tx;
> +}
> +
> +static int
> +tap_dev_start(struct rte_eth_dev *dev)
> +{
> + /* Force the Link up */
> + dev->data->dev_link.link_status = ETH_LINK_UP;
> +
> + return 0;
> +}
> +
> +/* This function gets called when the current port gets stopped.
> + */
> +static void
> +tap_dev_stop(struct rte_eth_dev *dev)
> +{
> + int i;
> + struct pmd_internals *internals = dev->data->dev_private;
> +
> + for (i = 0; i < internals->nb_queues; i++)
> + if (internals->fds[i] != -1)
> + close(internals->fds[i]);
> +
> + dev->data->dev_link.link_status = ETH_LINK_DOWN;
> +}
> +
> +static int
> +tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
> +{
> + return 0;
> +}
> +
> +static void
> +tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> +
> + dev_info->if_index = internals->if_index;
> + dev_info->max_mac_addrs = 1;
> + dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
> + dev_info->max_rx_queues = internals->nb_queues;
> + dev_info->max_tx_queues = internals->nb_queues;
> + dev_info->min_rx_bufsize = 0;
> + dev_info->pci_dev = NULL;
> +}
> +
> +static void
> +tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
> +{
> + unsigned int i, imax;
> + unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
> + unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
> + const struct pmd_internals *pmd = dev->data->dev_private;
> +
> + imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
> + pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
> +
> + for (i = 0; i < imax; i++) {
> + tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
> + tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
> + rx_total += tap_stats->q_ipackets[i];
> + rx_bytes_total += tap_stats->q_ibytes[i];
> + }
> +
> + for (i = 0; i < imax; i++) {
> + tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
> + tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
> + tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
> + tx_total += tap_stats->q_opackets[i];
> + tx_err_total += tap_stats->q_errors[i];
> + tx_bytes_total += tap_stats->q_obytes[i];
> + }
> +
> + tap_stats->ipackets = rx_total;
> + tap_stats->ibytes = rx_bytes_total;
> + tap_stats->opackets = tx_total;
> + tap_stats->oerrors = tx_err_total;
> + tap_stats->obytes = tx_bytes_total;
> +}
> +
> +static void
> +tap_stats_reset(struct rte_eth_dev *dev)
> +{
> + int i;
> + struct pmd_internals *pmd = dev->data->dev_private;
> +
> + for (i = 0; i < pmd->nb_queues; i++) {
> + pmd->rxq[i].stats.ipackets = 0;
> + pmd->rxq[i].stats.ibytes = 0;
> + }
> +
> + for (i = 0; i < pmd->nb_queues; i++) {
> + pmd->txq[i].stats.opackets = 0;
> + pmd->txq[i].stats.errs = 0;
> + pmd->txq[i].stats.obytes = 0;
> + }
> +}
> +
> +static void
> +tap_dev_close(struct rte_eth_dev *dev __rte_unused)
> +{
> +}
> +
> +static void
> +tap_rx_queue_release(void *queue)
> +{
> + struct rx_queue *rxq = queue;
> +
> + if (rxq && (rxq->fd > 0)) {
> + close(rxq->fd);
> + rxq->fd = -1;
> + }
> +}
> +
> +static void
> +tap_tx_queue_release(void *queue)
> +{
> + struct tx_queue *txq = queue;
> +
> + if (txq && (txq->fd > 0)) {
> + close(txq->fd);
> + txq->fd = -1;
> + }
> +}
> +
> +static int
> +tap_link_update(struct rte_eth_dev *dev __rte_unused,
> + int wait_to_complete __rte_unused)
> +{
> + return 0;
> +}
> +
> +static int
> +tap_setup_queue(struct rte_eth_dev *dev,
> + struct pmd_internals *internals,
> + uint16_t qid)
> +{
> + struct rx_queue *rx = &internals->rxq[qid];
> + struct tx_queue *tx = &internals->txq[qid];
> + int fd;
> +
> + fd = rx->fd;
> + if (fd < 0) {
> + fd = tx->fd;
> + if (fd < 0) {
> + RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid
> %d\n",
> + dev->data->name, qid);
> + fd = tun_alloc(dev->data->name);
> + if (fd < 0) {
> + RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
> + dev->data->name);
> + return -1;
> + }
> + }
> + }
> + dev->data->rx_queues[qid] = rx;
> + dev->data->tx_queues[qid] = tx;
> +
> + rx->fd = fd;
> + tx->fd = fd;
> +
> + return fd;
> +}
> +
> +static int
> +tap_rx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t rx_queue_id,
> + uint16_t nb_rx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_rxconf *rx_conf __rte_unused,
> + struct rte_mempool *mp)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + uint16_t buf_size;
> + int fd;
> +
> + if ((rx_queue_id >= internals->nb_queues) || !mp) {
> + RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
> + internals->nb_queues, mp);
> + return -1;
> + }
> +
> + internals->rxq[rx_queue_id].mp = mp;
> + internals->rxq[rx_queue_id].in_port = dev->data->port_id;
> +
> + /* Now get the space available for data in the mbuf */
> + buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
> + RTE_PKTMBUF_HEADROOM);
> +
> + if (buf_size < ETH_FRAME_LEN) {
> + RTE_LOG(ERR, PMD,
> + "%s: %d bytes will not fit in mbuf (%d bytes)\n",
> + dev->data->name, ETH_FRAME_LEN, buf_size);
> + return -ENOMEM;
> + }
> +
> + fd = tap_setup_queue(dev, internals, rx_queue_id);
> + if (fd == -1)
> + return -1;
> +
> + internals->fds[rx_queue_id] = fd;
> + RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
> + dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].
> fd);
> +
> + return 0;
> +}
> +
> +static int
> +tap_tx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t tx_queue_id,
> + uint16_t nb_tx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_txconf *tx_conf __rte_unused)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + int ret;
> +
> + if (tx_queue_id >= internals->nb_queues)
> + return -1;
> +
> + ret = tap_setup_queue(dev, internals, tx_queue_id);
> + if (ret == -1)
> + return -1;
> +
> + RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
> + dev->data->name, tx_queue_id, internals->txq[tx_queue_id].
> fd);
> +
> + return 0;
> +}
> +
> +static const struct eth_dev_ops ops = {
> + .dev_start = tap_dev_start,
> + .dev_stop = tap_dev_stop,
> + .dev_close = tap_dev_close,
> + .dev_configure = tap_dev_configure,
> + .dev_infos_get = tap_dev_info,
> + .rx_queue_setup = tap_rx_queue_setup,
> + .tx_queue_setup = tap_tx_queue_setup,
> + .rx_queue_release = tap_rx_queue_release,
> + .tx_queue_release = tap_tx_queue_release,
> + .link_update = tap_link_update,
> + .stats_get = tap_stats_get,
> + .stats_reset = tap_stats_reset,
> +};
> +
> +static int
> +pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
> +{
> + struct ifreq ifr;
> +
> + if ((fd <= 0) || !dev || !addr)
> + return -1;
> +
> + memset(&ifr, 0, sizeof(ifr));
> +
> + if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
> + RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
> + ifr.ifr_name);
> + return -1;
> + }
> +
> + /* Set the host based MAC address to this special MAC format */
> + ifr.ifr_hwaddr.sa_data[0] = 'T';
> + ifr.ifr_hwaddr.sa_data[1] = 'a';
> + ifr.ifr_hwaddr.sa_data[2] = 'p';
> + ifr.ifr_hwaddr.sa_data[3] = '-';
> + ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
> + ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
> + if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
> + RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR)
> (%s)\n",
> + dev->data->name, ifr.ifr_name);
> + return -1;
> + }
> +
> + /* Set the local application MAC address, needs to be different
> then
> + * the host based MAC address.
> + */
> + ifr.ifr_hwaddr.sa_data[0] = 'd';
> + ifr.ifr_hwaddr.sa_data[1] = 'n';
> + ifr.ifr_hwaddr.sa_data[2] = 'e';
> + ifr.ifr_hwaddr.sa_data[3] = 't';
> + ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
> + ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
> + rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
> +
> + return 0;
> +}
> +
> +static int
> +eth_dev_tap_create(const char *name, char *tap_name)
> +{
> + int numa_node = rte_socket_id();
> + struct rte_eth_dev *dev = NULL;
> + struct pmd_internals *pmd = NULL;
> + struct rte_eth_dev_data *data = NULL;
> + int i, fd = -1;
> +
> + RTE_LOG(INFO, PMD,
> + "%s: Create TAP Ethernet device with %d queues on numa
> %u\n",
> + name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
> +
> + data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
> + if (!data) {
> + RTE_LOG(INFO, PMD, "Failed to allocate data\n");
> + goto error_exit;
> + }
> +
> + pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
> + if (!pmd) {
> + RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
> + goto error_exit;
> + }
> +
> + /* Use the name and not the tap_name */
> + dev = rte_eth_dev_allocate(tap_name);
> + if (!dev) {
> + RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
> + goto error_exit;
> + }
> +
> + snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
> +
> + pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
> +
> + /* Setup some default values */
> + data->dev_private = pmd;
> + data->port_id = dev->data->port_id;
> + data->dev_flags = RTE_ETH_DEV_DETACHABLE;
> + data->kdrv = RTE_KDRV_NONE;
> + data->drv_name = pmd_tap_drv.driver.name;
> + data->numa_node = numa_node;
> +
> + data->dev_link = pmd_link;
> + data->mac_addrs = &pmd->eth_addr;
> + data->nb_rx_queues = pmd->nb_queues;
> + data->nb_tx_queues = pmd->nb_queues;
> +
> + dev->data = data;
> + dev->dev_ops = &ops;
> + dev->driver = NULL;
> + dev->rx_pkt_burst = pmd_rx_burst;
> + dev->tx_pkt_burst = pmd_tx_burst;
> + snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
> +
> + /* Create the first Tap device */
> + fd = tun_alloc(tap_name);
> + if (fd < 0) {
> + RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
> + goto error_exit;
> + }
> +
> + /* Presetup the fds to -1 as being not working */
> + for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
> + pmd->fds[i] = -1;
> + pmd->rxq[i].fd = -1;
> + pmd->txq[i].fd = -1;
> + }
> +
> + /* Take the TUN/TAP fd and place in the first location */
> + pmd->rxq[0].fd = fd;
> + pmd->txq[0].fd = fd;
> + pmd->fds[0] = fd;
> +
> + if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
> + RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
> + goto error_exit;
> + }
> +
> + return 0;
> +
> +error_exit:
> + RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
> +
> + rte_free(data);
> + rte_free(pmd);
> +
> + rte_eth_dev_release_port(dev);
> +
> + return -EINVAL;
> +}
> +
> +static int
> +set_interface_name(const char *key __rte_unused,
> + const char *value,
> + void *extra_args)
> +{
> + char *name = (char *)extra_args;
> +
> + if (value)
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
> + else
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
> + DEFAULT_TAP_NAME, (tap_unit - 1));
> +
> + return 0;
> +}
> +
> +static int
> +set_interface_speed(const char *key __rte_unused,
> + const char *value,
> + void *extra_args)
> +{
> + *(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
> +
> + return 0;
> +}
> +
> +/* Open a TAP interface device.
> + */
> +static int
> +rte_pmd_tap_probe(const char *name, const char *params)
> +{
> + int ret;
> + struct rte_kvargs *kvlist = NULL;
> + int speed;
> + char tap_name[RTE_ETH_NAME_MAX_LEN];
> +
> + speed = ETH_SPEED_NUM_10G;
> + snprintf(tap_name, sizeof(tap_name), "%s%d",
> + DEFAULT_TAP_NAME, tap_unit++);
> +
> + RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
> + name, tap_name);
> +
> + if (params && (params[0] != '\0')) {
> + RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
> +
> + kvlist = rte_kvargs_parse(params, valid_arguments);
> + if (kvlist) {
> + if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) ==
> 1) {
> + ret = rte_kvargs_process(kvlist,
> + ETH_TAP_SPEED_ARG,
> +
> &set_interface_speed,
> + &speed);
> + if (ret == -1)
> + goto leave;
> + }
> +
> + if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) ==
> 1) {
> + ret = rte_kvargs_process(kvlist,
> + ETH_TAP_IFACE_ARG,
> +
> &set_interface_name,
> + tap_name);
> + if (ret == -1)
> + goto leave;
> + }
> + }
> + }
> + pmd_link.link_speed = speed;
> +
> + ret = eth_dev_tap_create(name, tap_name);
> +
> +leave:
> + if (ret == -1) {
> + RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
> + name, tap_name);
> + tap_unit--; /* Restore the unit number */
> + }
> + rte_kvargs_free(kvlist);
> +
> + return ret;
> +}
> +
> +/* detach a TAP device.
> + */
> +static int
> +rte_pmd_tap_remove(const char *name)
> +{
> + struct rte_eth_dev *eth_dev = NULL;
> + struct pmd_internals *internals;
> + int i;
> +
> + RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
> + rte_socket_id());
> +
> + /* find the ethdev entry */
> + eth_dev = rte_eth_dev_allocated(name);
> + if (!eth_dev)
> + return 0;
> +
> + internals = eth_dev->data->dev_private;
> + for (i = 0; i < internals->nb_queues; i++)
> + if (internals->fds[i] != -1)
> + close(internals->fds[i]);
> +
> + rte_free(eth_dev->data->dev_private);
> + rte_free(eth_dev->data);
> +
> + rte_eth_dev_release_port(eth_dev);
> +
> + return 0;
> +}
> +
> +static struct rte_vdev_driver pmd_tap_drv = {
> + .probe = rte_pmd_tap_probe,
> + .remove = rte_pmd_tap_remove,
> +};
> +RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
> +RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
> +RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
> diff --git a/drivers/net/tap/rte_pmd_tap_version.map
> b/drivers/net/tap/rte_pmd_tap_version.map
> new file mode 100644
> index 0000000..31eca32
> --- /dev/null
> +++ b/drivers/net/tap/rte_pmd_tap_version.map
> @@ -0,0 +1,4 @@
> +DPDK_17.02 {
> +
> + local: *;
> +};
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index f75f0e2..02c32ae 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) +=
> -lrte_pmd_pcap -lpcap
> _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += -lrte_pmd_qede
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) += -lrte_pmd_ring
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += -lrte_pmd_szedata2 -lsze2
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += -lrte_pmd_tap
> _LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) +=
> -lrte_pmd_thunderx_nicvf -lm
> _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += -lrte_pmd_virtio
> ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
> --
> 2.8.0.GIT
>
>
^ permalink raw reply
* Re: [PATCH] vmxnet3: fix Rx deadlock
From: Yong Wang @ 2016-12-12 18:17 UTC (permalink / raw)
To: Stefan Puiu; +Cc: dev@dpdk.org, mac_leehk@yahoo.com.hk
In-Reply-To: <CACKs7VAJDu6aMY6tLJXcM4doS8diZkAOidVCRZwR6u1RTuRaDQ@mail.gmail.com>
> -----Original Message-----
> From: Stefan Puiu [mailto:stefan.puiu@gmail.com]
> Sent: Monday, December 12, 2016 12:27 AM
> To: Yong Wang <yongwang@vmware.com>
> Cc: dev@dpdk.org; mac_leehk@yahoo.com.hk
> Subject: Re: [PATCH] vmxnet3: fix Rx deadlock
>
> Hello and thanks for reviewing the patch.
>
> On Wed, Nov 30, 2016 at 6:59 AM, Yong Wang <yongwang@vmware.com>
> wrote:
> [...]
> > I think a more accurate description is that the particular descriptor's
> generation bit never got flipped properly when an mbuf failed to be refilled
> which caused the rx stuck, rather than vmxnet3_post_rx_bufs() not being
> called afterwards.
> >
>
> Not sure if this kind of level of detail is useful, but if you can
> think of a better explanation to put in the changelist, I can add it.
> I see the generation bit not flipping as a symptom, while the core
> problem is the hardware can't write to the descriptor. I felt the
> explanation was going into too much detail anyway, so I've reworded it
> a bit for v2. Let me know what you think.
This is one of the cases that I prefer accuracy and I think the level of details is needed for whoever will work on this part of the code (datapath tx and rx routines).
The v2 description looks good to me expect the following description:
"nobody retries this later, so the driver gets stuck in this state."
The driver definitely retries vmxnet3_post_rx_bufs() after it was in the problematic state but due to the descriptor's gen bit not flipped, the driver won't refill an mbuf. How about "the driver won't refill the mbuf after this so it gets stuck in this state."?
> Thanks,
> Stefan.
^ permalink raw reply
* Re: [PATCH 6/7] net/qede: fix maximum VF count to 0
From: Ferruh Yigit @ 2016-12-12 18:13 UTC (permalink / raw)
To: Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev, Thomas Monjalon
In-Reply-To: <D47420A6.C0178%Harish.Patil@cavium.com>
On 12/12/2016 5:47 PM, Harish Patil wrote:
>
>> On 12/3/2016 2:43 AM, Harish Patil wrote:
>>> Set max_vfs to 0 since it is relevant only to SR-IOV PF
>>> which is not supported yet.
>>>
>>> Fixes: 2ea6f76a ("qede: add core driver")
>>>
>>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>>
>> Can you please update patch title to indicate what has been fixed
>> instead of what has been done in the patch.
>
> Can you please clarify? The change in the patch is to set max_vfs=0.
> So that’s why the title - "fix maximum VF count to 0"
Let me try, if I can :)
I can see what patch does, and I got the reasoning behind.
Previously driver was reporting as it was supporting SR-IOV with DPDK
PF, right? But it was wrong and you are fixing it.
How you fix is by setting max_vfs=0, but that is the technical detail of
the fix.
What you are trying to fix is not setting a variable to a specific
value, what you are trying to fix is SR-IOV support.
I hope I can make it more clear.
>
>>
>>
>> btw, while checking feature list, I have seen qede_vf supports SR-IOV,
>> is that correct?
>
> Yes. The supported combination for SR-IOV is VF driver (qede PMD) with PF
> driver (qede linux driver).
So you are using SR-IOV feature set in VF driver, as meaning VF driver
support exists. I don't know what SR-IOV feature mean for VF drivers.
Some other VF drivers not has this feature flag set.
CC'ed Thomas for help, if this is the intention of the feature flag, it
is OK.
> We don’t have support for SR-IOV PF driver yet. When SR-IOV PF driver is
> supported then max_vfs shall return the actual max VFs, but for now it
> should return max_vfs=0. Hope it is clear.
>
>>
>>> ---
>>> drivers/net/qede/qede_ethdev.c | 5 +----
>>> 1 file changed, 1 insertion(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/net/qede/qede_ethdev.c
>>> b/drivers/net/qede/qede_ethdev.c
>>> index ee8fb43..10abb8b 100644
>>> --- a/drivers/net/qede/qede_ethdev.c
>>> +++ b/drivers/net/qede/qede_ethdev.c
>>> @@ -976,10 +976,7 @@ static int qede_dev_configure(struct rte_eth_dev
>>> *eth_dev)
>>> dev_info->max_rx_queues = (uint16_t)QEDE_MAX_RSS_CNT(qdev);
>>> dev_info->max_tx_queues = dev_info->max_rx_queues;
>>> dev_info->max_mac_addrs = qdev->dev_info.num_mac_addrs;
>>> - if (IS_VF(edev))
>>> - dev_info->max_vfs = 0;
>>> - else
>>> - dev_info->max_vfs = (uint16_t)NUM_OF_VFS(&qdev->edev);
>>> + dev_info->max_vfs = 0;
>>> dev_info->reta_size = ECORE_RSS_IND_TABLE_SIZE;
>>> dev_info->hash_key_size = ECORE_RSS_KEY_SIZE * sizeof(uint32_t);
>>> dev_info->flow_type_rss_offloads = (uint64_t)QEDE_RSS_OFFLOAD_ALL;
>>>
>>
>>
>
>
^ permalink raw reply
* Re: [RFC PATCH] eventdev: add buffered enqueue and flush APIs
From: Eads, Gage @ 2016-12-12 17:56 UTC (permalink / raw)
To: Jerin Jacob
Cc: dev@dpdk.org, Richardson, Bruce, Van Haaren, Harry,
hemant.agrawal@nxp.com
In-Reply-To: <20161208044139.GA24793@svelivela-lt.caveonetworks.com>
> -----Original Message-----
> From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> Sent: Wednesday, December 7, 2016 10:42 PM
> To: Eads, Gage <gage.eads@intel.com>
> Cc: dev@dpdk.org; Richardson, Bruce <bruce.richardson@intel.com>; Van
> Haaren, Harry <harry.van.haaren@intel.com>; hemant.agrawal@nxp.com
> Subject: Re: [RFC PATCH] eventdev: add buffered enqueue and flush APIs
>
> On Mon, Dec 05, 2016 at 11:30:46PM +0000, Eads, Gage wrote:
> >
> > > On Dec 3, 2016, at 5:18 AM, Jerin Jacob
> <jerin.jacob@caviumnetworks.com> wrote:
> > >
> > >> On Fri, Dec 02, 2016 at 01:45:56PM -0600, Gage Eads wrote:
> > >> This commit adds buffered enqueue functionality to the eventdev API.
> > >> It is conceptually similar to the ethdev API's tx buffering,
> > >> however with a smaller API surface and no dropping of events.
> > >
> > > Hello Gage,
> > > Different implementation may have different strategies to hold the buffers.
> >
> > A benefit of inlining the buffering logic in the header is that we avoid the
> overhead of entering the PMD for what is a fairly simple operation (common
> case: add event to an array, increment counter). If we make this
> implementation-defined (i.e. use PMD callbacks), we lose that benefit.
> In general, I agree from the system perspective. But, few general issues with
> eventdev integration part,
>
> 1) What if the burst has ATOMIC flows and if we are NOT en-queuing to the
> implementation then other event ports won't get the packets from the same
> ATOMIC tag ? BAD. Right?
I'm not sure what scenario you're describing here. The buffered (as implemented in my patch) and non-buffered enqueue operations are functionally the same (as long as the buffer is flushed), the difference lies in when the events are moved from the application level to the PMD.
> 2) At least, In our HW implementation, The event buffer strategy is more like, if
> you enqueue to HW then ONLY you get the events from dequeue provided if op
> == RTE_EVENT_OP_FORWARD.So it will create deadlock.i.e application cannot
> hold the events with RTE_EVENT_OP_FORWARD
If I'm reading this correctly, you're concerned that buffered events can result in deadlock if they're not flushed. Whether the buffering is done in the app itself, inline in the API, or in the PMDs, not flushing the buffer is an application bug. E.g. the app could be fixed by flushing its enqueue buffer after processing every burst dequeued event set, or only if dequeue returns 0 events.
> 3) So considering the above case there is nothing like flush for us
> 4) In real high throughput benchmark case, we will get the packets at the rate
> of max burst and then we always needs to memcpy before we flush.
> Otherwise there will be ordering issue as burst can get us the packet from
> different flows(unlike polling mode)
I take it you're referring to the memcpy in the patch, and not an additional memcpy? At any rate, I'm hoping that SIMD instructions can optimize the 16B event copy.
>
> >
> > > and some does not need to hold the buffers if it is DDR backed.
> >
> > Though DDR-backed hardware doesn't need to buffer in software, doing so
> would reduce the software overhead of enqueueing. Compared to N individual
> calls to enqueue, buffering N events then calling enqueue burst once can
> benefit from amortized (or parallelized) PMD-specific bookkeeping and error-
> checking across the set of events, and will definitely benefit from the amortized
> function call overhead and better I-cache behavior. (Essentially this is VPP from
> the fd.io project.) This should result in higher overall event throughout
> (agnostic of the underlying device).
>
> See above. I am not against burst processing in "application".
> The flush does not make sense for us in HW perspective and it is costly for us if
> we trying generalize it.
>
Besides the data copy that buffering requires, are there additional costs from your perspective?
> >
> > I'm skeptical that other buffering strategies would emerge, but I can only
> speculate on Cavium/NXP/etc. NPU software.
> i>
> > > IHMO, This may not be the candidate for common code. I guess you can
> > > move this to driver side and abstract under SW driver's enqueue_burst.
> > >
> >
> > I don't think that will work without adding a flush API, otherwise we could
> have indefinitely buffered events. I see three ways forward:
>
> I agree. More portable way is to move the "flush" to the implementation and
> "flush"
> whenever it makes sense to PMD.
>
> >
> > - The proposed approach
> > - Add the proposed functions but make them implementation-specific.
> > - Require the application to write its own buffering logic (i.e. no
> > API change)
>
> I think, If the additional function call overhead cost is too much for SW
> implementation then we can think of implementation-specific API or custom
> application flow based on SW driver.
>
> But I am not fan of that(but tempted do now a days), If we take that route, we
> have truckload of custom implementation specific API and now we try to hide
> all black magic under enqueue/dequeue to make it portable at some expense.
Agreed, it's not worth special-casing the API with this relatively minor addition.
Thanks,
Gage
^ permalink raw reply
* [PATCH] vhost: Introduce vhost-user's REPLY_ACK feature
From: Maxime Coquelin @ 2016-12-12 17:54 UTC (permalink / raw)
To: yuanhan.liu, dev; +Cc: Maxime Coquelin
REPLY_ACK features provide a generic way for QEMU to ensure both
completion and success of a request.
As described in vhost-user spec in QEMU repository, QEMU sets
VHOST_USER_NEED_REPLY flag (bit 3) when expecting a reply_ack from
the backend. Backend must reply with 0 for success or non-zero
otherwise when flag is set.
Currently, only VHOST_USER_SET_MEM_TABLE request implements reply_ack,
in order to synchronize mapping updates.
This patch enables REPLY_ACK feature generally, but only checks error
code for VHOST_USER_SET_MEM_TABLE.
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
Hi,
The intend of this patch is not to fix a known issue, but it is
nice to have this feature, and it will be used by upcoming MTU
feature if it remains in its current form.
Thanks,
Maxime
lib/librte_vhost/vhost_user.c | 11 ++++++++++-
lib/librte_vhost/vhost_user.h | 5 ++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 6b83c15..9ce80cb 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -903,6 +903,7 @@ send_vhost_message(int sockfd, struct VhostUserMsg *msg)
return 0;
msg->flags &= ~VHOST_USER_VERSION_MASK;
+ msg->flags &= ~VHOST_USER_NEED_REPLY;
msg->flags |= VHOST_USER_VERSION;
msg->flags |= VHOST_USER_REPLY_MASK;
@@ -938,6 +939,7 @@ vhost_user_msg_handler(int vid, int fd)
return -1;
}
+ ret = 0;
RTE_LOG(INFO, VHOST_CONFIG, "read message %s\n",
vhost_message_str[msg.request]);
switch (msg.request) {
@@ -967,7 +969,7 @@ vhost_user_msg_handler(int vid, int fd)
break;
case VHOST_USER_SET_MEM_TABLE:
- vhost_user_set_mem_table(dev, &msg);
+ ret = vhost_user_set_mem_table(dev, &msg);
break;
case VHOST_USER_SET_LOG_BASE:
@@ -1025,9 +1027,16 @@ vhost_user_msg_handler(int vid, int fd)
break;
default:
+ ret = -1;
break;
}
+ if (msg.flags & VHOST_USER_NEED_REPLY) {
+ msg.payload.u64 = !!ret;
+ msg.size = sizeof(msg.payload.u64);
+ send_vhost_message(fd, &msg);
+ }
+
return 0;
}
diff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h
index ba78d32..179e441 100644
--- a/lib/librte_vhost/vhost_user.h
+++ b/lib/librte_vhost/vhost_user.h
@@ -46,10 +46,12 @@
#define VHOST_USER_PROTOCOL_F_MQ 0
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
#define VHOST_USER_PROTOCOL_F_RARP 2
+#define VHOST_USER_PROTOCOL_F_REPLY_ACK 3
#define VHOST_USER_PROTOCOL_FEATURES ((1ULL << VHOST_USER_PROTOCOL_F_MQ) | \
(1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD) |\
- (1ULL << VHOST_USER_PROTOCOL_F_RARP))
+ (1ULL << VHOST_USER_PROTOCOL_F_RARP) | \
+ (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK))
typedef enum VhostUserRequest {
VHOST_USER_NONE = 0,
@@ -98,6 +100,7 @@ typedef struct VhostUserMsg {
#define VHOST_USER_VERSION_MASK 0x3
#define VHOST_USER_REPLY_MASK (0x1 << 2)
+#define VHOST_USER_NEED_REPLY (0x1 << 3)
uint32_t flags;
uint32_t size; /* the following payload size */
union {
--
2.9.3
^ permalink raw reply related
* Re: [PATCH 2/7] net/qede: refactor filtering code
From: Ferruh Yigit @ 2016-12-12 17:53 UTC (permalink / raw)
To: Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev
In-Reply-To: <D4741EDB.C012D%Harish.Patil@cavium.com>
On 12/12/2016 5:36 PM, Harish Patil wrote:
>
>> On 12/3/2016 2:43 AM, Harish Patil wrote:
>>> The filter_config in qed_eth_ops_pass is a wrapper call driving all the
>>> filtering configuration. This requires defining multiple structures and
>>> passing different function arguments for each filter type which is
>>> unnecessary. So as part of this refactoring we remove filter_config from
>>> qed_eth_ops_pass and invoke base apis directly. Another change is to
>>> use a singly list for unicast/multicast macs and thereby prevent
>>> duplicate
>>
>> singly linked list?
>
> Yes. Two lists to track unicast and multicast mac entries:
> + SLIST_HEAD(mc_list_head, qede_mcast_entry) mc_list_head;
>
> + SLIST_HEAD(uc_list_head, qede_ucast_entry) uc_list_head;
>
>
>
>>
>>> entries.
>>>
>>> This change is primarily intended to support future tunneling support
>>> which makes use of existing L2 filtering/classifications.
>>>
>>> Fixes: 2ea6f76a ("qede: add core driver")
>>
>> What is fixed in this patch, isn't it a refactor?
>
> The fix part is to make use of the newly added lists and prevent duplicate
> mac filters.
> Before that there were no checks. Other than that its refactoring to
> mainly invoke direct base APIs.
So this is not fixing any defect in driver, so I believe Fixes tag can
be removed. This tag is mainly useful to pick commits for stable trees.
>
>>
>> btw, all Fixes formats are wrong in the patchset, can you please use the
>> git alias provided:
>> http://dpdk.org/doc/guides/contributing/patches.html#commit-messages-body
>>
>>>
>>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>>> ---
>> <...>
>>
>
>
^ permalink raw reply
* Re: [PATCH 1/7] net/qede: reduce noise in debug logs
From: Ferruh Yigit @ 2016-12-12 17:50 UTC (permalink / raw)
To: Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev, Mody, Rasesh
In-Reply-To: <D474163F.BFFD0%Harish.Patil@cavium.com>
On 12/12/2016 5:15 PM, Harish Patil wrote:
> Hi Ferruh,
>
>> On 12/3/2016 2:43 AM, Harish Patil wrote:
>>> From: Rasesh Mody <Rasesh.Mody@cavium.com>
>>>
>>> Replace CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER with
>>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL which is a 32-bit bitmapped value
>>> where each bit represent a particular submodule to debug. Also move
>>> notice messages under CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO.
>>>
>>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>>> Signed-off-by: Rasesh Mody <Rasesh.Mody@cavium.com>
>>> ---
>>> config/common_base | 2 +-
>>> doc/guides/nics/qede.rst | 4 ++--
>>> drivers/net/qede/qede_ethdev.c | 4 ++--
>>> drivers/net/qede/qede_logs.h | 21 +++++----------------
>>> 4 files changed, 10 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/config/common_base b/config/common_base
>>> index 4bff83a..2ffd557 100644
>>> --- a/config/common_base
>>> +++ b/config/common_base
>>> @@ -320,7 +320,7 @@ CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
>>> CONFIG_RTE_LIBRTE_QEDE_PMD=y
>>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
>>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
>>> -CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
>>> +CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL=0
>>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
>>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
>>> #Provides abs path/name of the firmware file.
>>> diff --git a/doc/guides/nics/qede.rst b/doc/guides/nics/qede.rst
>>> index d22ecdd..ddf4248 100644
>>> --- a/doc/guides/nics/qede.rst
>>> +++ b/doc/guides/nics/qede.rst
>>> @@ -103,9 +103,9 @@ enabling debugging options may affect system
>>> performance.
>>>
>>> Toggle display of generic debugging messages.
>>>
>>> -- ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER`` (default **n**)
>>> +- ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL`` (default **0**)
>>
>> Does it make sense to document how DEBUG_VAL used?
>>
>> Also commit log says bitmapped value to enable/disable a particular
>> submodule, you may want to document here which value enable/disable
>> which submodule.
>>
>>>
>>> - Toggle display of ecore related messages.
>>> + Control driver debug verbosity using 32-bit bitmap flags.
>>>
>>> - ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX`` (default **n**)
>>>
>
> Not really, I think that would be too much. But if you think it really
> helps then perhaps yes we can document.
> Otherwise it is just for internal debugging.
As a user of your driver, how can I know how to enable / disable a
module log?
I know VAL enables / disables them, but I don't know what modules exists
and what values are required.
If this is just for internal debugging and user not need to configure
this one, does it needs to be a config option in configuration file?
>
>
>>
>> <...>
>>
>>> diff --git a/drivers/net/qede/qede_logs.h b/drivers/net/qede/qede_logs.h
>>> index 45c4af0..08fdf04 100644
>>> --- a/drivers/net/qede/qede_logs.h
>>> +++ b/drivers/net/qede/qede_logs.h
>>> @@ -16,15 +16,18 @@
>>> (p_dev)->name ? (p_dev)->name : "", \
>>> ##__VA_ARGS__)
>>>
>>> +#ifdef RTE_LIBRTE_QEDE_DEBUG_INFO
>>
>> Is "_INFO" carries any meaning in this config option, why not just
>> RTE_LIBRTE_QEDE_DEBUG?
>
> INFO is used to mean just informational type of messages.
> If you think it doesn’t make sense then I can rename it.
I don't have a strong opinion, I think that _INFO is not adding value
unless you have different config options per each level like _VERBOSE,
_INFO, _NOTICE. But if you believe your users will benefit from it, it
is your call.
>
>>
>>> #define DP_NOTICE(p_dev, is_assert, fmt, ...) \
>>> rte_log(RTE_LOG_NOTICE, RTE_LOGTYPE_PMD,\
>>> "[QEDE PMD: (%s)]%s:" fmt, \
>>> (p_dev)->name ? (p_dev)->name : "", \
>>> __func__, \
>>> ##__VA_ARGS__)
>>> +#else
>>> +#define DP_NOTICE(p_dev, fmt, ...) do { } while (0)
>>> +#endif
>>>
>>> #ifdef RTE_LIBRTE_QEDE_DEBUG_INFO
>>> -
>>> #define DP_INFO(p_dev, fmt, ...) \
>>> rte_log(RTE_LOG_INFO, RTE_LOGTYPE_PMD, \
>>> "[%s:%d(%s)]" fmt, \
>>> @@ -33,10 +36,8 @@
>>> ##__VA_ARGS__)
>>> #else
>>> #define DP_INFO(p_dev, fmt, ...) do { } while (0)
>>> -
>>> #endif
>>>
>>> -#ifdef RTE_LIBRTE_QEDE_DEBUG_DRIVER
>>
>> Are you sure you want to enable DP_VERBOSE, I guess most verbose log
>> macro, by default? Perhaps may want to control it via
>> RTE_LIBRTE_QEDE_DEBUG_INFO?
>
> DP_VERBOSE is enabled but it has a check:
> if ((p_dev)->dp_module & module)
> which controls what to print.
> Here dp_module is controlled by CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL flag.
> Hope it is clear.
Clear thanks,
I guess right now:
DEBUG_VAL: enables verbose debug for selected module(s)
DEBUG_INFO: Enables NOTICE and INFO level for ? (all modules?)
ERR level is always enabled
Again it is your call, but I think CONFIG_RTE_LIBRTE_QEDE_DEBUG can be
used to enable/disable all debugs, and when enabled QEDE_DEBUG_VAL can
select which modules to enable verbose debug ...
>>
>>> #define DP_VERBOSE(p_dev, module, fmt, ...) \
>>> do { \
>>> if ((p_dev)->dp_module & module) \
>>> @@ -46,9 +47,7 @@
>>> (p_dev)->name ? (p_dev)->name : "", \
>>> ##__VA_ARGS__); \
>>> } while (0)
>>> -#else
>>> -#define DP_VERBOSE(p_dev, fmt, ...) do { } while (0)
>>> -#endif
>>> +
>>>
>> <...>
>>
>>
>
^ permalink raw reply
* Re: [PATCH 6/7] net/qede: fix maximum VF count to 0
From: Harish Patil @ 2016-12-12 17:47 UTC (permalink / raw)
To: Ferruh Yigit, Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev
In-Reply-To: <f7ccf786-4f58-5e1e-3cd2-28725bb4e8b5@intel.com>
>On 12/3/2016 2:43 AM, Harish Patil wrote:
>> Set max_vfs to 0 since it is relevant only to SR-IOV PF
>> which is not supported yet.
>>
>> Fixes: 2ea6f76a ("qede: add core driver")
>>
>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>
>Can you please update patch title to indicate what has been fixed
>instead of what has been done in the patch.
Can you please clarify? The change in the patch is to set max_vfs=0.
So that’s why the title - "fix maximum VF count to 0"
>
>
>btw, while checking feature list, I have seen qede_vf supports SR-IOV,
>is that correct?
Yes. The supported combination for SR-IOV is VF driver (qede PMD) with PF
driver (qede linux driver).
We don’t have support for SR-IOV PF driver yet. When SR-IOV PF driver is
supported then max_vfs shall return the actual max VFs, but for now it
should return max_vfs=0. Hope it is clear.
>
>> ---
>> drivers/net/qede/qede_ethdev.c | 5 +----
>> 1 file changed, 1 insertion(+), 4 deletions(-)
>>
>> diff --git a/drivers/net/qede/qede_ethdev.c
>>b/drivers/net/qede/qede_ethdev.c
>> index ee8fb43..10abb8b 100644
>> --- a/drivers/net/qede/qede_ethdev.c
>> +++ b/drivers/net/qede/qede_ethdev.c
>> @@ -976,10 +976,7 @@ static int qede_dev_configure(struct rte_eth_dev
>>*eth_dev)
>> dev_info->max_rx_queues = (uint16_t)QEDE_MAX_RSS_CNT(qdev);
>> dev_info->max_tx_queues = dev_info->max_rx_queues;
>> dev_info->max_mac_addrs = qdev->dev_info.num_mac_addrs;
>> - if (IS_VF(edev))
>> - dev_info->max_vfs = 0;
>> - else
>> - dev_info->max_vfs = (uint16_t)NUM_OF_VFS(&qdev->edev);
>> + dev_info->max_vfs = 0;
>> dev_info->reta_size = ECORE_RSS_IND_TABLE_SIZE;
>> dev_info->hash_key_size = ECORE_RSS_KEY_SIZE * sizeof(uint32_t);
>> dev_info->flow_type_rss_offloads = (uint64_t)QEDE_RSS_OFFLOAD_ALL;
>>
>
>
^ permalink raw reply
* Re: [PATCH 2/7] net/qede: refactor filtering code
From: Harish Patil @ 2016-12-12 17:36 UTC (permalink / raw)
To: Ferruh Yigit, Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev
In-Reply-To: <f114b64c-0a63-736a-98a6-b8cae747f21a@intel.com>
>On 12/3/2016 2:43 AM, Harish Patil wrote:
>> The filter_config in qed_eth_ops_pass is a wrapper call driving all the
>> filtering configuration. This requires defining multiple structures and
>> passing different function arguments for each filter type which is
>> unnecessary. So as part of this refactoring we remove filter_config from
>> qed_eth_ops_pass and invoke base apis directly. Another change is to
>> use a singly list for unicast/multicast macs and thereby prevent
>>duplicate
>
>singly linked list?
Yes. Two lists to track unicast and multicast mac entries:
+ SLIST_HEAD(mc_list_head, qede_mcast_entry) mc_list_head;
+ SLIST_HEAD(uc_list_head, qede_ucast_entry) uc_list_head;
>
>> entries.
>>
>> This change is primarily intended to support future tunneling support
>> which makes use of existing L2 filtering/classifications.
>>
>> Fixes: 2ea6f76a ("qede: add core driver")
>
>What is fixed in this patch, isn't it a refactor?
The fix part is to make use of the newly added lists and prevent duplicate
mac filters.
Before that there were no checks. Other than that its refactoring to
mainly invoke direct base APIs.
>
>btw, all Fixes formats are wrong in the patchset, can you please use the
>git alias provided:
>http://dpdk.org/doc/guides/contributing/patches.html#commit-messages-body
>
>>
>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>> ---
><...>
>
^ permalink raw reply
* Re: [PATCH v12 0/6] add Tx preparation
From: Ananyev, Konstantin @ 2016-12-12 17:29 UTC (permalink / raw)
To: Yong Wang, Yigit, Ferruh, Thomas Monjalon
Cc: Harish Patil, dev@dpdk.org, Rahul Lakkireddy, Stephen Hurd,
Jan Medala, Jakub Palider, John Daley, Adrien Mazarguil,
Alejandro Lucero, Rasesh Mody, Jacob, Jerin, Yuanhan Liu,
Kulasek, TomaszX, olivier.matz@6wind.com
In-Reply-To: <BY2PR05MB2359405F47AFEB13EE708D91AF840@BY2PR05MB2359.namprd05.prod.outlook.com>
> > > This means vmxnet3 PMD also should be updated, right?
> >
> > Yes, that's right.
> >
> > >Should that update
> > > be part of tx_prep patchset? Or separate patch?
> >
> > Another question I suppose is who will do the actual patch for vmxnet3.
> > Yong, are you ok to do the patch for vmxnet3, or prefer us to do that?
> > Please note, that in both cases will need your help in testing/reviewing it.
> > Konstantin
>
> It will be great if you can put together a patch as part of the entire patchset on tx_prep() for vmxnet3 and I will definitely help review
> it.
Ok.
>
> Regarding testing, I can definitely help but I don't have a testing harness to cover the entire matrix (different ESX version, different
> vmxnet3 device version, VM-VM, VM-physical over different uplinks, etc.) so it will be limited. Related to this, I have the impression
> that Intel has some existing coverage for vmxnet3 as well as other NICs. Do we know if that will cover this use case as well?
I'll ask our validation team, but I don't know off-hand what coverage for vmxnet3 we have.
Konstantin
>
> > >
> > > >>>
> > > >>
> > > >>>>> This is for any TX offload for which the upper layer SW would have
> > > >>
> > > >>>>> to modify the contents of the packet.
> > > >>
> > > >>>>> Though as I can see for qede neither PKT_TX_IP_CKSUM or
> > > >>
> > > >>>> PKT_TX_TCP_CKSUM
> > > >>
> > > >>>>> exhibits any extra requirements for the user.
> > > >>
> > > >>>>> Is that correct?
> > > >>
> > > >>
> > > >
^ permalink raw reply
* Re: [PATCH 1/7] net/qede: reduce noise in debug logs
From: Harish Patil @ 2016-12-12 17:15 UTC (permalink / raw)
To: Ferruh Yigit, Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev, Mody, Rasesh
In-Reply-To: <91ac9846-530c-2dd3-4bd6-2c3b9143405b@intel.com>
Hi Ferruh,
>On 12/3/2016 2:43 AM, Harish Patil wrote:
>> From: Rasesh Mody <Rasesh.Mody@cavium.com>
>>
>> Replace CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER with
>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL which is a 32-bit bitmapped value
>> where each bit represent a particular submodule to debug. Also move
>> notice messages under CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO.
>>
>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>> Signed-off-by: Rasesh Mody <Rasesh.Mody@cavium.com>
>> ---
>> config/common_base | 2 +-
>> doc/guides/nics/qede.rst | 4 ++--
>> drivers/net/qede/qede_ethdev.c | 4 ++--
>> drivers/net/qede/qede_logs.h | 21 +++++----------------
>> 4 files changed, 10 insertions(+), 21 deletions(-)
>>
>> diff --git a/config/common_base b/config/common_base
>> index 4bff83a..2ffd557 100644
>> --- a/config/common_base
>> +++ b/config/common_base
>> @@ -320,7 +320,7 @@ CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
>> CONFIG_RTE_LIBRTE_QEDE_PMD=y
>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INIT=n
>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_INFO=n
>> -CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER=n
>> +CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL=0
>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX=n
>> CONFIG_RTE_LIBRTE_QEDE_DEBUG_RX=n
>> #Provides abs path/name of the firmware file.
>> diff --git a/doc/guides/nics/qede.rst b/doc/guides/nics/qede.rst
>> index d22ecdd..ddf4248 100644
>> --- a/doc/guides/nics/qede.rst
>> +++ b/doc/guides/nics/qede.rst
>> @@ -103,9 +103,9 @@ enabling debugging options may affect system
>>performance.
>>
>> Toggle display of generic debugging messages.
>>
>> -- ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_DRIVER`` (default **n**)
>> +- ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL`` (default **0**)
>
>Does it make sense to document how DEBUG_VAL used?
>
>Also commit log says bitmapped value to enable/disable a particular
>submodule, you may want to document here which value enable/disable
>which submodule.
>
>>
>> - Toggle display of ecore related messages.
>> + Control driver debug verbosity using 32-bit bitmap flags.
>>
>> - ``CONFIG_RTE_LIBRTE_QEDE_DEBUG_TX`` (default **n**)
>>
Not really, I think that would be too much. But if you think it really
helps then perhaps yes we can document.
Otherwise it is just for internal debugging.
>
><...>
>
>> diff --git a/drivers/net/qede/qede_logs.h b/drivers/net/qede/qede_logs.h
>> index 45c4af0..08fdf04 100644
>> --- a/drivers/net/qede/qede_logs.h
>> +++ b/drivers/net/qede/qede_logs.h
>> @@ -16,15 +16,18 @@
>> (p_dev)->name ? (p_dev)->name : "", \
>> ##__VA_ARGS__)
>>
>> +#ifdef RTE_LIBRTE_QEDE_DEBUG_INFO
>
>Is "_INFO" carries any meaning in this config option, why not just
>RTE_LIBRTE_QEDE_DEBUG?
INFO is used to mean just informational type of messages.
If you think it doesn’t make sense then I can rename it.
>
>> #define DP_NOTICE(p_dev, is_assert, fmt, ...) \
>> rte_log(RTE_LOG_NOTICE, RTE_LOGTYPE_PMD,\
>> "[QEDE PMD: (%s)]%s:" fmt, \
>> (p_dev)->name ? (p_dev)->name : "", \
>> __func__, \
>> ##__VA_ARGS__)
>> +#else
>> +#define DP_NOTICE(p_dev, fmt, ...) do { } while (0)
>> +#endif
>>
>> #ifdef RTE_LIBRTE_QEDE_DEBUG_INFO
>> -
>> #define DP_INFO(p_dev, fmt, ...) \
>> rte_log(RTE_LOG_INFO, RTE_LOGTYPE_PMD, \
>> "[%s:%d(%s)]" fmt, \
>> @@ -33,10 +36,8 @@
>> ##__VA_ARGS__)
>> #else
>> #define DP_INFO(p_dev, fmt, ...) do { } while (0)
>> -
>> #endif
>>
>> -#ifdef RTE_LIBRTE_QEDE_DEBUG_DRIVER
>
>Are you sure you want to enable DP_VERBOSE, I guess most verbose log
>macro, by default? Perhaps may want to control it via
>RTE_LIBRTE_QEDE_DEBUG_INFO?
DP_VERBOSE is enabled but it has a check:
if ((p_dev)->dp_module & module)
which controls what to print.
Here dp_module is controlled by CONFIG_RTE_LIBRTE_QEDE_DEBUG_VAL flag.
Hope it is clear.
>
>> #define DP_VERBOSE(p_dev, module, fmt, ...) \
>> do { \
>> if ((p_dev)->dp_module & module) \
>> @@ -46,9 +47,7 @@
>> (p_dev)->name ? (p_dev)->name : "", \
>> ##__VA_ARGS__); \
>> } while (0)
>> -#else
>> -#define DP_VERBOSE(p_dev, fmt, ...) do { } while (0)
>> -#endif
>> +
>>
><...>
>
>
^ permalink raw reply
* Re: [PATCH] vhost: allow for many vhost user ports
From: Jan Wickbom @ 2016-12-12 16:55 UTC (permalink / raw)
To: Yuanhan Liu; +Cc: dev@dpdk.org, Patrik Andersson R
In-Reply-To: <20161208055041.GO31182@yliu-dev.sh.intel.com>
> -----Original Message-----
> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> Sent: den 8 december 2016 06:51
> To: Jan Wickbom <jan.wickbom@ericsson.com>
> Cc: dev@dpdk.org; Patrik Andersson R <patrik.r.andersson@ericsson.com>
> Subject: Re: [PATCH] vhost: allow for many vhost user ports
>
> On Wed, Dec 07, 2016 at 01:23:48PM +0000, Jan Wickbom wrote:
> > > On Thu, Dec 01, 2016 at 04:26:50PM +0100, Jan Wickbom wrote:
> > > > static int
> > > > -fdset_fill(fd_set *rfset, fd_set *wfset, struct fdset *pfdset)
> > > > +fdset_fill(struct pollfd *rwfds, struct fdset *pfdset)
> ...
> > > > + rwfds[i].fd = pfdentry->fd;
> > > > + rwfds[i].events = pfdentry->rcb ? POLLIN : 0;
> > > > + rwfds[i].events |= pfdentry->wcb ? POLLOUT :
> > > 0;
> > >
> > > Another thing is we don't have to re-init this rwfds array again
> > > and again. Instead, we could
> > >
> > > - set it up correctly when fdset_add is invoked: set the fd and
> > > events.
> > >
> > > - reset revents when it's been handled at fdset_event_dispatch().
> > >
> > > - swap with the last one and shrink the array on fd delete
> > >
> > > Could you make a follow up patch for that?
> >
> > I don't see how that could easily be done. The loop index, i, is a direct
> reference between
> > an entry in the rwfds array and an entry in the pfdset array. It should stay
> like that while we are
> > hanging in the poll(). If an entry in the pfdset array is removed while we
> are hanging in the poll()
> > and we then immediately replaces it with the last entry in the array we will
> end up in trouble if the
> > revent gets set for the "replaced" index. The direct reference is gone.
> > Or am I missing something?
>
> Yes, we should not shrink the rwfds during the poll, but we could later, at
> the end of the while() loop.
Did something in v3, please have a look.
>
> Talking about that, you should not invoke fdset_shrink() inside fdset_del(),
> since it could be in the poll stage.
Thanks! Forgot this! Will send a v4
>
> --yliu
^ permalink raw reply
* [PATCH v3] vhost: allow for many vhost user ports
From: Jan Wickbom @ 2016-12-12 16:50 UTC (permalink / raw)
To: yuanhan.liu; +Cc: dev, patrik.r.andersson, Jan Wickbom
In-Reply-To: <1480606010-6132-1-git-send-email-jan.wickbom@ericsson.com>
Currently select() is used to monitor file descriptors for vhostuser
ports. This limits the number of ports possible to create since the
fd number is used as index in the fd_set and we have seen fds > 1023.
This patch changes select() to poll(). This way we can keep an
packed (pollfd) array for the fds, e.g. as many fds as the size of
the array.
Also see:
http://dpdk.org/ml/archives/dev/2016-April/037024.html
Signed-off-by: Jan Wickbom <jan.wickbom@ericsson.com>
Reported-by: Patrik Andersson <patrik.r.andersson@ericsson.com>
---
v3:
* removed unnecessary include
* removed fdset_fill, made it functionally part of poll loop
v2:
* removed unnecessary casts
* static array replacing allocated memory
lib/librte_vhost/fd_man.c | 194 +++++++++++++++++++++++++---------------------
lib/librte_vhost/fd_man.h | 2 +-
2 files changed, 105 insertions(+), 91 deletions(-)
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index 2d3eeb7..c360d07 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -35,16 +35,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
-#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <poll.h>
#include <unistd.h>
+#include <string.h>
#include <rte_common.h>
#include <rte_log.h>
#include "fd_man.h"
+#define FDPOLLERR (POLLERR | POLLHUP | POLLNVAL)
+
+
+static struct pollfd rwfds[MAX_FDS];
+
+/**
+ * Adjusts the highest index populated in the array of fds
+ * @return
+ * The new size of fdset.
+ */
+static void
+fdset_shrink(struct fdset *pfdset)
+{
+ int idx;
+
+ for (idx = pfdset->num - 1;
+ idx >= 0 && pfdset->fd[idx].fd == -1;
+ idx--)
+ ;
+
+ pfdset->num = idx + 1;
+}
+
/**
* Returns the index in the fdset for a given fd.
* If fd is -1, it means to search for a free entry.
@@ -56,72 +80,32 @@
{
int i;
- if (pfdset == NULL)
- return -1;
-
- for (i = 0; i < MAX_FDS && pfdset->fd[i].fd != fd; i++)
+ for (i = 0; i < pfdset->num && pfdset->fd[i].fd != fd; i++)
;
- return i == MAX_FDS ? -1 : i;
+ return i == pfdset->num ? -1 : i;
}
static int
fdset_find_free_slot(struct fdset *pfdset)
{
- return fdset_find_fd(pfdset, -1);
+ if (pfdset->num < MAX_FDS)
+ return pfdset->num;
+ else
+ return fdset_find_fd(pfdset, -1);
}
-static int
-fdset_add_fd(struct fdset *pfdset, int idx, int fd,
+static void
+fdset_add_fd(struct fdset *pfdset, int idx, int fd,
fd_cb rcb, fd_cb wcb, void *dat)
{
struct fdentry *pfdentry;
- if (pfdset == NULL || idx >= MAX_FDS || fd >= FD_SETSIZE)
- return -1;
-
pfdentry = &pfdset->fd[idx];
pfdentry->fd = fd;
pfdentry->rcb = rcb;
pfdentry->wcb = wcb;
pfdentry->dat = dat;
-
- return 0;
-}
-
-/**
- * Fill the read/write fd_set with the fds in the fdset.
- * @return
- * the maximum fds filled in the read/write fd_set.
- */
-static int
-fdset_fill(fd_set *rfset, fd_set *wfset, struct fdset *pfdset)
-{
- struct fdentry *pfdentry;
- int i, maxfds = -1;
- int num = MAX_FDS;
-
- if (pfdset == NULL)
- return -1;
-
- for (i = 0; i < num; i++) {
- pfdentry = &pfdset->fd[i];
- if (pfdentry->fd != -1) {
- int added = 0;
- if (pfdentry->rcb && rfset) {
- FD_SET(pfdentry->fd, rfset);
- added = 1;
- }
- if (pfdentry->wcb && wfset) {
- FD_SET(pfdentry->fd, wfset);
- added = 1;
- }
- if (added)
- maxfds = pfdentry->fd < maxfds ?
- maxfds : pfdentry->fd;
- }
- }
- return maxfds;
}
void
@@ -132,6 +116,8 @@
if (pfdset == NULL)
return;
+ pthread_mutex_init(&pfdset->fd_mutex, NULL);
+
for (i = 0; i < MAX_FDS; i++) {
pfdset->fd[i].fd = -1;
pfdset->fd[i].dat = NULL;
@@ -152,14 +138,15 @@
pthread_mutex_lock(&pfdset->fd_mutex);
- /* Find a free slot in the list. */
i = fdset_find_free_slot(pfdset);
- if (i == -1 || fdset_add_fd(pfdset, i, fd, rcb, wcb, dat) < 0) {
+ if (i == -1) {
pthread_mutex_unlock(&pfdset->fd_mutex);
return -2;
}
- pfdset->num++;
+ fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
+ if (i == pfdset->num)
+ pfdset->num++;
pthread_mutex_unlock(&pfdset->fd_mutex);
@@ -189,7 +176,7 @@
pfdset->fd[i].fd = -1;
pfdset->fd[i].rcb = pfdset->fd[i].wcb = NULL;
pfdset->fd[i].dat = NULL;
- pfdset->num--;
+ fdset_shrink(pfdset);
i = -1;
}
pthread_mutex_unlock(&pfdset->fd_mutex);
@@ -198,25 +185,26 @@
return dat;
}
+
/**
- * Unregister the fd at the specified slot from the fdset.
+ * Moves the fd from last slot to specified slot, including
+ * corresponding pollfd
*/
static void
-fdset_del_slot(struct fdset *pfdset, int index)
+fdset_move_last(struct fdset *pfdset, int idx)
{
- if (pfdset == NULL || index < 0 || index >= MAX_FDS)
- return;
-
- pthread_mutex_lock(&pfdset->fd_mutex);
+ int last_idx = pfdset->num - 1;
- pfdset->fd[index].fd = -1;
- pfdset->fd[index].rcb = pfdset->fd[index].wcb = NULL;
- pfdset->fd[index].dat = NULL;
- pfdset->num--;
+ if (idx < last_idx) {
+ pfdset->fd[idx] = pfdset->fd[last_idx];
+ pfdset->fd[last_idx].fd = -1;
- pthread_mutex_unlock(&pfdset->fd_mutex);
+ rwfds[idx] = rwfds[last_idx];
+ rwfds[last_idx].revents = 0;
+ }
}
+
/**
* This functions runs in infinite blocking loop until there is no fd in
* pfdset. It calls corresponding r/w handler if there is event on the fd.
@@ -229,55 +217,71 @@
void
fdset_event_dispatch(struct fdset *pfdset)
{
- fd_set rfds, wfds;
- int i, maxfds;
+ int i;
struct fdentry *pfdentry;
- int num = MAX_FDS;
fd_cb rcb, wcb;
void *dat;
int fd;
int remove1, remove2;
- int ret;
if (pfdset == NULL)
return;
- while (1) {
- struct timeval tv;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- pthread_mutex_lock(&pfdset->fd_mutex);
-
- maxfds = fdset_fill(&rfds, &wfds, pfdset);
-
- pthread_mutex_unlock(&pfdset->fd_mutex);
+ memset(rwfds, 0, sizeof(rwfds));
+ while (1) {
/*
- * When select is blocked, other threads might unregister
+ * When poll is blocked, other threads might unregister
* listenfds from and register new listenfds into fdset.
- * When select returns, the entries for listenfds in the fdset
+ * When poll returns, the entries for listenfds in the fdset
* might have been updated. It is ok if there is unwanted call
* for new listenfds.
*/
- ret = select(maxfds + 1, &rfds, &wfds, NULL, &tv);
- if (ret <= 0)
- continue;
+ poll(rwfds, pfdset->num, 1000 /* millisecs */);
- for (i = 0; i < num; i++) {
- remove1 = remove2 = 0;
+ for (i = 0; i < pfdset->num; ) {
pthread_mutex_lock(&pfdset->fd_mutex);
+
pfdentry = &pfdset->fd[i];
fd = pfdentry->fd;
+
+ if (fd < 0) {
+ /* Removed during poll */
+
+ fdset_move_last(pfdset, i);
+ fdset_shrink(pfdset);
+
+ pthread_mutex_unlock(&pfdset->fd_mutex);
+
+ continue;
+ }
+
+ if (!rwfds[i].revents) {
+ /* No revents, maybe added during poll */
+
+ rwfds[i].fd = fd;
+ rwfds[i].events = pfdentry->rcb ? POLLIN : 0;
+ rwfds[i].events |= pfdentry->wcb ? POLLOUT : 0;
+ pthread_mutex_unlock(&pfdset->fd_mutex);
+
+ i++;
+ continue;
+ }
+
+ /* Valid fd, and at least one revent ... */
+
+ remove1 = remove2 = 0;
+
rcb = pfdentry->rcb;
wcb = pfdentry->wcb;
dat = pfdentry->dat;
pfdentry->busy = 1;
+
pthread_mutex_unlock(&pfdset->fd_mutex);
- if (fd >= 0 && FD_ISSET(fd, &rfds) && rcb)
+
+ if (rcb && rwfds[i].revents & (POLLIN | FDPOLLERR))
rcb(fd, dat, &remove1);
- if (fd >= 0 && FD_ISSET(fd, &wfds) && wcb)
+ if (wcb && rwfds[i].revents & (POLLOUT | FDPOLLERR))
wcb(fd, dat, &remove2);
pfdentry->busy = 0;
/*
@@ -292,8 +296,18 @@
* listen fd in another thread, we couldn't call
* fd_set_del.
*/
- if (remove1 || remove2)
- fdset_del_slot(pfdset, i);
+ if (remove1 || remove2) {
+ pthread_mutex_lock(&pfdset->fd_mutex);
+
+ fdset_move_last(pfdset, i);
+ fdset_shrink(pfdset);
+
+ pthread_mutex_unlock(&pfdset->fd_mutex);
+
+ continue;
+ }
+
+ i++;
}
}
}
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index bd66ed1..b5ba688 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -51,7 +51,7 @@ struct fdentry {
struct fdset {
struct fdentry fd[MAX_FDS];
pthread_mutex_t fd_mutex;
- int num; /* current fd number of this fdset */
+ int num; /* highest index occupied in fd array + 1 */
};
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v3 6/9] examples/ethtool: use ixgbe public function
From: Ferruh Yigit @ 2016-12-12 16:25 UTC (permalink / raw)
To: Bernard Iremonger, thomas.monjalon, dev
In-Reply-To: <1481550626-14539-7-git-send-email-bernard.iremonger@intel.com>
On 12/12/2016 1:50 PM, Bernard Iremonger wrote:
> Replace rte_eth_dev_set_vf_rxmode with rte_pmd_ixgbe_set_vf_rx_mode.
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
> examples/ethtool/lib/rte_ethtool.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
> index a1f91d4..0e539f7 100644
> --- a/examples/ethtool/lib/rte_ethtool.c
> +++ b/examples/ethtool/lib/rte_ethtool.c
> @@ -1,7 +1,7 @@
> /*-
> * BSD LICENSE
> *
> - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
> * All rights reserved.
> *
> * Redistribution and use in source and binary forms, with or without
> @@ -36,6 +36,7 @@
> #include <rte_version.h>
> #include <rte_ethdev.h>
> #include <rte_ether.h>
> +#include <rte_pmd_ixgbe.h>
> #include "rte_ethtool.h"
>
> #define PKTPOOL_SIZE 512
> @@ -354,7 +355,7 @@ rte_ethtool_net_set_rx_mode(uint8_t port_id)
>
> /* Set VF vf_rx_mode, VF unsupport status is discard */
> for (vf = 0; vf < num_vfs; vf++)
> - rte_eth_dev_set_vf_rxmode(port_id, vf,
> + rte_pmd_ixgbe_set_vf_rxmode(port_id, vf,
Will these cause a build error if IXGBE_PMD is not enabled?
> ETH_VMDQ_ACCEPT_UNTAG, 0);
>
> /* Enable Rx vlan filter, VF unspport status is discard */
>
^ permalink raw reply
* Re: [PATCH v3 9/9] doc: update release notes
From: Ferruh Yigit @ 2016-12-12 16:07 UTC (permalink / raw)
To: Iremonger, Bernard, thomas.monjalon@6wind.com, dev@dpdk.org
In-Reply-To: <8CEF83825BEC744B83065625E567D7C224D06914@IRSMSX108.ger.corp.intel.com>
On 12/12/2016 3:55 PM, Iremonger, Bernard wrote:
> Hi Ferruh,
>
>
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Monday, December 12, 2016 3:52 PM
>> To: Iremonger, Bernard <bernard.iremonger@intel.com>;
>> thomas.monjalon@6wind.com; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH v3 9/9] doc: update release notes
>>
>> Hi Bernard,
>>
>> On 12/12/2016 1:50 PM, Bernard Iremonger wrote:
>>> Add release note for removing set VF API's from the ethdev, renaming
>>> the API's and moving them to the ixgbe PMD.
>>
>> Sorry, my bad, I wasn't clear enough.
>>
>> I was thinking about updating "Shared Library Versions" section of the
>> release notes, and increasing the librte_ethdev.so version (from 5 to 6) I
>> believe new feature section does not require an update.
>>
>> If you don't mind I can update library version with previous patch, and you
>> don't need to send a new version of the patch. Please let me know.
>
> Yes, that's fine with me.
It seems already increased for this release, by another patch, so no
change required there.
I will move your release notes changes to "API Changes" section.
>
>
>>>
>>> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
>>> ---
>>> doc/guides/rel_notes/release_17_02.rst | 20 ++++++++++++++++++++
>>> 1 file changed, 20 insertions(+)
>>>
>>> diff --git a/doc/guides/rel_notes/release_17_02.rst
>>> b/doc/guides/rel_notes/release_17_02.rst
>>> index 3b65038..d30b258 100644
>>> --- a/doc/guides/rel_notes/release_17_02.rst
>>> +++ b/doc/guides/rel_notes/release_17_02.rst
>>> @@ -38,6 +38,26 @@ New Features
>>> Also, make sure to start the actual text at the margin.
>>>
>> =========================================================
>>>
>>> +* **Moved five APIs for VF management from the ethdev to the ixgbe
>>> +PMD.**
>>> +
>>> + The following five APIs for VF management from the PF have been
>>> + removed from the ethdev, renamed and added to the ixgbe PMD::
>>> +
>>> + rte_eth_dev_set_vf_rate_limit
>>> + rte_eth_dev_set_vf_rx
>>> + rte_eth_dev_set_vf_rxmode
>>> + rte_eth_dev_set_vf_tx
>>> + rte_eth_dev_set_vf_vlan_filter
>>> +
>>> + The API's have been renamed to the following::
>>> +
>>> + rte_pmd_ixgbe_set_vf_rate_limit
>>> + rte_pmd_ixgbe_set_vf_rx
>>> + rte_pmd_ixgbe_set_vf_rxmode
>>> + rte_pmd_ixgbe_set_vf_tx
>>> + rte_pmd_ixgbe_set_vf_vlan_filter
>>> +
>>> + The declarations for the API’s can be found in ``rte_pmd_ixgbe.h``.
>>>
>>> Resolved Issues
>>> ---------------
>>>
> Regards,
>
> Bernard.
>
^ permalink raw reply
* Re: [PATCH v3 9/9] doc: update release notes
From: Iremonger, Bernard @ 2016-12-12 15:55 UTC (permalink / raw)
To: Yigit, Ferruh, thomas.monjalon@6wind.com, dev@dpdk.org
In-Reply-To: <9eab7091-fc0a-cc12-3588-64df429cd3b0@intel.com>
Hi Ferruh,
> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Monday, December 12, 2016 3:52 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>;
> thomas.monjalon@6wind.com; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 9/9] doc: update release notes
>
> Hi Bernard,
>
> On 12/12/2016 1:50 PM, Bernard Iremonger wrote:
> > Add release note for removing set VF API's from the ethdev, renaming
> > the API's and moving them to the ixgbe PMD.
>
> Sorry, my bad, I wasn't clear enough.
>
> I was thinking about updating "Shared Library Versions" section of the
> release notes, and increasing the librte_ethdev.so version (from 5 to 6) I
> believe new feature section does not require an update.
>
> If you don't mind I can update library version with previous patch, and you
> don't need to send a new version of the patch. Please let me know.
Yes, that's fine with me.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> > doc/guides/rel_notes/release_17_02.rst | 20 ++++++++++++++++++++
> > 1 file changed, 20 insertions(+)
> >
> > diff --git a/doc/guides/rel_notes/release_17_02.rst
> > b/doc/guides/rel_notes/release_17_02.rst
> > index 3b65038..d30b258 100644
> > --- a/doc/guides/rel_notes/release_17_02.rst
> > +++ b/doc/guides/rel_notes/release_17_02.rst
> > @@ -38,6 +38,26 @@ New Features
> > Also, make sure to start the actual text at the margin.
> >
> =========================================================
> >
> > +* **Moved five APIs for VF management from the ethdev to the ixgbe
> > +PMD.**
> > +
> > + The following five APIs for VF management from the PF have been
> > + removed from the ethdev, renamed and added to the ixgbe PMD::
> > +
> > + rte_eth_dev_set_vf_rate_limit
> > + rte_eth_dev_set_vf_rx
> > + rte_eth_dev_set_vf_rxmode
> > + rte_eth_dev_set_vf_tx
> > + rte_eth_dev_set_vf_vlan_filter
> > +
> > + The API's have been renamed to the following::
> > +
> > + rte_pmd_ixgbe_set_vf_rate_limit
> > + rte_pmd_ixgbe_set_vf_rx
> > + rte_pmd_ixgbe_set_vf_rxmode
> > + rte_pmd_ixgbe_set_vf_tx
> > + rte_pmd_ixgbe_set_vf_vlan_filter
> > +
> > + The declarations for the API’s can be found in ``rte_pmd_ixgbe.h``.
> >
> > Resolved Issues
> > ---------------
> >
Regards,
Bernard.
^ permalink raw reply
* Re: [PATCH v3 9/9] doc: update release notes
From: Ferruh Yigit @ 2016-12-12 15:51 UTC (permalink / raw)
To: Bernard Iremonger, thomas.monjalon, dev
In-Reply-To: <1481550626-14539-10-git-send-email-bernard.iremonger@intel.com>
Hi Bernard,
On 12/12/2016 1:50 PM, Bernard Iremonger wrote:
> Add release note for removing set VF API's from the ethdev,
> renaming the API's and moving them to the ixgbe PMD.
Sorry, my bad, I wasn't clear enough.
I was thinking about updating "Shared Library Versions" section of the
release notes, and increasing the librte_ethdev.so version (from 5 to 6)
I believe new feature section does not require an update.
If you don't mind I can update library version with previous patch, and
you don't need to send a new version of the patch. Please let me know.
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
> doc/guides/rel_notes/release_17_02.rst | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
> index 3b65038..d30b258 100644
> --- a/doc/guides/rel_notes/release_17_02.rst
> +++ b/doc/guides/rel_notes/release_17_02.rst
> @@ -38,6 +38,26 @@ New Features
> Also, make sure to start the actual text at the margin.
> =========================================================
>
> +* **Moved five APIs for VF management from the ethdev to the ixgbe PMD.**
> +
> + The following five APIs for VF management from the PF have been removed from the ethdev,
> + renamed and added to the ixgbe PMD::
> +
> + rte_eth_dev_set_vf_rate_limit
> + rte_eth_dev_set_vf_rx
> + rte_eth_dev_set_vf_rxmode
> + rte_eth_dev_set_vf_tx
> + rte_eth_dev_set_vf_vlan_filter
> +
> + The API's have been renamed to the following::
> +
> + rte_pmd_ixgbe_set_vf_rate_limit
> + rte_pmd_ixgbe_set_vf_rx
> + rte_pmd_ixgbe_set_vf_rxmode
> + rte_pmd_ixgbe_set_vf_tx
> + rte_pmd_ixgbe_set_vf_vlan_filter
> +
> + The declarations for the API’s can be found in ``rte_pmd_ixgbe.h``.
>
> Resolved Issues
> ---------------
>
^ permalink raw reply
* Re: [PATCH v12 0/6] add Tx preparation
From: Ananyev, Konstantin @ 2016-12-12 15:02 UTC (permalink / raw)
To: Jan Medala, Yigit, Ferruh
Cc: Thomas Monjalon, Harish Patil, dev@dpdk.org, Rahul Lakkireddy,
Stephen Hurd, Jakub Palider, John Daley, Adrien Mazarguil,
Alejandro Lucero, Rasesh Mody, Jacob, Jerin, Yuanhan Liu,
Kulasek, TomaszX, olivier.matz@6wind.com, Yong Wang
In-Reply-To: <CANw_3ZdK2HUZC3K6LLB2QtD3AmKvjtObRDPwjZS0g5rHTEpcBQ@mail.gmail.com>
Hi Jan,
>Hello,
>Sorry for late response.
>From ENA perspective, we need to dig deeper about the requirements and use cases, but I'm pretty confident (95%) that ena will need to implement tx_prep() API. There is at least one >scenario, when HW relay on partial checksum.
Could you let us know as soon as you'll figure it out.
Hopefully will still be able to hit into 17.02 integration deadline.
Thanks
Konstantin
^ permalink raw reply
* Re: [dpdk-dev, 1/8] drivers/common/dpaa2: Run time assembler for Descriptor formation
From: Neil Horman @ 2016-12-12 14:59 UTC (permalink / raw)
To: Akhil Goyal
Cc: dev, thomas.monjalon, eclan.doherty, pablo.de.lara.guarch,
hemant.agrawal, Horia Geanta Neag
In-Reply-To: <20161205125540.6419-2-akhil.goyal@nxp.com>
On Mon, Dec 05, 2016 at 06:25:33PM +0530, Akhil Goyal wrote:
> FLib is a library which helps in making the descriptors which
> is understood by NXP's SEC hardware.
> This patch provides header files for command words which can be used
> for descritptor formation.
>
> Signed-off-by: Horia Geanta Neag <horia.geanta@nxp.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
> ---
> drivers/common/dpaa2/flib/README | 43 +
> drivers/common/dpaa2/flib/compat.h | 186 +++++
> drivers/common/dpaa2/flib/rta.h | 918 +++++++++++++++++++++
> .../common/dpaa2/flib/rta/fifo_load_store_cmd.h | 308 +++++++
> drivers/common/dpaa2/flib/rta/header_cmd.h | 213 +++++
> drivers/common/dpaa2/flib/rta/jump_cmd.h | 172 ++++
> drivers/common/dpaa2/flib/rta/key_cmd.h | 187 +++++
> drivers/common/dpaa2/flib/rta/load_cmd.h | 301 +++++++
> drivers/common/dpaa2/flib/rta/math_cmd.h | 366 ++++++++
> drivers/common/dpaa2/flib/rta/move_cmd.h | 405 +++++++++
> drivers/common/dpaa2/flib/rta/nfifo_cmd.h | 161 ++++
> drivers/common/dpaa2/flib/rta/operation_cmd.h | 549 ++++++++++++
> drivers/common/dpaa2/flib/rta/protocol_cmd.h | 680 +++++++++++++++
> drivers/common/dpaa2/flib/rta/sec_run_time_asm.h | 767 +++++++++++++++++
> drivers/common/dpaa2/flib/rta/seq_in_out_ptr_cmd.h | 172 ++++
> drivers/common/dpaa2/flib/rta/signature_cmd.h | 40 +
> drivers/common/dpaa2/flib/rta/store_cmd.h | 149 ++++
> 17 files changed, 5617 insertions(+)
> create mode 100644 drivers/common/dpaa2/flib/README
> create mode 100644 drivers/common/dpaa2/flib/compat.h
> create mode 100644 drivers/common/dpaa2/flib/rta.h
> create mode 100644 drivers/common/dpaa2/flib/rta/fifo_load_store_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/header_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/jump_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/key_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/load_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/math_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/move_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/nfifo_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/operation_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/protocol_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/sec_run_time_asm.h
> create mode 100644 drivers/common/dpaa2/flib/rta/seq_in_out_ptr_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/signature_cmd.h
> create mode 100644 drivers/common/dpaa2/flib/rta/store_cmd.h
>
> diff --git a/drivers/common/dpaa2/flib/README b/drivers/common/dpaa2/flib/README
> new file mode 100644
> index 0000000..a8b3358
> --- /dev/null
> +++ b/drivers/common/dpaa2/flib/README
> @@ -0,0 +1,43 @@
> +Copyright 2008-2013 Freescale Semiconductor, Inc.
> +
> +Runtime Assembler provides an easy and flexible runtime method for writing
> +SEC descriptors.
> +
> +1. What's supported
> +===================
> +1.1 Initialization/verification code for descriptor buffer.
> +1.2 Configuration/verification code for SEC commands:
> + FIFOLOAD and SEQFIFOLOAD;
> + FIFOSTORE and SEQFIFOSTORE;
> + SHARED HEADER and JOB HEADER;
> + JUMP;
> + KEY;
> + LOAD and SEQLOAD;
> + MATH;
> + MOVE and MOVELEN;
> + NFIFO - pseudo command (shortcut for writing FIFO entries using LOAD command);
> + PKA OPERATION and ALGORITHM OPERATION;
> + PROTOCOL;
> + SEQ IN PTR and SEQ OUT PTR;
> + SIGNATURE;
> + STORE and SEQSTORE.
> +1.3 Support for referential code:
> + patching routines for LOAD, MOVE, JUMP and HEADER commands.
> + raw patching (i.e. patch any 4-byte word from descriptor)
> +1.4 Support for extended (32/36/40-bit) pointer size.
> +1.5 SEC Eras 1-6
> + Below is a non-exhaustive list of platforms:
> + Era 1 - P4080R1
> + Era 2 - P4080R2
> + Era 3 - P1010, P1023, P3041, P5020
> + Era 4 - BSC9131, BSC9132, P4080R3
> + Era 5 - P5040, B4860, T4240R1
> + Era 6 - C290, T4240R2, T1040, T2080
> +
> +2. What's not supported
> +=======================
> +2.1 SEC Eras 7 and 8.
> +
> +3. Integration
> +==============
> +To integrate this tool into your project, rta.h file must be included.
> diff --git a/drivers/common/dpaa2/flib/compat.h b/drivers/common/dpaa2/flib/compat.h
> new file mode 100644
> index 0000000..bd946e1
> --- /dev/null
> +++ b/drivers/common/dpaa2/flib/compat.h
> @@ -0,0 +1,186 @@
> +/*
> + * Copyright 2013 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
> + */
> +
> +#ifndef __RTA_COMPAT_H__
> +#define __RTA_COMPAT_H__
> +
> +#include <stdint.h>
> +#include <errno.h>
> +
> +#ifdef __GLIBC__
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <stdbool.h>
> +#include <byteswap.h>
> +
> +#ifndef __BYTE_ORDER__
> +#error "Undefined endianness"
> +#endif
> +
> +/* FSL's Embedded Warrior C Library; assume AIOP or MC environment */
> +#elif defined(__EWL__) && (defined(AIOP) || defined(MC))
> +#include "common/fsl_string.h"
> +#include "common/fsl_stdlib.h"
> +#include "common/fsl_stdio.h"
> +#if defined(AIOP)
> +#include "dplib/fsl_cdma.h"
> +#endif
> +#include "fsl_dbg.h"
> +#include "fsl_endian.h"
> +#if _EWL_C99
> +#include <stdbool.h>
> +#else
> +#if !__option(c99)
> +typedef unsigned char _Bool;
> +#endif
> +#define bool _Bool
> +#define true 1
> +#define false 0
> +#define __bool_true_false_are_defined 1
> +#endif /* _EWL_C99 */
> +#else
> +#error Environment not supported!
> +#endif
> +
> +#ifndef __always_inline
> +#define __always_inline inline __attribute__((always_inline))
> +#endif
> +
> +#ifndef __always_unused
> +#define __always_unused __attribute__((unused))
> +#endif
> +
> +#ifndef __maybe_unused
> +#define __maybe_unused __attribute__((unused))
> +#endif
> +
> +#if defined(__GLIBC__) && (defined(SUPPRESS_PRINTS) || \
> + (!defined(pr_debug) && !defined(RTA_DEBUG)))
> +#ifndef __printf
> +#define __printf(a, b) __attribute__((format(printf, 1, 2)))
> +#endif
> +static inline __printf(1, 2) int no_printf(const char *fmt __always_unused, ...)
> +{
> + return 0;
> +}
> +#endif
> +
> +#if defined(__GLIBC__) && !defined(pr_debug)
> +#if !defined(SUPPRESS_PRINTS) && defined(RTA_DEBUG)
> +#define pr_debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
> +#else
> +#define pr_debug(fmt, ...) no_printf(fmt, ##__VA_ARGS__)
> +#endif
> +#endif /* pr_debug */
> +
> +#if defined(__GLIBC__) && !defined(pr_err)
> +#if !defined(SUPPRESS_PRINTS)
> +#define pr_err(fmt, ...) printf(fmt, ##__VA_ARGS__)
> +#else
> +#define pr_err(fmt, ...) no_printf(fmt, ##__VA_ARGS__)
> +#endif
> +#endif /* pr_err */
> +
> +#if defined(__GLIBC__) && !defined(pr_warning)
> +#if !defined(SUPPRESS_PRINTS)
> +#define pr_warning(fmt, ...) printf(fmt, ##__VA_ARGS__)
> +#else
> +#define pr_warning(fmt, ...) no_printf(fmt, ##__VA_ARGS__)
> +#endif
> +#endif /* pr_warning */
> +
> +#if defined(__GLIBC__) && !defined(pr_warn)
> +#define pr_warn pr_warning
> +#endif /* pr_warn */
Seems like logging should be folded into the rte logging facility, not
controlled independently, and manipulated via redefinitions of printf
> +
> +/**
> + * ARRAY_SIZE - returns the number of elements in an array
> + * @x: array
> + */
> +#ifndef ARRAY_SIZE
> +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +#endif
> +
> +#ifndef ALIGN
> +#define ALIGN(x, a) (((x) + ((__typeof__(x))(a) - 1)) & \
> + ~((__typeof__(x))(a) - 1))
> +#endif
> +
> +#ifndef BIT
> +#define BIT(nr) (1UL << (nr))
> +#endif
> +
> +#ifndef upper_32_bits
> +/**
> + * upper_32_bits - return bits 32-63 of a number
> + * @n: the number we're accessing
> + */
> +#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16))
> +#endif
> +
> +#ifndef lower_32_bits
> +/**
> + * lower_32_bits - return bits 0-31 of a number
> + * @n: the number we're accessing
> + */
> +#define lower_32_bits(n) ((uint32_t)(n))
> +#endif
> +
> +/* Use Linux naming convention */
> +#ifdef __GLIBC__
> + #define swab16(x) bswap_16(x)
> + #define swab32(x) bswap_32(x)
> + #define swab64(x) bswap_64(x)
> + /* Define cpu_to_be32 macro if not defined in the build environment */
> + #if !defined(cpu_to_be32)
> + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> + #define cpu_to_be32(x) (x)
> + #else
> + #define cpu_to_be32(x) swab32(x)
> + #endif
> + #endif
> + /* Define cpu_to_le32 macro if not defined in the build environment */
> + #if !defined(cpu_to_le32)
> + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
> + #define cpu_to_le32(x) swab32(x)
> + #else
> + #define cpu_to_le32(x) (x)
> + #endif
Definately shouldn't be redefining your own byte swapping routines here.
^ permalink raw reply
* [PATCH v12] net/tap: new TUN/TAP device PMD
From: Keith Wiles @ 2016-12-12 14:38 UTC (permalink / raw)
To: dev; +Cc: pmatilai, yuanhan.liu, ferruh.yigit, john.mcnamara
In-Reply-To: <1476396234-44694-1-git-send-email-keith.wiles@intel.com>
The PMD allows for DPDK and the host to communicate using a raw
device interface on the host and in the DPDK application. The device
created is a Tap device with a L2 packet header.
v12- Fixup minor changes for driver_name and version number
v11- Add the tap.rst to the nic/index.rst file
v10- Change the string name used to allow for multiple devices.
v9 - Fix up the docs to use correct syntax
v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
v7 - Reword the comment in common_base and fix the data->name issue
v6 - fixed the checkpatch issues
v5 - merge in changes from list review see related emails
fixed many minor edits
v4 - merge with latest driver changes
v3 - fix includes by removing ifdef for other type besides Linux
Fix the copyright notice in the Makefile
v2 - merge all of the patches into one patch
Fix a typo on naming the tap device
Update the maintainers list
Signed-off-by: Keith Wiles <keith.wiles@intel.com>
---
MAINTAINERS | 5 +
config/common_base | 9 +
config/common_linuxapp | 1 +
doc/guides/nics/index.rst | 1 +
doc/guides/nics/tap.rst | 136 ++++++
drivers/net/Makefile | 1 +
drivers/net/tap/Makefile | 57 +++
drivers/net/tap/rte_eth_tap.c | 765 ++++++++++++++++++++++++++++++++
drivers/net/tap/rte_pmd_tap_version.map | 4 +
mk/rte.app.mk | 1 +
10 files changed, 980 insertions(+)
create mode 100644 doc/guides/nics/tap.rst
create mode 100644 drivers/net/tap/Makefile
create mode 100644 drivers/net/tap/rte_eth_tap.c
create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
diff --git a/MAINTAINERS b/MAINTAINERS
index 26d9590..842fb6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,11 @@ F: doc/guides/nics/pcap_ring.rst
F: app/test/test_pmd_ring.c
F: app/test/test_pmd_ring_perf.c
+Tap PMD
+M: Keith Wiles <keith.wiles@intel.com>
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
Null Networking PMD
M: Tetsuya Mukawa <mtetsuyah@gmail.com>
F: drivers/net/null/
diff --git a/config/common_base b/config/common_base
index 652a839..eb51cdb 100644
--- a/config/common_base
+++ b/config/common_base
@@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
CONFIG_RTE_TEST_PMD=y
CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the TAP PMD
+#
+# The TAP PMD is currently only built for Linux and the
+# option is enabled by default in common_linuxapp file,
+# set to 'n' in the common_base file.
+#
+CONFIG_RTE_LIBRTE_PMD_TAP=n
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..782b503 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,4 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
CONFIG_RTE_LIBRTE_POWER=y
CONFIG_RTE_VIRTIO_USER=y
+CONFIG_RTE_LIBRTE_PMD_TAP=y
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index 92d56a5..af92529 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -51,6 +51,7 @@ Network Interface Controller Drivers
nfp
qede
szedata2
+ tap
thunderx
virtio
vhost
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 0000000..622b9e7
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,136 @@
+.. BSD LICENSE
+ Copyright(c) 2016 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS 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 COPYRIGHT
+ OWNER 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.
+
+Tun/Tap Poll Mode Driver
+========================
+
+The ``rte_eth_tap.c`` PMD creates a device using TUN/TAP interfaces on the
+local host. The PMD allows for DPDK and the host to communicate using a raw
+device interface on the host and in the DPDK application.
+
+The device created is a TAP device, which sends/receives packet in a raw
+format with a L2 header. The usage for a TAP PMD is for connectivity to the
+local host using a TAP interface. When the TAP PMD is initialized it will
+create a number of tap devices in the host accessed via ``ifconfig -a`` or
+``ip`` command. The commands can be used to assign and query the virtual like
+device.
+
+These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK
+along with being able to be used as a network connection to the DPDK
+application. The method enable one or more interfaces is to use the
+``--vdev=net_tap`` option on the DPDK application command line. Each
+``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
+and so on.
+
+The interfaced name can be changed by adding the ``iface=foo0``, for example::
+
+ --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
+
+Also the speed of the interface can be changed from 10G to whatever number
+needed, but the interface does not enforce that speed, for example::
+
+ --vdev=net_tap,iface=foo0,speed=25000
+
+After the DPDK application is started you can send and receive packets on the
+interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
+point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
+and others to communicate with the DPDK application. The DPDK application may
+not understand network protocols like IPv4/6, UDP or TCP unless the
+application has been written to understand these protocols.
+
+If you need the interface as a real network interface meaning running and has
+a valid IP address then you can do this with the following commands::
+
+ sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+ sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Please change the IP addresses as you see fit.
+
+If routing is enabled on the host you can also communicate with the DPDK App
+over the internet via a standard socket layer application as long as you
+account for the protocol handing in the application.
+
+If you have a Network Stack in your DPDK application or something like it you
+can utilize that stack to handle the network protocols. Plus you would be able
+to address the interface using an IP address assigned to the internal
+interface.
+
+Example
+-------
+
+The following is a simple example of using the TUN/TAP PMD with the Pktgen
+packet generator. It requires that the ``socat`` utility is installed on the
+test system.
+
+Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
+used to build the dpdk you pulled down.
+
+Run pktgen from the pktgen directory in a terminal with a commandline like the
+following::
+
+ sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4 \
+ --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg \
+ --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1 \
+ -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3 \
+ -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3 \
+ -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1 \
+ -f themes/black-yellow.theme
+
+.. Note:
+
+ Change the ``-b`` options to blacklist all of your physical ports. The
+ following command line is all one line.
+
+ Also, ``-f themes/black-yellow.theme`` is optional if the default colors
+ work on your system configuration. See the Pktgen docs for more
+ information.
+
+Verify with ``ifconfig -a`` command in a different xterm window, should have a
+``dtap0`` and ``dtap1`` interfaces created.
+
+Next set the links for the two interfaces to up via the commands below::
+
+ sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+ sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Then use socat to create a loopback for the two interfaces::
+
+ sudo socat interface:dtap0 interface:dtap1
+
+Then on the Pktgen command line interface you can start sending packets using
+the commands ``start 0`` and ``start 1`` or you can start both at the same
+time with ``start all``. The command ``str`` is an alias for ``start all`` and
+``stp`` is an alias for ``stop all``.
+
+While running you should see the 64 byte counters increasing to verify the
+traffic is being looped back. You can use ``set all size XXX`` to change the
+size of the packets after you stop the traffic. Use the pktgen ``help``
+command to see a list of all commands. You can also use the ``-f`` option to
+load commands at startup.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index bc93230..e366a85 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
new file mode 100644
index 0000000..e18f30c
--- /dev/null
+++ b/drivers/net/tap/Makefile
@@ -0,0 +1,57 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS 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 COPYRIGHT
+# OWNER 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.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_tap.a
+
+EXPORT_MAP := rte_pmd_tap_version.map
+
+LIBABIVER := 1
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
new file mode 100644
index 0000000..976f2d9
--- /dev/null
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -0,0 +1,765 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vdev.h>
+#include <rte_kvargs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+/* Linux based path to the TUN device */
+#define TUN_TAP_DEV_PATH "/dev/net/tun"
+#define DEFAULT_TAP_NAME "dtap"
+
+#define ETH_TAP_IFACE_ARG "iface"
+#define ETH_TAP_SPEED_ARG "speed"
+
+#define RTE_PMD_TAP_MAX_QUEUES 16
+
+static struct rte_vdev_driver pmd_tap_drv;
+
+static const char *valid_arguments[] = {
+ ETH_TAP_IFACE_ARG,
+ ETH_TAP_SPEED_ARG,
+ NULL
+};
+
+static int tap_unit;
+
+static struct rte_eth_link pmd_link = {
+ .link_speed = ETH_SPEED_NUM_10G,
+ .link_duplex = ETH_LINK_FULL_DUPLEX,
+ .link_status = ETH_LINK_DOWN,
+ .link_autoneg = ETH_LINK_SPEED_AUTONEG
+};
+
+struct pkt_stats {
+ uint64_t opackets; /* Number of output packets */
+ uint64_t ipackets; /* Number of input packets */
+ uint64_t obytes; /* Number of bytes on output */
+ uint64_t ibytes; /* Number of bytes on input */
+ uint64_t errs; /* Number of error packets */
+};
+
+struct rx_queue {
+ struct rte_mempool *mp; /* Mempool for RX packets */
+ uint16_t in_port; /* Port ID */
+ int fd;
+
+ struct pkt_stats stats; /* Stats for this RX queue */
+};
+
+struct tx_queue {
+ int fd;
+ struct pkt_stats stats; /* Stats for this TX queue */
+};
+
+struct pmd_internals {
+ char name[RTE_ETH_NAME_MAX_LEN]; /* Internal Tap device name */
+ uint16_t nb_queues; /* Number of queues supported */
+ struct ether_addr eth_addr; /* Mac address of the device port */
+
+ int if_index; /* IF_INDEX for the port */
+ int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
+
+ struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX queues */
+ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */
+};
+
+/* Tun/Tap allocation routine
+ *
+ * name is the number of the interface to use, unless NULL to take the host
+ * supplied name.
+ */
+static int
+tun_alloc(char *name)
+{
+ struct ifreq ifr;
+ unsigned int features;
+ int fd;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ if (name && name[0])
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+ fd = open(TUN_TAP_DEV_PATH, O_RDWR);
+ if (fd < 0) {
+ RTE_LOG(ERR, PMD, "Unable to create TAP interface");
+ goto error;
+ }
+
+ /* Grab the TUN features to verify we can work */
+ if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
+ goto error;
+ }
+ RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
+
+ if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
+ RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
+ goto error;
+ } else if ((features & IFF_ONE_QUEUE) &&
+ (RTE_PMD_TAP_MAX_QUEUES == 1)) {
+ ifr.ifr_flags |= IFF_ONE_QUEUE;
+ RTE_LOG(DEBUG, PMD, "Single queue only support\n");
+ } else {
+ ifr.ifr_flags |= IFF_MULTI_QUEUE;
+ RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
+ RTE_PMD_TAP_MAX_QUEUES);
+ }
+
+ /* Set the TUN/TAP configuration and get the name if needed */
+ if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
+ ifr.ifr_name);
+ perror("TUNSETIFF");
+ goto error;
+ }
+
+ /* Always set the file descriptor to non-blocking */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
+ perror("F_SETFL, NONBLOCK");
+ goto error;
+ }
+
+ /* If the name is different that new name as default */
+ if (name && strcmp(name, ifr.ifr_name))
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
+
+ return fd;
+
+error:
+ if (fd > 0)
+ close(fd);
+ return -1;
+}
+
+/* Callback to handle the rx burst of packets to the correct interface and
+ * file descriptor(s) in a multi-queue setup.
+ */
+static uint16_t
+pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+ int len;
+ struct rte_mbuf *mbuf;
+ struct rx_queue *rxq = queue;
+ uint16_t num_rx;
+ unsigned long num_rx_bytes = 0;
+
+ for (num_rx = 0; num_rx < nb_pkts; ) {
+ /* allocate the next mbuf */
+ mbuf = rte_pktmbuf_alloc(rxq->mp);
+ if (unlikely(!mbuf)) {
+ RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
+ break;
+ }
+
+ len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
+ rte_pktmbuf_tailroom(mbuf));
+ if (len <= 0) {
+ rte_pktmbuf_free(mbuf);
+ break;
+ }
+
+ mbuf->data_len = len;
+ mbuf->pkt_len = len;
+ mbuf->port = rxq->in_port;
+
+ /* account for the receive frame */
+ bufs[num_rx++] = mbuf;
+ num_rx_bytes += mbuf->pkt_len;
+ }
+ rxq->stats.ipackets += num_rx;
+ rxq->stats.ibytes += num_rx_bytes;
+
+ return num_rx;
+}
+
+/* Callback to handle sending packets from the tap interface
+ */
+static uint16_t
+pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+ struct rte_mbuf *mbuf;
+ struct tx_queue *txq = queue;
+ struct pollfd pfd;
+ uint16_t num_tx = 0;
+ unsigned long num_tx_bytes = 0;
+ int i, n;
+
+ if (unlikely(nb_pkts == 0))
+ return 0;
+
+ pfd.events = POLLOUT;
+ pfd.fd = txq->fd;
+ for (i = 0; i < nb_pkts; i++) {
+ n = poll(&pfd, 1, 0);
+
+ if (n <= 0)
+ break;
+
+ if (pfd.revents & POLLOUT) {
+ /* copy the tx frame data */
+ mbuf = bufs[num_tx];
+ n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
+ rte_pktmbuf_pkt_len(mbuf));
+ if (n <= 0)
+ break;
+
+ num_tx++;
+ num_tx_bytes += mbuf->pkt_len;
+ rte_pktmbuf_free(mbuf);
+ }
+ }
+
+ txq->stats.opackets += num_tx;
+ txq->stats.errs += nb_pkts - num_tx;
+ txq->stats.obytes += num_tx_bytes;
+
+ return num_tx;
+}
+
+static int
+tap_dev_start(struct rte_eth_dev *dev)
+{
+ /* Force the Link up */
+ dev->data->dev_link.link_status = ETH_LINK_UP;
+
+ return 0;
+}
+
+/* This function gets called when the current port gets stopped.
+ */
+static void
+tap_dev_stop(struct rte_eth_dev *dev)
+{
+ int i;
+ struct pmd_internals *internals = dev->data->dev_private;
+
+ for (i = 0; i < internals->nb_queues; i++)
+ if (internals->fds[i] != -1)
+ close(internals->fds[i]);
+
+ dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static void
+tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+
+ dev_info->if_index = internals->if_index;
+ dev_info->max_mac_addrs = 1;
+ dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
+ dev_info->max_rx_queues = internals->nb_queues;
+ dev_info->max_tx_queues = internals->nb_queues;
+ dev_info->min_rx_bufsize = 0;
+ dev_info->pci_dev = NULL;
+}
+
+static void
+tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
+{
+ unsigned int i, imax;
+ unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+ unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
+ const struct pmd_internals *pmd = dev->data->dev_private;
+
+ imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+ pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+
+ for (i = 0; i < imax; i++) {
+ tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
+ tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
+ rx_total += tap_stats->q_ipackets[i];
+ rx_bytes_total += tap_stats->q_ibytes[i];
+ }
+
+ for (i = 0; i < imax; i++) {
+ tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
+ tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
+ tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
+ tx_total += tap_stats->q_opackets[i];
+ tx_err_total += tap_stats->q_errors[i];
+ tx_bytes_total += tap_stats->q_obytes[i];
+ }
+
+ tap_stats->ipackets = rx_total;
+ tap_stats->ibytes = rx_bytes_total;
+ tap_stats->opackets = tx_total;
+ tap_stats->oerrors = tx_err_total;
+ tap_stats->obytes = tx_bytes_total;
+}
+
+static void
+tap_stats_reset(struct rte_eth_dev *dev)
+{
+ int i;
+ struct pmd_internals *pmd = dev->data->dev_private;
+
+ for (i = 0; i < pmd->nb_queues; i++) {
+ pmd->rxq[i].stats.ipackets = 0;
+ pmd->rxq[i].stats.ibytes = 0;
+ }
+
+ for (i = 0; i < pmd->nb_queues; i++) {
+ pmd->txq[i].stats.opackets = 0;
+ pmd->txq[i].stats.errs = 0;
+ pmd->txq[i].stats.obytes = 0;
+ }
+}
+
+static void
+tap_dev_close(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
+static void
+tap_rx_queue_release(void *queue)
+{
+ struct rx_queue *rxq = queue;
+
+ if (rxq && (rxq->fd > 0)) {
+ close(rxq->fd);
+ rxq->fd = -1;
+ }
+}
+
+static void
+tap_tx_queue_release(void *queue)
+{
+ struct tx_queue *txq = queue;
+
+ if (txq && (txq->fd > 0)) {
+ close(txq->fd);
+ txq->fd = -1;
+ }
+}
+
+static int
+tap_link_update(struct rte_eth_dev *dev __rte_unused,
+ int wait_to_complete __rte_unused)
+{
+ return 0;
+}
+
+static int
+tap_setup_queue(struct rte_eth_dev *dev,
+ struct pmd_internals *internals,
+ uint16_t qid)
+{
+ struct rx_queue *rx = &internals->rxq[qid];
+ struct tx_queue *tx = &internals->txq[qid];
+ int fd;
+
+ fd = rx->fd;
+ if (fd < 0) {
+ fd = tx->fd;
+ if (fd < 0) {
+ RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
+ dev->data->name, qid);
+ fd = tun_alloc(dev->data->name);
+ if (fd < 0) {
+ RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
+ dev->data->name);
+ return -1;
+ }
+ }
+ }
+ dev->data->rx_queues[qid] = rx;
+ dev->data->tx_queues[qid] = tx;
+
+ rx->fd = fd;
+ tx->fd = fd;
+
+ return fd;
+}
+
+static int
+tap_rx_queue_setup(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id,
+ uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mp)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ uint16_t buf_size;
+ int fd;
+
+ if ((rx_queue_id >= internals->nb_queues) || !mp) {
+ RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
+ internals->nb_queues, mp);
+ return -1;
+ }
+
+ internals->rxq[rx_queue_id].mp = mp;
+ internals->rxq[rx_queue_id].in_port = dev->data->port_id;
+
+ /* Now get the space available for data in the mbuf */
+ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+ RTE_PKTMBUF_HEADROOM);
+
+ if (buf_size < ETH_FRAME_LEN) {
+ RTE_LOG(ERR, PMD,
+ "%s: %d bytes will not fit in mbuf (%d bytes)\n",
+ dev->data->name, ETH_FRAME_LEN, buf_size);
+ return -ENOMEM;
+ }
+
+ fd = tap_setup_queue(dev, internals, rx_queue_id);
+ if (fd == -1)
+ return -1;
+
+ internals->fds[rx_queue_id] = fd;
+ RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
+ dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
+
+ return 0;
+}
+
+static int
+tap_tx_queue_setup(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id,
+ uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ int ret;
+
+ if (tx_queue_id >= internals->nb_queues)
+ return -1;
+
+ ret = tap_setup_queue(dev, internals, tx_queue_id);
+ if (ret == -1)
+ return -1;
+
+ RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
+ dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
+
+ return 0;
+}
+
+static const struct eth_dev_ops ops = {
+ .dev_start = tap_dev_start,
+ .dev_stop = tap_dev_stop,
+ .dev_close = tap_dev_close,
+ .dev_configure = tap_dev_configure,
+ .dev_infos_get = tap_dev_info,
+ .rx_queue_setup = tap_rx_queue_setup,
+ .tx_queue_setup = tap_tx_queue_setup,
+ .rx_queue_release = tap_rx_queue_release,
+ .tx_queue_release = tap_tx_queue_release,
+ .link_update = tap_link_update,
+ .stats_get = tap_stats_get,
+ .stats_reset = tap_stats_reset,
+};
+
+static int
+pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
+{
+ struct ifreq ifr;
+
+ if ((fd <= 0) || !dev || !addr)
+ return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+ RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
+ ifr.ifr_name);
+ return -1;
+ }
+
+ /* Set the host based MAC address to this special MAC format */
+ ifr.ifr_hwaddr.sa_data[0] = 'T';
+ ifr.ifr_hwaddr.sa_data[1] = 'a';
+ ifr.ifr_hwaddr.sa_data[2] = 'p';
+ ifr.ifr_hwaddr.sa_data[3] = '-';
+ ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+ ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+ if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
+ RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
+ dev->data->name, ifr.ifr_name);
+ return -1;
+ }
+
+ /* Set the local application MAC address, needs to be different then
+ * the host based MAC address.
+ */
+ ifr.ifr_hwaddr.sa_data[0] = 'd';
+ ifr.ifr_hwaddr.sa_data[1] = 'n';
+ ifr.ifr_hwaddr.sa_data[2] = 'e';
+ ifr.ifr_hwaddr.sa_data[3] = 't';
+ ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+ ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+ rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+static int
+eth_dev_tap_create(const char *name, char *tap_name)
+{
+ int numa_node = rte_socket_id();
+ struct rte_eth_dev *dev = NULL;
+ struct pmd_internals *pmd = NULL;
+ struct rte_eth_dev_data *data = NULL;
+ int i, fd = -1;
+
+ RTE_LOG(INFO, PMD,
+ "%s: Create TAP Ethernet device with %d queues on numa %u\n",
+ name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
+
+ data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
+ if (!data) {
+ RTE_LOG(INFO, PMD, "Failed to allocate data\n");
+ goto error_exit;
+ }
+
+ pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
+ if (!pmd) {
+ RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
+ goto error_exit;
+ }
+
+ /* Use the name and not the tap_name */
+ dev = rte_eth_dev_allocate(tap_name);
+ if (!dev) {
+ RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
+ goto error_exit;
+ }
+
+ snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
+
+ pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
+
+ /* Setup some default values */
+ data->dev_private = pmd;
+ data->port_id = dev->data->port_id;
+ data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+ data->kdrv = RTE_KDRV_NONE;
+ data->drv_name = pmd_tap_drv.driver.name;
+ data->numa_node = numa_node;
+
+ data->dev_link = pmd_link;
+ data->mac_addrs = &pmd->eth_addr;
+ data->nb_rx_queues = pmd->nb_queues;
+ data->nb_tx_queues = pmd->nb_queues;
+
+ dev->data = data;
+ dev->dev_ops = &ops;
+ dev->driver = NULL;
+ dev->rx_pkt_burst = pmd_rx_burst;
+ dev->tx_pkt_burst = pmd_tx_burst;
+ snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
+
+ /* Create the first Tap device */
+ fd = tun_alloc(tap_name);
+ if (fd < 0) {
+ RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
+ goto error_exit;
+ }
+
+ /* Presetup the fds to -1 as being not working */
+ for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
+ pmd->fds[i] = -1;
+ pmd->rxq[i].fd = -1;
+ pmd->txq[i].fd = -1;
+ }
+
+ /* Take the TUN/TAP fd and place in the first location */
+ pmd->rxq[0].fd = fd;
+ pmd->txq[0].fd = fd;
+ pmd->fds[0] = fd;
+
+ if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
+ RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
+ goto error_exit;
+ }
+
+ return 0;
+
+error_exit:
+ RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
+
+ rte_free(data);
+ rte_free(pmd);
+
+ rte_eth_dev_release_port(dev);
+
+ return -EINVAL;
+}
+
+static int
+set_interface_name(const char *key __rte_unused,
+ const char *value,
+ void *extra_args)
+{
+ char *name = (char *)extra_args;
+
+ if (value)
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+ else
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
+ DEFAULT_TAP_NAME, (tap_unit - 1));
+
+ return 0;
+}
+
+static int
+set_interface_speed(const char *key __rte_unused,
+ const char *value,
+ void *extra_args)
+{
+ *(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
+
+ return 0;
+}
+
+/* Open a TAP interface device.
+ */
+static int
+rte_pmd_tap_probe(const char *name, const char *params)
+{
+ int ret;
+ struct rte_kvargs *kvlist = NULL;
+ int speed;
+ char tap_name[RTE_ETH_NAME_MAX_LEN];
+
+ speed = ETH_SPEED_NUM_10G;
+ snprintf(tap_name, sizeof(tap_name), "%s%d",
+ DEFAULT_TAP_NAME, tap_unit++);
+
+ RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
+ name, tap_name);
+
+ if (params && (params[0] != '\0')) {
+ RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
+
+ kvlist = rte_kvargs_parse(params, valid_arguments);
+ if (kvlist) {
+ if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist,
+ ETH_TAP_SPEED_ARG,
+ &set_interface_speed,
+ &speed);
+ if (ret == -1)
+ goto leave;
+ }
+
+ if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist,
+ ETH_TAP_IFACE_ARG,
+ &set_interface_name,
+ tap_name);
+ if (ret == -1)
+ goto leave;
+ }
+ }
+ }
+ pmd_link.link_speed = speed;
+
+ ret = eth_dev_tap_create(name, tap_name);
+
+leave:
+ if (ret == -1) {
+ RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
+ name, tap_name);
+ tap_unit--; /* Restore the unit number */
+ }
+ rte_kvargs_free(kvlist);
+
+ return ret;
+}
+
+/* detach a TAP device.
+ */
+static int
+rte_pmd_tap_remove(const char *name)
+{
+ struct rte_eth_dev *eth_dev = NULL;
+ struct pmd_internals *internals;
+ int i;
+
+ RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
+ rte_socket_id());
+
+ /* find the ethdev entry */
+ eth_dev = rte_eth_dev_allocated(name);
+ if (!eth_dev)
+ return 0;
+
+ internals = eth_dev->data->dev_private;
+ for (i = 0; i < internals->nb_queues; i++)
+ if (internals->fds[i] != -1)
+ close(internals->fds[i]);
+
+ rte_free(eth_dev->data->dev_private);
+ rte_free(eth_dev->data);
+
+ rte_eth_dev_release_port(eth_dev);
+
+ return 0;
+}
+
+static struct rte_vdev_driver pmd_tap_drv = {
+ .probe = rte_pmd_tap_probe,
+ .remove = rte_pmd_tap_remove,
+};
+RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
+RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
+RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
new file mode 100644
index 0000000..31eca32
--- /dev/null
+++ b/drivers/net/tap/rte_pmd_tap_version.map
@@ -0,0 +1,4 @@
+DPDK_17.02 {
+
+ local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..02c32ae 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap
_LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += -lrte_pmd_qede
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) += -lrte_pmd_ring
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += -lrte_pmd_szedata2 -lsze2
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += -lrte_pmd_tap
_LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
_LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += -lrte_pmd_virtio
ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
--
2.8.0.GIT
^ permalink raw reply related
* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
From: Jianbo Liu @ 2016-12-12 14:35 UTC (permalink / raw)
To: Shreyansh Jain; +Cc: David Marchand, dev@dpdk.org, Thomas Monjalon
In-Reply-To: <1697fe66-962d-0848-5e68-615249b52dad@nxp.com>
Hi Shreyansh,
On 7 December 2016 at 21:10, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Wednesday 07 December 2016 05:47 PM, David Marchand wrote:
>>
>> Hello Shreyansh,
>>
>> On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com>
>> wrote:
>>>
>>> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>>>>
>>>>> 0002~0003: Introducing the basic Bus model and associated test case
>>>>> 0005: Support insertion of device rather than addition to tail
>>>>
>>>>
>>>>
>>>> Patch 2 and 5 could be squashed.
>>>
>>>
>>>
>>> I deliberately kept them separate. I intent to extend the Patch 5 for
>>> hotplugging. But, if I don't end up adding support for that in this
>>> series,
>>> I will merge these two.
>>
>>
>> Fine.
>>
>>
>>>> The constructor priority stuff seems unneeded as long as we use
>>>> explicit reference to a global (or local, did not check) bus symbol
>>>> rather than a runtime lookup.
>>>
>>>
>>>
>>> I didn't understand your point here.
>>> IMO, constructor priority (or some other way to handle this) is
>>> important. I
>>> faced this issue while verifying it at my end when the drivers were
>>> getting
>>> registered before the bus.
>>>
>>> Can you elaborate more on '..use explicit reference to a global...'?
>>
>>
>> The drivers register themselves to a bus using this bus specific api.
>>
>> For pci, this is rte_eal_pci_register().
>> The pci_bus object must be moved to eal_common_pci.c (we can stil
>> internally expose for bsd / linux specific implementations).
>> Then, rte_eal_pci_register() can add the pci driver to the pci_bus
>> drivers list even if this pci_bus object is not registered yet to the
>> buses list.
>
>
> So, in eal_common_bus.c
>
> --->8---
>
> struct rte_bus *global_ptr_to_pci_bus = NULL;
>
> struct rte_bus pci_bus = { ... };
>
> rte_eal_pci_register() {
> if (global_ptr_to_pci_bus == NULL)
> rte_eal_bus_register(&pci_bus)
> else
> // continue as if PCI bus is registered
> }
>
> --->8---
>
> so, no RTE_REGISTER_BUS()?
>
> If yes, then RTE_REGISTER_BUS() should also check for an existing
> registration for duplication.
>
> I was banking on a model where bus handlers (or bus drivers) are independent
> entities, just like PMDs. So, we have a bus XYZ without any drivers
> necessarily based on it.
>
> By making registration dependent on driver registration, it becomes implicit
> that buses don't exist without drivers.
> I am not in favor of this - or maybe I lack enough reason for this (about
> how it will make framework/PMD life better).
>
>>
>> And no constructor order issue ?
>>
>>
>>>>
>>>>
>>>>> 0004: Add scan and match callbacks for the Bus and updated test
>>>>> case
>>>>
>>>>
>>>>
>>>> Why do you push back the bus object in the 'scan' method ?
>>>> This method is bus specific which means that the code "knows" the
>>>> object registered with the callback.
>>>
>>>
>>>
>>> This 'knows' is the grey area for me.
>>> The bus (for example, PCI) after scanning needs to call
>>> rte_eal_bus_add_device() to link the device in bus's device_list.
>>>
>>> Two options:
>>> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
>>> 2. Call rte_eal_get_bus() every time someone needs the reference.
>>> 3. C++ style, 'this->'.
>>>
>>> I have taken the 3rd path. It simplifies my code to not assume a handle
>>> as
>>> well as not allow for reference fetch calls every now and then.
>>>
>>> As a disadvantage: it means passing this as argument - and some cases
>>> maintaining it as __rte_unused.
>>>
>>> Taking (1) or (2) is not advantageous than this approach.
>>
>>
>> 1) is the simplest one.
>>
>> When you write a pci_scan method and embed it in you pci_bus object,
>> but this pci_scan method still wonders which bus object it is supposed
>> to work on, this is a bit like Schizophrenia ;-).
>
>
> :)
> This now is linked to the above issue of constructor priority and having a
> global bus reference. I don't personally prefer it.
> I will still give this a serious thought, though.
>
I'm also in favor of (3).
>>
>>
>>>> Is is that you want to have a single scan method used by multiple buses
>>>> ?
>>>
>>>
>>>
>>> Yes, but only as a use case. For example, platform devices are of various
>>> types - what if we have a south-bound bus over a platform bus. In which
>>> case, a hierarchical bus layout is possible.
>>> But, this is far-fetched idea for now.
>>
How to express the hierarchical bus layout as the bus in your design
is more like independent objects to hold drivers and their devices?
>>
>> Well, if you have no usecase at the moment, let's keep it simple, please.
>>
>
> Ok.
>
>>
>>>>
>>>>> 0006: Integrate bus scan/match with EAL, without any effective
>>>>> driver
>>>>
>>>>
>>>>
>>>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>>>> linked, I would squash them into one.
>>>
>>>
>>>
>>> Yes, it is hard and sometimes there is simply no strong rationale for
>>> splitting or merging. This is one of those cases.
>>> My idea was that one patch _only_ introduces Bus services (structures,
>>> functions etc) and another should enable the calls to it from EAL.
>>> In that sense, I still think 4 and 6 should remain separate, may be
>>> consecutive, though.
>>
>>
>> Ok, will see in next version of the patchset.
>
>
> Is there anything specific that you are looking for in patchset v2?
> I was thinking of:
> 0. fixing BSD compilation issue reported by CI
> 1. improving the test_pci.c
> 2. hotplugging
> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how drivers
> link to it, and how EAL resources like devargs are consumed.
>
> Anything else?
>
>>
>>
>>>>
>>>>> 0007: rte_pci_driver->probe replaced with rte_driver->probe
>>>>
>>>>
>>>>
>>>> This patch is too big, please separate in two patches: eal changes
>>>> then ethdev/driver changes.
>>>
>>>
>>>
>>> I don't think that can be done. One change is incomplete without the
>>> other.
>>>
>>> Changes to all files are only for rte_pci_driver->probe to
>>> rte_driver->probe
>>> movement. EAL changes is to allow rte_eth_dev_pci_probe function after
>>> such
>>> a change as rte_driver->probe has different arguments as compared to
>>> rte_pci_driver->probe. The patches won't compile if I split.
>>>
>>> Am I missing something?
>>>>
>>>>
>>>> Why do you push back the driver object in the 'probe' method ? (idem
>>>> rte_bus->scan).
>>>
>>>
>>>
>>> I am assuming you are referring to rte_driver->probe().
>>> This is being done so that implementations (specific to drivers on a
>>> particular bus) can start extracting the rte_xxx_driver, if need be.
>>>
>>> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
>>> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
>>> absence of the rte_driver object, this function cannot call
>>> rte_pci_driver->probe (for example) for driver specific operations.
>>
>>
>> Sorry, I am thinking a step ahead with eth_driver out of the picture.
>> But once eth_driver disappears, I can see no reason to keep this
>> driver in the probe method (Schizophrenia again).
>
>
> When eth_driver disappears, i was thinking of accomodating the eth_dev_init
> into the rte_pci_driver->probe/init.
> But, this is still a nascent thought.
> I am yet to start working on eth_driver.
>
>>
>>
>>
>
^ permalink raw reply
* [PATCH v12] net/tap: new TUN/TAP device PMD
From: Keith Wiles @ 2016-12-12 14:24 UTC (permalink / raw)
To: dev; +Cc: pmatilai, yuanhan.liu, ferruh.yigit, john.mcnamara
In-Reply-To: <1476396234-44694-1-git-send-email-keith.wiles@intel.com>
The PMD allows for DPDK and the host to communicate using a raw
device interface on the host and in the DPDK application. The device
created is a Tap device with a L2 packet header.
v12- Fixup minor changes for driver_name and version number
v11- Add the tap.rst to the nic/index.rst file
v10- Change the string name used to allow for multiple devices.
v9 - Fix up the docs to use correct syntax
v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
v7 - Reword the comment in common_base and fix the data->name issue
v6 - fixed the checkpatch issues
v5 - merge in changes from list review see related emails
fixed many minor edits
v4 - merge with latest driver changes
v3 - fix includes by removing ifdef for other type besides Linux
Fix the copyright notice in the Makefile
v2 - merge all of the patches into one patch
Fix a typo on naming the tap device
Update the maintainers list
Signed-off-by: Keith Wiles <keith.wiles@intel.com>
---
MAINTAINERS | 5 +
config/common_base | 9 +
config/common_linuxapp | 1 +
doc/guides/nics/index.rst | 1 +
doc/guides/nics/tap.rst | 136 ++++++
drivers/net/Makefile | 1 +
drivers/net/tap/Makefile | 57 +++
drivers/net/tap/rte_eth_tap.c | 765 ++++++++++++++++++++++++++++++++
drivers/net/tap/rte_pmd_tap_version.map | 4 +
mk/rte.app.mk | 1 +
10 files changed, 980 insertions(+)
create mode 100644 doc/guides/nics/tap.rst
create mode 100644 drivers/net/tap/Makefile
create mode 100644 drivers/net/tap/rte_eth_tap.c
create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
diff --git a/MAINTAINERS b/MAINTAINERS
index 26d9590..842fb6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,11 @@ F: doc/guides/nics/pcap_ring.rst
F: app/test/test_pmd_ring.c
F: app/test/test_pmd_ring_perf.c
+Tap PMD
+M: Keith Wiles <keith.wiles@intel.com>
+F: drivers/net/tap
+F: doc/guides/nics/tap.rst
+
Null Networking PMD
M: Tetsuya Mukawa <mtetsuyah@gmail.com>
F: drivers/net/null/
diff --git a/config/common_base b/config/common_base
index 652a839..eb51cdb 100644
--- a/config/common_base
+++ b/config/common_base
@@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
CONFIG_RTE_TEST_PMD=y
CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the TAP PMD
+#
+# The TAP PMD is currently only built for Linux and the
+# option is enabled by default in common_linuxapp file,
+# set to 'n' in the common_base file.
+#
+CONFIG_RTE_LIBRTE_PMD_TAP=n
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2483dfa..782b503 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -44,3 +44,4 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
CONFIG_RTE_LIBRTE_POWER=y
CONFIG_RTE_VIRTIO_USER=y
+CONFIG_RTE_LIBRTE_PMD_TAP=y
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index 92d56a5..af92529 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -51,6 +51,7 @@ Network Interface Controller Drivers
nfp
qede
szedata2
+ tap
thunderx
virtio
vhost
diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
new file mode 100644
index 0000000..622b9e7
--- /dev/null
+++ b/doc/guides/nics/tap.rst
@@ -0,0 +1,136 @@
+.. BSD LICENSE
+ Copyright(c) 2016 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS 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 COPYRIGHT
+ OWNER 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.
+
+Tun/Tap Poll Mode Driver
+========================
+
+The ``rte_eth_tap.c`` PMD creates a device using TUN/TAP interfaces on the
+local host. The PMD allows for DPDK and the host to communicate using a raw
+device interface on the host and in the DPDK application.
+
+The device created is a TAP device, which sends/receives packet in a raw
+format with a L2 header. The usage for a TAP PMD is for connectivity to the
+local host using a TAP interface. When the TAP PMD is initialized it will
+create a number of tap devices in the host accessed via ``ifconfig -a`` or
+``ip`` command. The commands can be used to assign and query the virtual like
+device.
+
+These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK
+along with being able to be used as a network connection to the DPDK
+application. The method enable one or more interfaces is to use the
+``--vdev=net_tap`` option on the DPDK application command line. Each
+``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
+and so on.
+
+The interfaced name can be changed by adding the ``iface=foo0``, for example::
+
+ --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
+
+Also the speed of the interface can be changed from 10G to whatever number
+needed, but the interface does not enforce that speed, for example::
+
+ --vdev=net_tap,iface=foo0,speed=25000
+
+After the DPDK application is started you can send and receive packets on the
+interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
+point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
+and others to communicate with the DPDK application. The DPDK application may
+not understand network protocols like IPv4/6, UDP or TCP unless the
+application has been written to understand these protocols.
+
+If you need the interface as a real network interface meaning running and has
+a valid IP address then you can do this with the following commands::
+
+ sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+ sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Please change the IP addresses as you see fit.
+
+If routing is enabled on the host you can also communicate with the DPDK App
+over the internet via a standard socket layer application as long as you
+account for the protocol handing in the application.
+
+If you have a Network Stack in your DPDK application or something like it you
+can utilize that stack to handle the network protocols. Plus you would be able
+to address the interface using an IP address assigned to the internal
+interface.
+
+Example
+-------
+
+The following is a simple example of using the TUN/TAP PMD with the Pktgen
+packet generator. It requires that the ``socat`` utility is installed on the
+test system.
+
+Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
+used to build the dpdk you pulled down.
+
+Run pktgen from the pktgen directory in a terminal with a commandline like the
+following::
+
+ sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4 \
+ --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg \
+ --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1 \
+ -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3 \
+ -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3 \
+ -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1 \
+ -f themes/black-yellow.theme
+
+.. Note:
+
+ Change the ``-b`` options to blacklist all of your physical ports. The
+ following command line is all one line.
+
+ Also, ``-f themes/black-yellow.theme`` is optional if the default colors
+ work on your system configuration. See the Pktgen docs for more
+ information.
+
+Verify with ``ifconfig -a`` command in a different xterm window, should have a
+``dtap0`` and ``dtap1`` interfaces created.
+
+Next set the links for the two interfaces to up via the commands below::
+
+ sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
+ sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
+
+Then use socat to create a loopback for the two interfaces::
+
+ sudo socat interface:dtap0 interface:dtap1
+
+Then on the Pktgen command line interface you can start sending packets using
+the commands ``start 0`` and ``start 1`` or you can start both at the same
+time with ``start all``. The command ``str`` is an alias for ``start all`` and
+``stp`` is an alias for ``stop all``.
+
+While running you should see the 64 byte counters increasing to verify the
+traffic is being looped back. You can use ``set all size XXX`` to change the
+size of the packets after you stop the traffic. Use the pktgen ``help``
+command to see a list of all commands. You can also use the ``-f`` option to
+load commands at startup.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index bc93230..e366a85 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
new file mode 100644
index 0000000..e18f30c
--- /dev/null
+++ b/drivers/net/tap/Makefile
@@ -0,0 +1,57 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS 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 COPYRIGHT
+# OWNER 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.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_tap.a
+
+EXPORT_MAP := rte_pmd_tap_version.map
+
+LIBABIVER := 1
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
new file mode 100644
index 0000000..d5e2fc3
--- /dev/null
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -0,0 +1,765 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_vdev.h>
+#include <rte_kvargs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_ether.h>
+#include <fcntl.h>
+
+/* Linux based path to the TUN device */
+#define TUN_TAP_DEV_PATH "/dev/net/tun"
+#define DEFAULT_TAP_NAME "dtap"
+
+#define ETH_TAP_IFACE_ARG "iface"
+#define ETH_TAP_SPEED_ARG "speed"
+
+#define RTE_PMD_TAP_MAX_QUEUES 16
+
+static const char *valid_arguments[] = {
+ ETH_TAP_IFACE_ARG,
+ ETH_TAP_SPEED_ARG,
+ NULL
+};
+
+static const char *drivername = "Tap PMD";
+static int tap_unit;
+
+static struct rte_eth_link pmd_link = {
+ .link_speed = ETH_SPEED_NUM_10G,
+ .link_duplex = ETH_LINK_FULL_DUPLEX,
+ .link_status = ETH_LINK_DOWN,
+ .link_autoneg = ETH_LINK_SPEED_AUTONEG
+};
+
+struct pkt_stats {
+ uint64_t opackets; /* Number of output packets */
+ uint64_t ipackets; /* Number of input packets */
+ uint64_t obytes; /* Number of bytes on output */
+ uint64_t ibytes; /* Number of bytes on input */
+ uint64_t errs; /* Number of error packets */
+};
+
+struct rx_queue {
+ struct rte_mempool *mp; /* Mempool for RX packets */
+ uint16_t in_port; /* Port ID */
+ int fd;
+
+ struct pkt_stats stats; /* Stats for this RX queue */
+};
+
+struct tx_queue {
+ int fd;
+ struct pkt_stats stats; /* Stats for this TX queue */
+};
+
+struct pmd_internals {
+ char name[RTE_ETH_NAME_MAX_LEN]; /* Internal Tap device name */
+ uint16_t nb_queues; /* Number of queues supported */
+ struct ether_addr eth_addr; /* Mac address of the device port */
+
+ int if_index; /* IF_INDEX for the port */
+ int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
+
+ struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX queues */
+ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */
+};
+
+/* Tun/Tap allocation routine
+ *
+ * name is the number of the interface to use, unless NULL to take the host
+ * supplied name.
+ */
+static int
+tun_alloc(char *name)
+{
+ struct ifreq ifr;
+ unsigned int features;
+ int fd;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ if (name && name[0])
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+ fd = open(TUN_TAP_DEV_PATH, O_RDWR);
+ if (fd < 0) {
+ RTE_LOG(ERR, PMD, "Unable to create TAP interface");
+ goto error;
+ }
+
+ /* Grab the TUN features to verify we can work */
+ if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
+ goto error;
+ }
+ RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
+
+ if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
+ RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
+ goto error;
+ } else if ((features & IFF_ONE_QUEUE) &&
+ (RTE_PMD_TAP_MAX_QUEUES == 1)) {
+ ifr.ifr_flags |= IFF_ONE_QUEUE;
+ RTE_LOG(DEBUG, PMD, "Single queue only support\n");
+ } else {
+ ifr.ifr_flags |= IFF_MULTI_QUEUE;
+ RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
+ RTE_PMD_TAP_MAX_QUEUES);
+ }
+
+ /* Set the TUN/TAP configuration and get the name if needed */
+ if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
+ ifr.ifr_name);
+ perror("TUNSETIFF");
+ goto error;
+ }
+
+ /* Always set the file descriptor to non-blocking */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
+ perror("F_SETFL, NONBLOCK");
+ goto error;
+ }
+
+ /* If the name is different that new name as default */
+ if (name && strcmp(name, ifr.ifr_name))
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
+
+ return fd;
+
+error:
+ if (fd > 0)
+ close(fd);
+ return -1;
+}
+
+/* Callback to handle the rx burst of packets to the correct interface and
+ * file descriptor(s) in a multi-queue setup.
+ */
+static uint16_t
+pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+ int len;
+ struct rte_mbuf *mbuf;
+ struct rx_queue *rxq = queue;
+ uint16_t num_rx;
+ unsigned long num_rx_bytes = 0;
+
+ for (num_rx = 0; num_rx < nb_pkts; ) {
+ /* allocate the next mbuf */
+ mbuf = rte_pktmbuf_alloc(rxq->mp);
+ if (unlikely(!mbuf)) {
+ RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
+ break;
+ }
+
+ len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
+ rte_pktmbuf_tailroom(mbuf));
+ if (len <= 0) {
+ rte_pktmbuf_free(mbuf);
+ break;
+ }
+
+ mbuf->data_len = len;
+ mbuf->pkt_len = len;
+ mbuf->port = rxq->in_port;
+
+ /* account for the receive frame */
+ bufs[num_rx++] = mbuf;
+ num_rx_bytes += mbuf->pkt_len;
+ }
+ rxq->stats.ipackets += num_rx;
+ rxq->stats.ibytes += num_rx_bytes;
+
+ return num_rx;
+}
+
+/* Callback to handle sending packets from the tap interface
+ */
+static uint16_t
+pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+{
+ struct rte_mbuf *mbuf;
+ struct tx_queue *txq = queue;
+ struct pollfd pfd;
+ uint16_t num_tx = 0;
+ unsigned long num_tx_bytes = 0;
+ int i, n;
+
+ if (unlikely(nb_pkts == 0))
+ return 0;
+
+ pfd.events = POLLOUT;
+ pfd.fd = txq->fd;
+ for (i = 0; i < nb_pkts; i++) {
+ n = poll(&pfd, 1, 0);
+
+ if (n <= 0)
+ break;
+
+ if (pfd.revents & POLLOUT) {
+ /* copy the tx frame data */
+ mbuf = bufs[num_tx];
+ n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
+ rte_pktmbuf_pkt_len(mbuf));
+ if (n <= 0)
+ break;
+
+ num_tx++;
+ num_tx_bytes += mbuf->pkt_len;
+ rte_pktmbuf_free(mbuf);
+ }
+ }
+
+ txq->stats.opackets += num_tx;
+ txq->stats.errs += nb_pkts - num_tx;
+ txq->stats.obytes += num_tx_bytes;
+
+ return num_tx;
+}
+
+static int
+tap_dev_start(struct rte_eth_dev *dev)
+{
+ /* Force the Link up */
+ dev->data->dev_link.link_status = ETH_LINK_UP;
+
+ return 0;
+}
+
+/* This function gets called when the current port gets stopped.
+ */
+static void
+tap_dev_stop(struct rte_eth_dev *dev)
+{
+ int i;
+ struct pmd_internals *internals = dev->data->dev_private;
+
+ for (i = 0; i < internals->nb_queues; i++)
+ if (internals->fds[i] != -1)
+ close(internals->fds[i]);
+
+ dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static void
+tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+
+ dev_info->driver_name = drivername;
+ dev_info->if_index = internals->if_index;
+ dev_info->max_mac_addrs = 1;
+ dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
+ dev_info->max_rx_queues = internals->nb_queues;
+ dev_info->max_tx_queues = internals->nb_queues;
+ dev_info->min_rx_bufsize = 0;
+ dev_info->pci_dev = NULL;
+}
+
+static void
+tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
+{
+ unsigned int i, imax;
+ unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+ unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
+ const struct pmd_internals *pmd = dev->data->dev_private;
+
+ imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+ pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+
+ for (i = 0; i < imax; i++) {
+ tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
+ tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
+ rx_total += tap_stats->q_ipackets[i];
+ rx_bytes_total += tap_stats->q_ibytes[i];
+ }
+
+ for (i = 0; i < imax; i++) {
+ tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
+ tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
+ tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
+ tx_total += tap_stats->q_opackets[i];
+ tx_err_total += tap_stats->q_errors[i];
+ tx_bytes_total += tap_stats->q_obytes[i];
+ }
+
+ tap_stats->ipackets = rx_total;
+ tap_stats->ibytes = rx_bytes_total;
+ tap_stats->opackets = tx_total;
+ tap_stats->oerrors = tx_err_total;
+ tap_stats->obytes = tx_bytes_total;
+}
+
+static void
+tap_stats_reset(struct rte_eth_dev *dev)
+{
+ int i;
+ struct pmd_internals *pmd = dev->data->dev_private;
+
+ for (i = 0; i < pmd->nb_queues; i++) {
+ pmd->rxq[i].stats.ipackets = 0;
+ pmd->rxq[i].stats.ibytes = 0;
+ }
+
+ for (i = 0; i < pmd->nb_queues; i++) {
+ pmd->txq[i].stats.opackets = 0;
+ pmd->txq[i].stats.errs = 0;
+ pmd->txq[i].stats.obytes = 0;
+ }
+}
+
+static void
+tap_dev_close(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
+static void
+tap_rx_queue_release(void *queue)
+{
+ struct rx_queue *rxq = queue;
+
+ if (rxq && (rxq->fd > 0)) {
+ close(rxq->fd);
+ rxq->fd = -1;
+ }
+}
+
+static void
+tap_tx_queue_release(void *queue)
+{
+ struct tx_queue *txq = queue;
+
+ if (txq && (txq->fd > 0)) {
+ close(txq->fd);
+ txq->fd = -1;
+ }
+}
+
+static int
+tap_link_update(struct rte_eth_dev *dev __rte_unused,
+ int wait_to_complete __rte_unused)
+{
+ return 0;
+}
+
+static int
+tap_setup_queue(struct rte_eth_dev *dev,
+ struct pmd_internals *internals,
+ uint16_t qid)
+{
+ struct rx_queue *rx = &internals->rxq[qid];
+ struct tx_queue *tx = &internals->txq[qid];
+ int fd;
+
+ fd = rx->fd;
+ if (fd < 0) {
+ fd = tx->fd;
+ if (fd < 0) {
+ RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
+ dev->data->name, qid);
+ fd = tun_alloc(dev->data->name);
+ if (fd < 0) {
+ RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
+ dev->data->name);
+ return -1;
+ }
+ }
+ }
+ dev->data->rx_queues[qid] = rx;
+ dev->data->tx_queues[qid] = tx;
+
+ rx->fd = fd;
+ tx->fd = fd;
+
+ return fd;
+}
+
+static int
+tap_rx_queue_setup(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id,
+ uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mp)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ uint16_t buf_size;
+ int fd;
+
+ if ((rx_queue_id >= internals->nb_queues) || !mp) {
+ RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
+ internals->nb_queues, mp);
+ return -1;
+ }
+
+ internals->rxq[rx_queue_id].mp = mp;
+ internals->rxq[rx_queue_id].in_port = dev->data->port_id;
+
+ /* Now get the space available for data in the mbuf */
+ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+ RTE_PKTMBUF_HEADROOM);
+
+ if (buf_size < ETH_FRAME_LEN) {
+ RTE_LOG(ERR, PMD,
+ "%s: %d bytes will not fit in mbuf (%d bytes)\n",
+ dev->data->name, ETH_FRAME_LEN, buf_size);
+ return -ENOMEM;
+ }
+
+ fd = tap_setup_queue(dev, internals, rx_queue_id);
+ if (fd == -1)
+ return -1;
+
+ internals->fds[rx_queue_id] = fd;
+ RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
+ dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
+
+ return 0;
+}
+
+static int
+tap_tx_queue_setup(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id,
+ uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ int ret;
+
+ if (tx_queue_id >= internals->nb_queues)
+ return -1;
+
+ ret = tap_setup_queue(dev, internals, tx_queue_id);
+ if (ret == -1)
+ return -1;
+
+ RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
+ dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
+
+ return 0;
+}
+
+static const struct eth_dev_ops ops = {
+ .dev_start = tap_dev_start,
+ .dev_stop = tap_dev_stop,
+ .dev_close = tap_dev_close,
+ .dev_configure = tap_dev_configure,
+ .dev_infos_get = tap_dev_info,
+ .rx_queue_setup = tap_rx_queue_setup,
+ .tx_queue_setup = tap_tx_queue_setup,
+ .rx_queue_release = tap_rx_queue_release,
+ .tx_queue_release = tap_tx_queue_release,
+ .link_update = tap_link_update,
+ .stats_get = tap_stats_get,
+ .stats_reset = tap_stats_reset,
+};
+
+static int
+pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
+{
+ struct ifreq ifr;
+
+ if ((fd <= 0) || !dev || !addr)
+ return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+ RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
+ ifr.ifr_name);
+ return -1;
+ }
+
+ /* Set the host based MAC address to this special MAC format */
+ ifr.ifr_hwaddr.sa_data[0] = 'T';
+ ifr.ifr_hwaddr.sa_data[1] = 'a';
+ ifr.ifr_hwaddr.sa_data[2] = 'p';
+ ifr.ifr_hwaddr.sa_data[3] = '-';
+ ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+ ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+ if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
+ RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
+ dev->data->name, ifr.ifr_name);
+ return -1;
+ }
+
+ /* Set the local application MAC address, needs to be different then
+ * the host based MAC address.
+ */
+ ifr.ifr_hwaddr.sa_data[0] = 'd';
+ ifr.ifr_hwaddr.sa_data[1] = 'n';
+ ifr.ifr_hwaddr.sa_data[2] = 'e';
+ ifr.ifr_hwaddr.sa_data[3] = 't';
+ ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
+ ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
+ rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+static int
+eth_dev_tap_create(const char *name, char *tap_name)
+{
+ int numa_node = rte_socket_id();
+ struct rte_eth_dev *dev = NULL;
+ struct pmd_internals *pmd = NULL;
+ struct rte_eth_dev_data *data = NULL;
+ int i, fd = -1;
+
+ RTE_LOG(INFO, PMD,
+ "%s: Create TAP Ethernet device with %d queues on numa %u\n",
+ name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
+
+ data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
+ if (!data) {
+ RTE_LOG(INFO, PMD, "Failed to allocate data\n");
+ goto error_exit;
+ }
+
+ pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
+ if (!pmd) {
+ RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
+ goto error_exit;
+ }
+
+ /* Use the name and not the tap_name */
+ dev = rte_eth_dev_allocate(tap_name);
+ if (!dev) {
+ RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
+ goto error_exit;
+ }
+
+ snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
+
+ pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
+
+ /* Setup some default values */
+ data->dev_private = pmd;
+ data->port_id = dev->data->port_id;
+ data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+ data->kdrv = RTE_KDRV_NONE;
+ data->drv_name = drivername;
+ data->numa_node = numa_node;
+
+ data->dev_link = pmd_link;
+ data->mac_addrs = &pmd->eth_addr;
+ data->nb_rx_queues = pmd->nb_queues;
+ data->nb_tx_queues = pmd->nb_queues;
+ data->drv_name = drivername;
+
+ dev->data = data;
+ dev->dev_ops = &ops;
+ dev->driver = NULL;
+ dev->rx_pkt_burst = pmd_rx_burst;
+ dev->tx_pkt_burst = pmd_tx_burst;
+ snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
+
+ /* Create the first Tap device */
+ fd = tun_alloc(tap_name);
+ if (fd < 0) {
+ RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
+ goto error_exit;
+ }
+
+ /* Presetup the fds to -1 as being not working */
+ for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
+ pmd->fds[i] = -1;
+ pmd->rxq[i].fd = -1;
+ pmd->txq[i].fd = -1;
+ }
+
+ /* Take the TUN/TAP fd and place in the first location */
+ pmd->rxq[0].fd = fd;
+ pmd->txq[0].fd = fd;
+ pmd->fds[0] = fd;
+
+ if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
+ RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
+ goto error_exit;
+ }
+
+ return 0;
+
+error_exit:
+ RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
+
+ rte_free(data);
+ rte_free(pmd);
+
+ rte_eth_dev_release_port(dev);
+
+ return -EINVAL;
+}
+
+static int
+set_interface_name(const char *key __rte_unused,
+ const char *value,
+ void *extra_args)
+{
+ char *name = (char *)extra_args;
+
+ if (value)
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
+ else
+ snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
+ DEFAULT_TAP_NAME, (tap_unit - 1));
+
+ return 0;
+}
+
+static int
+set_interface_speed(const char *key __rte_unused,
+ const char *value,
+ void *extra_args)
+{
+ *(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
+
+ return 0;
+}
+
+/* Open a TAP interface device.
+ */
+static int
+rte_pmd_tap_probe(const char *name, const char *params)
+{
+ int ret;
+ struct rte_kvargs *kvlist = NULL;
+ int speed;
+ char tap_name[RTE_ETH_NAME_MAX_LEN];
+
+ speed = ETH_SPEED_NUM_10G;
+ snprintf(tap_name, sizeof(tap_name), "%s%d",
+ DEFAULT_TAP_NAME, tap_unit++);
+
+ RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
+ name, tap_name);
+
+ if (params && (params[0] != '\0')) {
+ RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
+
+ kvlist = rte_kvargs_parse(params, valid_arguments);
+ if (kvlist) {
+ if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist,
+ ETH_TAP_SPEED_ARG,
+ &set_interface_speed,
+ &speed);
+ if (ret == -1)
+ goto leave;
+ }
+
+ if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
+ ret = rte_kvargs_process(kvlist,
+ ETH_TAP_IFACE_ARG,
+ &set_interface_name,
+ tap_name);
+ if (ret == -1)
+ goto leave;
+ }
+ }
+ }
+ pmd_link.link_speed = speed;
+
+ ret = eth_dev_tap_create(name, tap_name);
+
+leave:
+ if (ret == -1) {
+ RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
+ name, tap_name);
+ tap_unit--; /* Restore the unit number */
+ }
+ rte_kvargs_free(kvlist);
+
+ return ret;
+}
+
+/* detach a TAP device.
+ */
+static int
+rte_pmd_tap_remove(const char *name)
+{
+ struct rte_eth_dev *eth_dev = NULL;
+ struct pmd_internals *internals;
+ int i;
+
+ RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
+ rte_socket_id());
+
+ /* find the ethdev entry */
+ eth_dev = rte_eth_dev_allocated(name);
+ if (!eth_dev)
+ return 0;
+
+ internals = eth_dev->data->dev_private;
+ for (i = 0; i < internals->nb_queues; i++)
+ if (internals->fds[i] != -1)
+ close(internals->fds[i]);
+
+ rte_free(eth_dev->data->dev_private);
+ rte_free(eth_dev->data);
+
+ rte_eth_dev_release_port(eth_dev);
+
+ return 0;
+}
+
+static struct rte_vdev_driver pmd_tap_drv = {
+ .probe = rte_pmd_tap_probe,
+ .remove = rte_pmd_tap_remove,
+};
+RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
+RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
new file mode 100644
index 0000000..61463bf
--- /dev/null
+++ b/drivers/net/tap/rte_pmd_tap_version.map
@@ -0,0 +1,4 @@
+DPDK_16.11 {
+
+ local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..02c32ae 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap
_LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += -lrte_pmd_qede
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) += -lrte_pmd_ring
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += -lrte_pmd_szedata2 -lsze2
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += -lrte_pmd_tap
_LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
_LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += -lrte_pmd_virtio
ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
--
2.8.0.GIT
^ permalink raw reply related
* [PATCH v3 9/9] doc: update release notes
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]
Add release note for removing set VF API's from the ethdev,
renaming the API's and moving them to the ixgbe PMD.
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
doc/guides/rel_notes/release_17_02.rst | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 3b65038..d30b258 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -38,6 +38,26 @@ New Features
Also, make sure to start the actual text at the margin.
=========================================================
+* **Moved five APIs for VF management from the ethdev to the ixgbe PMD.**
+
+ The following five APIs for VF management from the PF have been removed from the ethdev,
+ renamed and added to the ixgbe PMD::
+
+ rte_eth_dev_set_vf_rate_limit
+ rte_eth_dev_set_vf_rx
+ rte_eth_dev_set_vf_rxmode
+ rte_eth_dev_set_vf_tx
+ rte_eth_dev_set_vf_vlan_filter
+
+ The API's have been renamed to the following::
+
+ rte_pmd_ixgbe_set_vf_rate_limit
+ rte_pmd_ixgbe_set_vf_rx
+ rte_pmd_ixgbe_set_vf_rxmode
+ rte_pmd_ixgbe_set_vf_tx
+ rte_pmd_ixgbe_set_vf_vlan_filter
+
+ The declarations for the API’s can be found in ``rte_pmd_ixgbe.h``.
Resolved Issues
---------------
--
2.10.1
^ permalink raw reply related
* [PATCH v3 8/9] librte_ether: remove the set VF API's
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>
remove the following API's:
rte_eth_dev_set_vf_rxmode
rte_eth_dev_set_vf_rx
rte_eth_dev_set_vf_tx
rte_eth_dev_set_vf_vlan_filter
rte_eth_dev_set_vf_rate_limit
Increment LIBABIVER in Makefile
Remove deprecation notice for removing rte_eth_dev_set_vf_* API's.
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
doc/guides/rel_notes/deprecation.rst | 13 ---
lib/librte_ether/Makefile | 4 +-
lib/librte_ether/rte_ethdev.c | 129 ------------------------------
lib/librte_ether/rte_ethdev.h | 140 ---------------------------------
lib/librte_ether/rte_ether_version.map | 7 +-
5 files changed, 3 insertions(+), 290 deletions(-)
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 2d17bc6..c897c18 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -38,19 +38,6 @@ Deprecation Notices
``_rte_eth_dev_callback_process``. In 17.02 the function will return an ``int``
instead of ``void`` and a fourth parameter ``void *ret_param`` will be added.
-* ethdev: for 17.02 it is planned to deprecate the following five functions
- and move them in ixgbe:
-
- ``rte_eth_dev_set_vf_rxmode``
-
- ``rte_eth_dev_set_vf_rx``
-
- ``rte_eth_dev_set_vf_tx``
-
- ``rte_eth_dev_set_vf_vlan_filter``
-
- ``rte_eth_set_vf_rate_limit``
-
* ABI changes are planned for 17.02 in the ``rte_mbuf`` structure: some fields
may be reordered to facilitate the writing of ``data_off``, ``refcnt``, and
``nb_segs`` in one operation, because some platforms have an overhead if the
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index efe1e5f..d23015c 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@ CFLAGS += $(WERROR_FLAGS)
EXPORT_MAP := rte_ether_version.map
-LIBABIVER := 5
+LIBABIVER := 6
SRCS-y += rte_ethdev.c
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1e0f206..6a93014 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2137,32 +2137,6 @@ rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr)
return 0;
}
-int
-rte_eth_dev_set_vf_rxmode(uint8_t port_id, uint16_t vf,
- uint16_t rx_mode, uint8_t on)
-{
- uint16_t num_vfs;
- struct rte_eth_dev *dev;
- struct rte_eth_dev_info dev_info;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
- dev = &rte_eth_devices[port_id];
- rte_eth_dev_info_get(port_id, &dev_info);
-
- num_vfs = dev_info.max_vfs;
- if (vf > num_vfs) {
- RTE_PMD_DEBUG_TRACE("set VF RX mode:invalid VF id %d\n", vf);
- return -EINVAL;
- }
-
- if (rx_mode == 0) {
- RTE_PMD_DEBUG_TRACE("set VF RX mode:mode mask ca not be zero\n");
- return -EINVAL;
- }
- RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx_mode, -ENOTSUP);
- return (*dev->dev_ops->set_vf_rx_mode)(dev, vf, rx_mode, on);
-}
/*
* Returns index into MAC address array of addr. Use 00:00:00:00:00:00 to find
@@ -2252,76 +2226,6 @@ rte_eth_dev_uc_all_hash_table_set(uint8_t port_id, uint8_t on)
return (*dev->dev_ops->uc_all_hash_table_set)(dev, on);
}
-int
-rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on)
-{
- uint16_t num_vfs;
- struct rte_eth_dev *dev;
- struct rte_eth_dev_info dev_info;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
- dev = &rte_eth_devices[port_id];
- rte_eth_dev_info_get(port_id, &dev_info);
-
- num_vfs = dev_info.max_vfs;
- if (vf > num_vfs) {
- RTE_PMD_DEBUG_TRACE("port %d: invalid vf id\n", port_id);
- return -EINVAL;
- }
-
- RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx, -ENOTSUP);
- return (*dev->dev_ops->set_vf_rx)(dev, vf, on);
-}
-
-int
-rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on)
-{
- uint16_t num_vfs;
- struct rte_eth_dev *dev;
- struct rte_eth_dev_info dev_info;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
- dev = &rte_eth_devices[port_id];
- rte_eth_dev_info_get(port_id, &dev_info);
-
- num_vfs = dev_info.max_vfs;
- if (vf > num_vfs) {
- RTE_PMD_DEBUG_TRACE("set pool tx:invalid pool id=%d\n", vf);
- return -EINVAL;
- }
-
- RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_tx, -ENOTSUP);
- return (*dev->dev_ops->set_vf_tx)(dev, vf, on);
-}
-
-int
-rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id,
- uint64_t vf_mask, uint8_t vlan_on)
-{
- struct rte_eth_dev *dev;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
- dev = &rte_eth_devices[port_id];
-
- if (vlan_id > ETHER_MAX_VLAN_ID) {
- RTE_PMD_DEBUG_TRACE("VF VLAN filter:invalid VLAN id=%d\n",
- vlan_id);
- return -EINVAL;
- }
-
- if (vf_mask == 0) {
- RTE_PMD_DEBUG_TRACE("VF VLAN filter:pool_mask can not be 0\n");
- return -EINVAL;
- }
-
- RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_filter, -ENOTSUP);
- return (*dev->dev_ops->set_vf_vlan_filter)(dev, vlan_id,
- vf_mask, vlan_on);
-}
-
int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
uint16_t tx_rate)
{
@@ -2352,39 +2256,6 @@ int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
return (*dev->dev_ops->set_queue_rate_limit)(dev, queue_idx, tx_rate);
}
-int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate,
- uint64_t q_msk)
-{
- struct rte_eth_dev *dev;
- struct rte_eth_dev_info dev_info;
- struct rte_eth_link link;
-
- if (q_msk == 0)
- return 0;
-
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
-
- dev = &rte_eth_devices[port_id];
- rte_eth_dev_info_get(port_id, &dev_info);
- link = dev->data->dev_link;
-
- if (vf > dev_info.max_vfs) {
- RTE_PMD_DEBUG_TRACE("set VF rate limit:port %d: "
- "invalid vf id=%d\n", port_id, vf);
- return -EINVAL;
- }
-
- if (tx_rate > link.link_speed) {
- RTE_PMD_DEBUG_TRACE("set VF rate limit:invalid tx_rate=%d, "
- "bigger than link speed= %d\n",
- tx_rate, link.link_speed);
- return -EINVAL;
- }
-
- RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rate_limit, -ENOTSUP);
- return (*dev->dev_ops->set_vf_rate_limit)(dev, vf, tx_rate, q_msk);
-}
-
int
rte_eth_mirror_rule_set(uint8_t port_id,
struct rte_eth_mirror_conf *mirror_conf,
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..c602d7d 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1249,39 +1249,11 @@ typedef int (*eth_uc_all_hash_table_set_t)(struct rte_eth_dev *dev,
uint8_t on);
/**< @internal Set all Unicast Hash bitmap */
-typedef int (*eth_set_vf_rx_mode_t)(struct rte_eth_dev *dev,
- uint16_t vf,
- uint16_t rx_mode,
- uint8_t on);
-/**< @internal Set a VF receive mode */
-
-typedef int (*eth_set_vf_rx_t)(struct rte_eth_dev *dev,
- uint16_t vf,
- uint8_t on);
-/**< @internal Set a VF receive mode */
-
-typedef int (*eth_set_vf_tx_t)(struct rte_eth_dev *dev,
- uint16_t vf,
- uint8_t on);
-/**< @internal Enable or disable a VF transmit */
-
-typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev,
- uint16_t vlan,
- uint64_t vf_mask,
- uint8_t vlan_on);
-/**< @internal Set VF VLAN pool filter */
-
typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t tx_rate);
/**< @internal Set queue TX rate */
-typedef int (*eth_set_vf_rate_limit_t)(struct rte_eth_dev *dev,
- uint16_t vf,
- uint16_t tx_rate,
- uint64_t q_msk);
-/**< @internal Set VF TX rate */
-
typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev,
struct rte_eth_mirror_conf *mirror_conf,
uint8_t rule_id,
@@ -1479,16 +1451,11 @@ struct eth_dev_ops {
eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */
eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/
eth_mirror_rule_reset_t mirror_rule_reset; /**< reset a traffic mirror rule.*/
- eth_set_vf_rx_mode_t set_vf_rx_mode; /**< Set VF RX mode */
- eth_set_vf_rx_t set_vf_rx; /**< enable/disable a VF receive */
- eth_set_vf_tx_t set_vf_tx; /**< enable/disable a VF transmit */
- eth_set_vf_vlan_filter_t set_vf_vlan_filter; /**< Set VF VLAN filter */
/** Add UDP tunnel port. */
eth_udp_tunnel_port_add_t udp_tunnel_port_add;
/** Del UDP tunnel port. */
eth_udp_tunnel_port_del_t udp_tunnel_port_del;
eth_set_queue_rate_limit_t set_queue_rate_limit; /**< Set queue rate limit */
- eth_set_vf_rate_limit_t set_vf_rate_limit; /**< Set VF rate limit */
/** Update redirection table. */
reta_update_t reta_update;
/** Query redirection table. */
@@ -3403,93 +3370,6 @@ int rte_eth_dev_uc_hash_table_set(uint8_t port,struct ether_addr *addr,
*/
int rte_eth_dev_uc_all_hash_table_set(uint8_t port,uint8_t on);
- /**
- * Set RX L2 Filtering mode of a VF of an Ethernet device.
- *
- * @param port
- * The port identifier of the Ethernet device.
- * @param vf
- * VF id.
- * @param rx_mode
- * The RX mode mask, which is one or more of accepting Untagged Packets,
- * packets that match the PFUTA table, Broadcast and Multicast Promiscuous.
- * ETH_VMDQ_ACCEPT_UNTAG,ETH_VMDQ_ACCEPT_HASH_UC,
- * ETH_VMDQ_ACCEPT_BROADCAST and ETH_VMDQ_ACCEPT_MULTICAST will be used
- * in rx_mode.
- * @param on
- * 1 - Enable a VF RX mode.
- * 0 - Disable a VF RX mode.
- * @return
- * - (0) if successful.
- * - (-ENOTSUP) if hardware doesn't support.
- * - (-ENOTSUP) if hardware doesn't support.
- * - (-EINVAL) if bad parameter.
- */
-int rte_eth_dev_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mode,
- uint8_t on);
-
-/**
-* Enable or disable a VF traffic transmit of the Ethernet device.
-*
-* @param port
-* The port identifier of the Ethernet device.
-* @param vf
-* VF id.
-* @param on
-* 1 - Enable a VF traffic transmit.
-* 0 - Disable a VF traffic transmit.
-* @return
-* - (0) if successful.
-* - (-ENODEV) if *port_id* invalid.
-* - (-ENOTSUP) if hardware doesn't support.
-* - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_tx(uint8_t port,uint16_t vf, uint8_t on);
-
-/**
-* Enable or disable a VF traffic receive of an Ethernet device.
-*
-* @param port
-* The port identifier of the Ethernet device.
-* @param vf
-* VF id.
-* @param on
-* 1 - Enable a VF traffic receive.
-* 0 - Disable a VF traffic receive.
-* @return
-* - (0) if successful.
-* - (-ENOTSUP) if hardware doesn't support.
-* - (-ENODEV) if *port_id* invalid.
-* - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_rx(uint8_t port,uint16_t vf, uint8_t on);
-
-/**
-* Enable/Disable hardware VF VLAN filtering by an Ethernet device of
-* received VLAN packets tagged with a given VLAN Tag Identifier.
-*
-* @param port id
-* The port identifier of the Ethernet device.
-* @param vlan_id
-* The VLAN Tag Identifier whose filtering must be enabled or disabled.
-* @param vf_mask
-* Bitmap listing which VFs participate in the VLAN filtering.
-* @param vlan_on
-* 1 - Enable VFs VLAN filtering.
-* 0 - Disable VFs VLAN filtering.
-* @return
-* - (0) if successful.
-* - (-ENOTSUP) if hardware doesn't support.
-* - (-ENODEV) if *port_id* invalid.
-* - (-EINVAL) if bad parameter.
-*/
-int
-rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
- uint64_t vf_mask,
- uint8_t vlan_on);
-
/**
* Set a traffic mirroring rule on an Ethernet device
*
@@ -3551,26 +3431,6 @@ int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx,
uint16_t tx_rate);
/**
- * Set the rate limitation for a vf on an Ethernet device.
- *
- * @param port_id
- * The port identifier of the Ethernet device.
- * @param vf
- * VF id.
- * @param tx_rate
- * The tx rate allocated from the total link speed for this VF id.
- * @param q_msk
- * The queue mask which need to set the rate.
- * @return
- * - (0) if successful.
- * - (-ENOTSUP) if hardware doesn't support this feature.
- * - (-ENODEV) if *port_id* invalid.
- * - (-EINVAL) if bad parameter.
- */
-int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf,
- uint16_t tx_rate, uint64_t q_msk);
-
-/**
* Initialize bypass logic. This function needs to be called before
* executing any other bypass API.
*
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 72be66d..7594416 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -61,10 +61,6 @@ DPDK_2.2 {
rte_eth_dev_set_mtu;
rte_eth_dev_set_rx_queue_stats_mapping;
rte_eth_dev_set_tx_queue_stats_mapping;
- rte_eth_dev_set_vf_rx;
- rte_eth_dev_set_vf_rxmode;
- rte_eth_dev_set_vf_tx;
- rte_eth_dev_set_vf_vlan_filter;
rte_eth_dev_set_vlan_offload;
rte_eth_dev_set_vlan_pvid;
rte_eth_dev_set_vlan_strip_on_queue;
@@ -94,7 +90,6 @@ DPDK_2.2 {
rte_eth_rx_queue_info_get;
rte_eth_rx_queue_setup;
rte_eth_set_queue_rate_limit;
- rte_eth_set_vf_rate_limit;
rte_eth_stats;
rte_eth_stats_get;
rte_eth_stats_reset;
@@ -146,4 +141,4 @@ DPDK_16.11 {
rte_eth_dev_pci_probe;
rte_eth_dev_pci_remove;
-} DPDK_16.07;
+} DPDK_16.07;
\ No newline at end of file
--
2.10.1
^ permalink raw reply related
* [PATCH v3 7/9] net/ixgbe: remove static set VF functions
From: Bernard Iremonger @ 2016-12-12 13:50 UTC (permalink / raw)
To: thomas.monjalon, dev; +Cc: Bernard Iremonger
In-Reply-To: <1481304361-16032-1-git-send-email-bernard.iremonger@intel.com>
remove the following static functions:
ixgbe_set_pool_rx_mode
ixgbe_set_pool_rx
ixgbe_set_pool_tx
ixgbe_set_pool_vlan_filter
ixgbe_set_vf_rate_limit
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 193 ---------------------------------------
1 file changed, 193 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 37b82a4..8db1410 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -276,12 +276,6 @@ static void ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev);
static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct
ether_addr * mac_addr, uint8_t on);
static int ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on);
-static int ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool,
- uint16_t rx_mask, uint8_t on);
-static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on);
-static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
- uint64_t pool_mask, uint8_t vlan_on);
static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
struct rte_eth_mirror_conf *mirror_conf,
uint8_t rule_id, uint8_t on);
@@ -297,8 +291,6 @@ static void ixgbe_configure_msix(struct rte_eth_dev *dev);
static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
uint16_t queue_idx, uint16_t tx_rate);
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
- uint16_t tx_rate, uint64_t q_msk);
static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev,
struct ether_addr *mac_addr,
@@ -568,12 +560,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
.uc_all_hash_table_set = ixgbe_uc_all_hash_table_set,
.mirror_rule_set = ixgbe_mirror_rule_set,
.mirror_rule_reset = ixgbe_mirror_rule_reset,
- .set_vf_rx_mode = ixgbe_set_pool_rx_mode,
- .set_vf_rx = ixgbe_set_pool_rx,
- .set_vf_tx = ixgbe_set_pool_tx,
- .set_vf_vlan_filter = ixgbe_set_pool_vlan_filter,
.set_queue_rate_limit = ixgbe_set_queue_rate_limit,
- .set_vf_rate_limit = ixgbe_set_vf_rate_limit,
.reta_update = ixgbe_dev_rss_reta_update,
.reta_query = ixgbe_dev_rss_reta_query,
#ifdef RTE_NIC_BYPASS
@@ -4547,132 +4534,6 @@ ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val)
return new_val;
}
-static int
-ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool,
- uint16_t rx_mask, uint8_t on)
-{
- int val = 0;
-
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(pool));
-
- if (hw->mac.type == ixgbe_mac_82598EB) {
- PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
- " on 82599 hardware and newer");
- return -ENOTSUP;
- }
- if (ixgbe_vmdq_mode_check(hw) < 0)
- return -ENOTSUP;
-
- val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
-
- if (on)
- vmolr |= val;
- else
- vmolr &= ~val;
-
- IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr);
-
- return 0;
-}
-
-static int
-ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
- uint32_t reg, addr;
- uint32_t val;
- const uint8_t bit1 = 0x1;
-
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- if (ixgbe_vmdq_mode_check(hw) < 0)
- return -ENOTSUP;
-
- if (pool >= ETH_64_POOLS)
- return -EINVAL;
-
- /* for pool >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
- if (pool >= 32) {
- addr = IXGBE_VFRE(1);
- val = bit1 << (pool - 32);
- } else {
- addr = IXGBE_VFRE(0);
- val = bit1 << pool;
- }
-
- reg = IXGBE_READ_REG(hw, addr);
-
- if (on)
- reg |= val;
- else
- reg &= ~val;
-
- IXGBE_WRITE_REG(hw, addr, reg);
-
- return 0;
-}
-
-static int
-ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
-{
- uint32_t reg, addr;
- uint32_t val;
- const uint8_t bit1 = 0x1;
-
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- if (ixgbe_vmdq_mode_check(hw) < 0)
- return -ENOTSUP;
-
- if (pool >= ETH_64_POOLS)
- return -EINVAL;
-
- /* for pool >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
- if (pool >= 32) {
- addr = IXGBE_VFTE(1);
- val = bit1 << (pool - 32);
- } else {
- addr = IXGBE_VFTE(0);
- val = bit1 << pool;
- }
-
- reg = IXGBE_READ_REG(hw, addr);
-
- if (on)
- reg |= val;
- else
- reg &= ~val;
-
- IXGBE_WRITE_REG(hw, addr, reg);
-
- return 0;
-}
-
-static int
-ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
- uint64_t pool_mask, uint8_t vlan_on)
-{
- int ret = 0;
- uint16_t pool_idx;
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- if (ixgbe_vmdq_mode_check(hw) < 0)
- return -ENOTSUP;
- for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
- if (pool_mask & ((uint64_t)(1ULL << pool_idx))) {
- ret = hw->mac.ops.set_vfta(hw, vlan, pool_idx,
- vlan_on, false);
- if (ret < 0)
- return ret;
- }
- }
-
- return ret;
-}
int
rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
@@ -5628,60 +5489,6 @@ static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
return 0;
}
-static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
- uint16_t tx_rate, uint64_t q_msk)
-{
- struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct ixgbe_vf_info *vfinfo =
- *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
- uint8_t nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
- uint32_t queue_stride =
- IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active;
- uint32_t queue_idx = vf * queue_stride, idx = 0, vf_idx;
- uint32_t queue_end = queue_idx + nb_q_per_pool - 1;
- uint16_t total_rate = 0;
-
- if (queue_end >= hw->mac.max_tx_queues)
- return -EINVAL;
-
- if (vfinfo != NULL) {
- for (vf_idx = 0; vf_idx < dev->pci_dev->max_vfs; vf_idx++) {
- if (vf_idx == vf)
- continue;
- for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate);
- idx++)
- total_rate += vfinfo[vf_idx].tx_rate[idx];
- }
- } else
- return -EINVAL;
-
- /* Store tx_rate for this vf. */
- for (idx = 0; idx < nb_q_per_pool; idx++) {
- if (((uint64_t)0x1 << idx) & q_msk) {
- if (vfinfo[vf].tx_rate[idx] != tx_rate)
- vfinfo[vf].tx_rate[idx] = tx_rate;
- total_rate += tx_rate;
- }
- }
-
- if (total_rate > dev->data->dev_link.link_speed) {
- /*
- * Reset stored TX rate of the VF if it causes exceed
- * link speed.
- */
- memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate));
- return -EINVAL;
- }
-
- /* Set RTTBCNRC of each queue/pool for vf X */
- for (; queue_idx <= queue_end; queue_idx++) {
- if (0x1 & q_msk)
- ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate);
- q_msk = q_msk >> 1;
- }
-
- return 0;
-}
static void
ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
--
2.10.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox