aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@gmail.com>2018-11-19 12:59:01 +0000
committerLuca Boccassi <luca.boccassi@gmail.com>2018-11-19 12:59:24 +0000
commit29058550643267a554e0368806dece63b047c5cb (patch)
treea6f573fe3fbc14585529b83cfcc65da2dceefbf5
parent8a853e3f0275efc8b05cb195085d45946942744a (diff)
New upstream version 18.11-rc4upstream/18.11-rc4
Change-Id: I861e1a2f7df210f57f44f1ad56b9ef789a4675e3 Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
-rw-r--r--MAINTAINERS4
-rw-r--r--app/pdump/main.c10
-rw-r--r--app/test-pmd/cmdline_mtr.c8
-rw-r--r--app/test-pmd/testpmd.c34
-rw-r--r--config/arm/meson.build3
-rw-r--r--config/meson.build26
-rwxr-xr-xdevtools/check-symbol-change.sh3
-rw-r--r--doc/build-sdk-meson.txt8
-rw-r--r--doc/guides/cryptodevs/dpaa2_sec.rst28
-rw-r--r--doc/guides/cryptodevs/dpaa_sec.rst25
-rw-r--r--doc/guides/cryptodevs/octeontx.rst29
-rw-r--r--doc/guides/eventdevs/dpaa.rst48
-rw-r--r--doc/guides/eventdevs/dpaa2.rst50
-rw-r--r--doc/guides/linux_gsg/linux_drivers.rst7
-rw-r--r--doc/guides/linux_gsg/sys_reqs.rst19
-rw-r--r--doc/guides/nics/dpaa.rst59
-rw-r--r--doc/guides/nics/dpaa2.rst49
-rw-r--r--doc/guides/platform/dpaa.rst103
-rw-r--r--doc/guides/platform/dpaa2.rst109
-rw-r--r--doc/guides/platform/index.rst2
-rw-r--r--doc/guides/platform/octeontx.rst116
-rw-r--r--doc/guides/prog_guide/metrics_lib.rst9
-rw-r--r--doc/guides/rawdevs/dpaa2_cmdif.rst46
-rw-r--r--doc/guides/rawdevs/dpaa2_qdma.rst47
-rw-r--r--doc/guides/rel_notes/release_18_11.rst35
-rw-r--r--doc/guides/sample_app_ug/compiling.rst15
-rw-r--r--doc/guides/sample_app_ug/flow_filtering.rst2
-rw-r--r--doc/guides/sample_app_ug/ip_reassembly.rst4
-rw-r--r--doc/guides/sample_app_ug/ipv4_multicast.rst1
-rw-r--r--doc/guides/sample_app_ug/vm_power_management.rst25
-rw-r--r--drivers/bus/pci/linux/pci_vfio.c14
-rw-r--r--drivers/common/cpt/cpt_ucode.h37
-rw-r--r--drivers/net/avf/avf_rxtx.h4
-rw-r--r--drivers/net/bonding/rte_eth_bond_pmd.c13
-rw-r--r--drivers/net/ena/ena_ethdev.c7
-rw-r--r--drivers/net/i40e/i40e_ethdev.c37
-rw-r--r--drivers/net/ixgbe/base/ixgbe_common.c2
-rw-r--r--drivers/net/mlx4/mlx4_mr.c42
-rw-r--r--drivers/net/mlx4/mlx4_rxtx.h26
-rw-r--r--drivers/net/mlx5/mlx5_flow.c29
-rw-r--r--drivers/net/mlx5/mlx5_flow.h9
-rw-r--r--drivers/net/mlx5/mlx5_flow_dv.c183
-rw-r--r--drivers/net/mlx5/mlx5_flow_tcf.c321
-rw-r--r--drivers/net/mlx5/mlx5_flow_verbs.c47
-rw-r--r--drivers/net/mlx5/mlx5_mr.c39
-rw-r--r--drivers/net/mlx5/mlx5_rxq.c5
-rw-r--r--drivers/net/mlx5/mlx5_rxtx.h38
-rw-r--r--drivers/net/mlx5/mlx5_rxtx_vec_neon.h2
-rw-r--r--drivers/net/mlx5/mlx5_rxtx_vec_sse.h2
-rw-r--r--drivers/net/mlx5/mlx5_stats.c3
-rw-r--r--drivers/net/mvpp2/mrvl_mtr.c2
-rw-r--r--drivers/net/octeontx/octeontx_ethdev.c20
-rw-r--r--drivers/net/pcap/rte_eth_pcap.c205
-rw-r--r--examples/ipv4_multicast/main.c2
-rw-r--r--examples/vhost_crypto/main.c17
-rw-r--r--lib/librte_eal/common/eal_common_memalloc.c2
-rw-r--r--lib/librte_eal/common/eal_filesystem.h4
-rw-r--r--lib/librte_eal/common/include/rte_version.h2
-rw-r--r--lib/librte_eal/common/malloc_elem.c6
-rw-r--r--lib/librte_eal/linuxapp/eal/eal_dev.c12
-rw-r--r--lib/librte_eal/linuxapp/eal/eal_memalloc.c3
-rw-r--r--lib/librte_eal/linuxapp/eal/eal_memory.c4
-rw-r--r--lib/librte_efd/rte_efd.c3
-rw-r--r--lib/librte_security/Makefile1
-rw-r--r--lib/librte_security/meson.build1
-rw-r--r--lib/librte_security/rte_security.c18
-rw-r--r--lib/librte_security/rte_security.h27
-rw-r--r--lib/librte_security/rte_security_driver.h1
-rw-r--r--lib/librte_security/rte_security_version.map2
-rw-r--r--meson.build2
-rw-r--r--test/test/test_eal_flags.c94
-rw-r--r--test/test/test_interrupts.c2
-rw-r--r--test/test/test_pmd_ring_perf.c8
-rw-r--r--test/test/test_power_kvm_vm.c2
-rwxr-xr-xusertools/dpdk-devbind.py7
75 files changed, 1468 insertions, 763 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 19353ac8..71ba3120 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -233,7 +233,7 @@ F: drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
F: drivers/net/i40e/i40e_rxtx_vec_neon.c
F: drivers/net/virtio/virtio_rxtx_simple_neon.c
-IBM POWER
+IBM POWER (alpha)
M: Chao Zhu <chaozhu@linux.vnet.ibm.com>
F: lib/librte_eal/common/arch/ppc_64/
F: lib/librte_eal/common/include/arch/ppc_64/
@@ -347,7 +347,7 @@ F: lib/librte_cryptodev/
F: test/test/test_cryptodev*
F: examples/l2fwd-crypto/
-Security API - EXPERIMENTAL
+Security API
M: Akhil Goyal <akhil.goyal@nxp.com>
M: Declan Doherty <declan.doherty@intel.com>
T: git://dpdk.org/next/dpdk-next-crypto
diff --git a/app/pdump/main.c b/app/pdump/main.c
index d96556ec..9e86bf62 100644
--- a/app/pdump/main.c
+++ b/app/pdump/main.c
@@ -119,8 +119,8 @@ struct pdump_tuples {
/* params for packet dumping */
enum pdump_by dump_by_type;
- int rx_vdev_id;
- int tx_vdev_id;
+ uint16_t rx_vdev_id;
+ uint16_t tx_vdev_id;
enum pcap_stream rx_vdev_stream_type;
enum pcap_stream tx_vdev_stream_type;
bool single_pdump_dev;
@@ -266,7 +266,7 @@ parse_pdump(const char *optarg)
&parse_uint_value, &v);
if (ret < 0)
goto free_kvlist;
- pt->port = (uint8_t) v.val;
+ pt->port = (uint16_t) v.val;
pt->dump_by_type = PORT_ID;
} else if (cnt2 == 1) {
ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
@@ -435,7 +435,7 @@ disable_pdump(struct pdump_tuples *pt)
}
static inline void
-pdump_rxtx(struct rte_ring *ring, uint8_t vdev_id, struct pdump_stats *stats)
+pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
{
/* write input packets of port to vdev for pdump */
struct rte_mbuf *rxtx_bufs[BURST_SIZE];
@@ -462,7 +462,7 @@ pdump_rxtx(struct rte_ring *ring, uint8_t vdev_id, struct pdump_stats *stats)
}
static void
-free_ring_data(struct rte_ring *ring, uint8_t vdev_id,
+free_ring_data(struct rte_ring *ring, uint16_t vdev_id,
struct pdump_stats *stats)
{
while (rte_ring_count(ring))
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
index 846de88d..c506d87e 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -1148,15 +1148,15 @@ static void cmd_set_port_meter_dscp_table_parsed(void *parsed_result,
}
if (port_id_is_invalid(port_id, ENABLED_WARN))
- return;
+ goto free_table;
/* Update Meter DSCP Table*/
ret = rte_mtr_meter_dscp_table_update(port_id, mtr_id,
dscp_table, &error);
- if (ret != 0) {
+ if (ret != 0)
print_err_msg(&error);
- return;
- }
+
+free_table:
free(dscp_table);
}
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 9c0edcae..4c75587d 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -506,7 +506,7 @@ static void check_all_ports_link_status(uint32_t port_mask);
static int eth_event_callback(portid_t port_id,
enum rte_eth_event_type type,
void *param, void *ret_param);
-static void eth_dev_event_callback(const char *device_name,
+static void dev_event_callback(const char *device_name,
enum rte_dev_event_type type,
void *param);
@@ -2434,7 +2434,7 @@ pmd_test_exit(void)
}
ret = rte_dev_event_callback_unregister(NULL,
- eth_dev_event_callback, NULL);
+ dev_event_callback, NULL);
if (ret < 0) {
RTE_LOG(ERR, EAL,
"fail to unregister device event callback.\n");
@@ -2516,8 +2516,14 @@ check_all_ports_link_status(uint32_t port_mask)
}
}
+/*
+ * This callback is for remove a port for a device. It has limitation because
+ * it is not for multiple port removal for a device.
+ * TODO: the device detach invoke will plan to be removed from user side to
+ * eal. And convert all PMDs to free port resources on ether device closing.
+ */
static void
-rmv_event_callback(void *arg)
+rmv_port_callback(void *arg)
{
int need_to_start = 0;
int org_no_link_check = no_link_check;
@@ -2565,7 +2571,7 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
if (port_id_is_invalid(port_id, DISABLED_WARN))
break;
if (rte_eal_alarm_set(100000,
- rmv_event_callback, (void *)(intptr_t)port_id))
+ rmv_port_callback, (void *)(intptr_t)port_id))
fprintf(stderr, "Could not set up deferred device removal\n");
break;
default:
@@ -2598,7 +2604,7 @@ register_eth_event_callback(void)
/* This function is used by the interrupt thread */
static void
-eth_dev_event_callback(const char *device_name, enum rte_dev_event_type type,
+dev_event_callback(const char *device_name, enum rte_dev_event_type type,
__rte_unused void *arg)
{
uint16_t port_id;
@@ -2612,7 +2618,7 @@ eth_dev_event_callback(const char *device_name, enum rte_dev_event_type type,
switch (type) {
case RTE_DEV_EVENT_REMOVE:
- RTE_LOG(ERR, EAL, "The device: %s has been removed!\n",
+ RTE_LOG(DEBUG, EAL, "The device: %s has been removed!\n",
device_name);
ret = rte_eth_dev_get_port_by_name(device_name, &port_id);
if (ret) {
@@ -2620,7 +2626,19 @@ eth_dev_event_callback(const char *device_name, enum rte_dev_event_type type,
device_name);
return;
}
- rmv_event_callback((void *)(intptr_t)port_id);
+ /*
+ * Because the user's callback is invoked in eal interrupt
+ * callback, the interrupt callback need to be finished before
+ * it can be unregistered when detaching device. So finish
+ * callback soon and use a deferred removal to detach device
+ * is need. It is a workaround, once the device detaching be
+ * moved into the eal in the future, the deferred removal could
+ * be deleted.
+ */
+ if (rte_eal_alarm_set(100000,
+ rmv_port_callback, (void *)(intptr_t)port_id))
+ RTE_LOG(ERR, EAL,
+ "Could not set up deferred device removal\n");
break;
case RTE_DEV_EVENT_ADD:
RTE_LOG(ERR, EAL, "The device: %s has been added!\n",
@@ -3167,7 +3185,7 @@ main(int argc, char** argv)
}
ret = rte_dev_event_callback_register(NULL,
- eth_dev_event_callback, NULL);
+ dev_event_callback, NULL);
if (ret) {
RTE_LOG(ERR, EAL,
"fail to register device event callback\n");
diff --git a/config/arm/meson.build b/config/arm/meson.build
index 4b23b395..b7551385 100644
--- a/config/arm/meson.build
+++ b/config/arm/meson.build
@@ -89,6 +89,9 @@ if cc.sizeof('void *') != 8
dpdk_conf.set('RTE_CACHE_LINE_SIZE', 64)
dpdk_conf.set('RTE_ARCH_ARM', 1)
dpdk_conf.set('RTE_ARCH_ARMv7', 1)
+ # the minimum architecture supported, armv7-a, needs the following,
+ # mk/machine/armv7a/rte.vars.mk sets it too
+ machine_args += '-mfpu=neon'
else
dpdk_conf.set('RTE_CACHE_LINE_SIZE', 128)
dpdk_conf.set('RTE_ARCH_ARM64', 1)
diff --git a/config/meson.build b/config/meson.build
index 0b710b79..db32499b 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -7,10 +7,32 @@ if meson.is_cross_build()
else
machine = get_option('machine')
endif
+
+# machine type 'default' is special, it defaults to the per arch agreed common
+# minimal baseline needed for DPDK.
+# That might not be the most optimized, but the most portable version while
+# still being able to support the CPU features required for DPDK.
+# This can be bumped up by the DPDK project, but it can never be an
+# invariant like 'native'
+if machine == 'default'
+ if host_machine.cpu_family().startswith('x86')
+ # matches the old pre-meson build systems default
+ machine = 'corei7'
+ elif host_machine.cpu_family().startswith('arm')
+ machine = 'armv7-a'
+ elif host_machine.cpu_family().startswith('aarch')
+ # arm64 manages defaults in config/arm/meson.build
+ machine = 'default'
+ elif host_machine.cpu_family().startswith('ppc')
+ machine = 'power8'
+ endif
+endif
+
dpdk_conf.set('RTE_MACHINE', machine)
machine_args = []
-# ppc64 does not support -march=native
-if host_machine.cpu_family().startswith('ppc') and machine == 'native'
+
+# ppc64 does not support -march= at all, use -mcpu and -mtune for that
+if host_machine.cpu_family().startswith('ppc')
machine_args += '-mcpu=' + machine
machine_args += '-mtune=' + machine
else
diff --git a/devtools/check-symbol-change.sh b/devtools/check-symbol-change.sh
index c0d2a6da..1d21e916 100755
--- a/devtools/check-symbol-change.sh
+++ b/devtools/check-symbol-change.sh
@@ -23,7 +23,7 @@ build_map_changes()
# does not end in 'map', indicating we have left the map chunk.
# When we hit this, turn off the in_map variable, which
# supresses the subordonate rules below
- /[-+] a\/.*\.^(map)/ {in_map=0}
+ /[-+] a\/.*\.[^map]/ {in_map=0}
# Triggering this rule, which starts a line and ends it
# with a { identifies a versioned section. The section name is
@@ -153,7 +153,6 @@ clean_and_exit_on_sig()
build_map_changes "$patch" "$mapfile"
check_for_rule_violations "$mapfile"
exit_code=$?
-
rm -f "$mapfile"
exit $exit_code
diff --git a/doc/build-sdk-meson.txt b/doc/build-sdk-meson.txt
index 508e2cb6..a4dd0919 100644
--- a/doc/build-sdk-meson.txt
+++ b/doc/build-sdk-meson.txt
@@ -132,7 +132,7 @@ Installing the Compiled Files
Use ``ninja install`` to install the required DPDK files onto the system.
The install prefix defaults to ``/usr/local`` but can be used as with other
-options above. The environment variable ``DEST_DIR`` can be used to adjust
+options above. The environment variable ``DESTDIR`` can be used to adjust
the root directory for the install, for example when packaging.
With the base install directory, the individual directories for libraries
@@ -203,3 +203,9 @@ From examples/helloworld/Makefile::
build:
@mkdir -p $@
+
+NOTE: for --static builds, DPDK needs to be built with Meson >= 0.46 in order to
+fully generate the list of private dependencies. If DPDK is built with an older
+version of Meson, it might be necessary to manually specify dependencies of DPDK
+PMDs/libraries, for example -lmlx5 -lmnl for librte-pmd-mlx5, or the static link
+step might fail.
diff --git a/doc/guides/cryptodevs/dpaa2_sec.rst b/doc/guides/cryptodevs/dpaa2_sec.rst
index 9191704e..aee79ab4 100644
--- a/doc/guides/cryptodevs/dpaa2_sec.rst
+++ b/doc/guides/cryptodevs/dpaa2_sec.rst
@@ -129,7 +129,7 @@ AEAD algorithms:
Supported DPAA2 SoCs
--------------------
-* LS2080A/LS2040A
+* LS2160A
* LS2084A/LS2044A
* LS2088A/LS2048A
* LS1088A/LS1048A
@@ -157,31 +157,15 @@ Prerequisites
DPAA2_SEC driver has similar pre-requisites as described in :ref:`dpaa2_overview`.
The following dependencies are not part of DPDK and must be installed separately:
-* **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for the family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-* **DPDK Extra Scripts**
-
- DPAA2 based resources can be configured easily with the help of ready scripts
- as provided in the DPDK helper repository.
-
- `DPDK Extra Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa2` for setup information
Currently supported by DPDK:
-* NXP SDK **17.08+**.
-* MC Firmware version **10.3.1** and higher.
-* Supported architectures: **arm64 LE**.
+- NXP SDK **18.09+**.
+- MC Firmware version **10.10.0** and higher.
+- Supported architectures: **arm64 LE**.
-* Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
+- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
Pre-Installation Configuration
------------------------------
diff --git a/doc/guides/cryptodevs/dpaa_sec.rst b/doc/guides/cryptodevs/dpaa_sec.rst
index dd683894..897a4fe8 100644
--- a/doc/guides/cryptodevs/dpaa_sec.rst
+++ b/doc/guides/cryptodevs/dpaa_sec.rst
@@ -101,32 +101,11 @@ Prerequisites
-------------
DPAA_SEC driver has similar pre-requisites as described in :ref:`dpaa_overview`.
-The following dependencies are not part of DPDK and must be installed separately:
-* **NXP Linux SDK**
+See :doc:`../platform/dpaa` for setup information
- NXP Linux software development kit (SDK) includes support for the family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-* **DPDK Extras Scripts**
-
- DPAA based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extras repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
-
-Currently supported by DPDK:
-
-* NXP SDK **2.0+**.
-* Supported architectures: **arm64 LE**.
-
-* Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
+- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
Pre-Installation Configuration
------------------------------
diff --git a/doc/guides/cryptodevs/octeontx.rst b/doc/guides/cryptodevs/octeontx.rst
index 660e980c..1600a56d 100644
--- a/doc/guides/cryptodevs/octeontx.rst
+++ b/doc/guides/cryptodevs/octeontx.rst
@@ -53,11 +53,8 @@ AEAD Algorithms
* ``RTE_CRYPTO_AEAD_AES_GCM``
-Compilation
------------
-
-The **OCTEON TX** :sup:`®` board must be running the linux kernel based on
-sdk-6.2.0 patch 3. In this, the OCTEON TX crypto PF driver is already built in.
+Config flags
+------------
For compiling the OCTEON TX crypto poll mode driver, please check if the
CONFIG_RTE_LIBRTE_PMD_OCTEONTX_CRYPTO setting is set to `y` in
@@ -65,23 +62,21 @@ config/common_base file.
* ``CONFIG_RTE_LIBRTE_PMD_OCTEONTX_CRYPTO=y``
-The following are the steps to compile the OCTEON TX crypto poll mode driver:
+Compilation
+-----------
-.. code-block:: console
+The OCTEON TX crypto poll mode driver can be compiled either natively on
+**OCTEON TX** :sup:`®` board or cross-compiled on an x86 based platform.
- cd <dpdk directory>
- make config T=arm64-thunderx-linuxapp-gcc
- make
+Refer :doc:`../platform/octeontx` for details about setting up the platform
+and building DPDK applications.
-The example applications can be compiled using the following:
+.. note::
-.. code-block:: console
+ OCTEON TX crypto PF driver needs microcode to be available at `/lib/firmware/` directory.
+ Refer SDK documents for further information.
- cd <dpdk directory>
- export RTE_SDK=$PWD
- export RTE_TARGET=build
- cd examples/<application>
- make
+SDK and related information can be obtained from: `Cavium support site <https://support.cavium.com/>`_.
Execution
---------
diff --git a/doc/guides/eventdevs/dpaa.rst b/doc/guides/eventdevs/dpaa.rst
index 2f356d3c..cfc40347 100644
--- a/doc/guides/eventdevs/dpaa.rst
+++ b/doc/guides/eventdevs/dpaa.rst
@@ -25,57 +25,17 @@ The DPAA EVENTDEV implements many features in the eventdev API;
Supported DPAA SoCs
--------------------
-- LS1046A
-- LS1043A
+- LS1046A/LS1026A
+- LS1043A/LS1023A
Prerequisites
-------------
-There are following pre-requisites for executing EVENTDEV on a DPAA compatible
-platform:
-
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/6.4-2017.08/aarch64-linux-gnu/>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile System**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-As an alternative method, DPAA EVENTDEV can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-- **DPDK Extra Scripts**
-
- DPAA based resources can be configured easily with the help of ready to use
- xml files as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa` for setup information
Currently supported by DPDK:
-- NXP SDK **2.0+** or LSDK **17.09+**
+- NXP SDK **2.0+** or LSDK **18.09+**
- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
diff --git a/doc/guides/eventdevs/dpaa2.rst b/doc/guides/eventdevs/dpaa2.rst
index ad94f24b..2b1700a5 100644
--- a/doc/guides/eventdevs/dpaa2.rst
+++ b/doc/guides/eventdevs/dpaa2.rst
@@ -26,7 +26,7 @@ The DPAA2 EVENTDEV implements many features in the eventdev API;
Supported DPAA2 SoCs
--------------------
-- LS2080A/LS2040A
+- LX2160A
- LS2084A/LS2044A
- LS2088A/LS2048A
- LS1088A/LS1048A
@@ -34,52 +34,12 @@ Supported DPAA2 SoCs
Prerequisites
-------------
-There are three main pre-requisities for executing DPAA2 EVENTDEV on a DPAA2
-compatible board:
-
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/aarch64-linux-gnu>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile system**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-As an alternative method, DPAA2 EVENTDEV can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA2 board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-- **DPDK Extra Scripts**
-
- DPAA2 based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa2` for setup information
Currently supported by DPDK:
-- NXP SDK **2.0+**.
-- MC Firmware version **10.0.0** and higher.
+- NXP SDK **18.09+**.
+- MC Firmware version **10.10.0** and higher.
- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
@@ -155,4 +115,4 @@ DPAA2 drivers for DPDK can only work on NXP SoCs as listed in the
Port-core binding
~~~~~~~~~~~~~~~~~
-DPAA2 EVENTDEV driver requires event port 'x' to be used on core 'x'.
+DPAA2 EVENTDEV can support only one eventport per core.
diff --git a/doc/guides/linux_gsg/linux_drivers.rst b/doc/guides/linux_gsg/linux_drivers.rst
index 371a817f..8da6a31b 100644
--- a/doc/guides/linux_gsg/linux_drivers.rst
+++ b/doc/guides/linux_gsg/linux_drivers.rst
@@ -48,6 +48,13 @@ be loaded as shown below:
``vfio-pci`` kernel module rather than ``igb_uio`` or ``uio_pci_generic``.
For more details see :ref:`linux_gsg_binding_kernel` below.
+.. note::
+
+ If the devices used for DPDK are bound to the ``uio_pci_generic`` kernel module,
+ please make sure that the IOMMU is disabled or passthrough. One can add
+ ``intel_iommu=off`` or ``amd_iommu=off`` or ``intel_iommu=on iommu=pt``in GRUB
+ command line on x86_64 systems, or add ``iommu.passthrough=1`` on arm64 system.
+
Since DPDK release 1.7 onward provides VFIO support, use of UIO is optional
for platforms that support using VFIO.
diff --git a/doc/guides/linux_gsg/sys_reqs.rst b/doc/guides/linux_gsg/sys_reqs.rst
index e2230f37..29c5f47a 100644
--- a/doc/guides/linux_gsg/sys_reqs.rst
+++ b/doc/guides/linux_gsg/sys_reqs.rst
@@ -64,7 +64,11 @@ Compilation of the DPDK
x86_x32 ABI is currently supported with distribution packages only on Ubuntu
higher than 13.10 or recent Debian distribution. The only supported compiler is gcc 4.9+.
-* libnuma-devel - library for handling NUMA (Non Uniform Memory Access).
+* Library for handling NUMA (Non Uniform Memory Access).
+
+ * numactl-devel in Red Hat/Fedora;
+
+ * libnuma-dev in Debian/Ubuntu;
* Python, version 2.7+ or 3.2+, to use various helper scripts included in the DPDK package.
@@ -103,6 +107,13 @@ System Software
uname -r
+.. note::
+
+ Kernel version 3.2 is no longer a kernel.org longterm stable kernel.
+ For DPDK 19.02 the minimum required kernel will be updated to
+ the current kernel.org oldest longterm stable supported kernel 3.16,
+ or recent versions of common distributions, notably RHEL/CentOS 7.
+
* glibc >= 2.7 (for features related to cpuset)
The version can be checked using the ``ldd --version`` command.
@@ -183,12 +194,6 @@ On a NUMA machine, pages should be allocated explicitly on separate nodes::
For 1G pages, it is not possible to reserve the hugepage memory after the system has booted.
- On IBM POWER system, the nr_overcommit_hugepages should be set to the same value as nr_hugepages.
- For example, if the required page number is 128, the following commands are used::
-
- echo 128 > /sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages
- echo 128 > /sys/kernel/mm/hugepages/hugepages-16384kB/nr_overcommit_hugepages
-
Using Hugepages with the DPDK
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/guides/nics/dpaa.rst b/doc/guides/nics/dpaa.rst
index 620c045d..2173673b 100644
--- a/doc/guides/nics/dpaa.rst
+++ b/doc/guides/nics/dpaa.rst
@@ -181,65 +181,8 @@ Supported DPAA SoCs
Prerequisites
-------------
-There are three main pre-requisities for executing DPAA PMD on a DPAA
-compatible board:
+See :doc:`../platform/dpaa` for setup information
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/6.4-2017.08/aarch64-linux-gnu/>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile system**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-4. **FMC Tool**
-
- Before any DPDK application can be executed, the Frame Manager Configuration
- Tool (FMC) need to be executed to set the configurations of the queues. This
- includes the queue state, RSS and other policies.
- This tool can be obtained from `NXP (Freescale) Public Git Repository <https://github.com/qoriq-open-source/fmc>`_.
-
- This tool needs configuration files which are available in the
- :ref:`DPDK Extra Scripts <extra_scripts>`, described below for DPDK usages.
-
-As an alternative method, DPAA PMD can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-
-.. _extra_scripts:
-
-- **DPDK Extra Scripts**
-
- DPAA based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
-
-Currently supported by DPDK:
-
-- NXP SDK **2.0+**.
-- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>`
to setup the basic DPDK environment.
diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst
index e2f385d4..769dc4e1 100644
--- a/doc/guides/nics/dpaa2.rst
+++ b/doc/guides/nics/dpaa2.rst
@@ -409,8 +409,7 @@ Features of the DPAA2 PMD are:
Supported DPAA2 SoCs
--------------------
-
-- LS2080A/LS2040A
+- LX2160A
- LS2084A/LS2044A
- LS2088A/LS2048A
- LS1088A/LS1048A
@@ -418,52 +417,12 @@ Supported DPAA2 SoCs
Prerequisites
-------------
-There are three main pre-requisities for executing DPAA2 PMD on a DPAA2
-compatible board:
-
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/6.4-2017.08/aarch64-linux-gnu/>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile system**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-As an alternative method, DPAA2 PMD can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA2 board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-- **DPDK Extra Scripts**
-
- DPAA2 based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa2` for setup information
Currently supported by DPDK:
-- NXP SDK **17.08+**.
-- MC Firmware version **10.3.1** and higher.
+- NXP SDK **18.09+**.
+- MC Firmware version **10.10.0** and higher.
- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
diff --git a/doc/guides/platform/dpaa.rst b/doc/guides/platform/dpaa.rst
new file mode 100644
index 00000000..39048715
--- /dev/null
+++ b/doc/guides/platform/dpaa.rst
@@ -0,0 +1,103 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2018 NXP
+
+NXP QorIQ DPAA Board Support Package
+====================================
+
+This doc has information about steps to setup QorIq dpaa
+based layerscape platform and information about common offload
+hw block drivers of **NXP QorIQ DPAA** SoC family.
+
+Supported DPAA SoCs
+--------------------
+
+* LS1046A/LS1026A
+* LS1043A/LS1023A
+
+More information about SoC can be found at `NXP Official Website
+<https://www.nxp.com/products/processors-and-microcontrollers/arm-based-
+processors-and-mcus/qoriq-layerscape-arm-processors:QORIQ-ARM>`_.
+
+
+Common Offload HW Block Drivers
+-------------------------------
+
+1. **Nics Driver**
+
+ See :doc:`../nics/dpaa` for NXP dpaa nic driver information.
+
+2. **Cryptodev Driver**
+
+ See :doc:`../cryptodevs/dpaa_sec` for NXP dpaa cryptodev driver information.
+
+3. **Eventdev Driver**
+
+ See :doc:`../eventdevs/dpaa` for NXP dpaa eventdev driver information.
+
+
+Steps To Setup Platform
+-----------------------
+
+There are four main pre-requisities for executing DPAA PMD on a DPAA
+compatible board:
+
+1. **ARM 64 Tool Chain**
+
+ For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu.tar.xz>`_.
+
+2. **Linux Kernel**
+
+ It can be obtained from `NXP's Github hosting <https://source.codeaurora.org/external/qoriq/qoriq-components/linux>`_.
+
+3. **Rootfile system**
+
+ Any *aarch64* supporting filesystem can be used. For example,
+ Ubuntu 16.04 LTS (Xenial) or 18.04 (Bionic) userland which can be obtained
+ from `here
+ <http://cdimage.ubuntu.com/ubuntu-base/releases/18.04/release/ubuntu-base-18.04.1-base-arm64.tar.gz>`_.
+
+4. **FMC Tool**
+
+ Before any DPDK application can be executed, the Frame Manager Configuration
+ Tool (FMC) need to be executed to set the configurations of the queues. This
+ includes the queue state, RSS and other policies.
+ This tool can be obtained from `NXP (Freescale) Public Git Repository <https://source.codeaurora.org/external/qoriq/qoriq-components/fmc>`_.
+
+ This tool needs configuration files which are available in the
+ :ref:`DPDK Extra Scripts <extra_scripts>`, described below for DPDK usages.
+
+As an alternative method, DPAA PMD can also be executed using images provided
+as part of SDK from NXP. The SDK includes all the above prerequisites necessary
+to bring up a DPAA board.
+
+The following dependencies are not part of DPDK and must be installed
+separately:
+
+- **NXP Linux SDK**
+
+ NXP Linux software development kit (SDK) includes support for family
+ of QorIQ® ARM-Architecture-based system on chip (SoC) processors
+ and corresponding boards.
+
+ It includes the Linux board support packages (BSPs) for NXP SoCs,
+ a fully operational tool chain, kernel and board specific modules.
+
+ SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
+
+
+.. _extra_scripts:
+
+- **DPDK Extra Scripts**
+
+ DPAA based resources can be configured easily with the help of ready scripts
+ as provided in the DPDK Extra repository.
+
+ `DPDK Extras Scripts <https://source.codeaurora.org/external/qoriq/qoriq-components/dpdk-extras>`_.
+
+Currently supported by DPDK:
+
+- NXP SDK **2.0+** (preferred: LSDK 18.09).
+- Supported architectures: **arm64 LE**.
+
+- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>`
+ to setup the basic DPDK environment.
diff --git a/doc/guides/platform/dpaa2.rst b/doc/guides/platform/dpaa2.rst
new file mode 100644
index 00000000..5a64406e
--- /dev/null
+++ b/doc/guides/platform/dpaa2.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2018 NXP
+
+NXP QorIQ DPAA2 Board Support Package
+=====================================
+
+This doc has information about steps to setup NXP QoriQ DPAA2 platform
+and information about common offload hw block drivers of
+**NXP QorIQ DPAA2** SoC family.
+
+Supported DPAA2 SoCs
+--------------------
+
+- LX2160A
+- LS2084A/LS2044A
+- LS2088A/LS2048A
+- LS1088A/LS1048A
+
+More information about SoC can be found at `NXP Official Website
+<https://www.nxp.com/products/processors-and-microcontrollers/arm-based-
+processors-and-mcus/qoriq-layerscape-arm-processors:QORIQ-ARM>`_.
+
+
+Common Offload HW Block Drivers
+-------------------------------
+
+1. **Nics Driver**
+
+ See :doc:`../nics/dpaa2` for NXP dpaa2 nic driver information.
+
+2. **Cryptodev Driver**
+
+ See :doc:`../cryptodevs/dpaa2_sec` for NXP dpaa2 cryptodev driver information.
+
+3. **Eventdev Driver**
+
+ See :doc:`../eventdevs/dpaa2` for NXP dpaa2 eventdev driver information.
+
+4. **Rawdev AIOP CMDIF Driver**
+
+ See :doc:`../rawdevs/dpaa2_cmdif` for NXP dpaa2 AIOP command interface driver information.
+
+5. **Rawdev QDMA Driver**
+
+ See :doc:`../rawdevs/dpaa2_qdma` for NXP dpaa2 QDMA driver information.
+
+
+Steps To Setup Platform
+-----------------------
+
+There are four main pre-requisities for executing DPAA2 PMD on a DPAA2
+compatible board:
+
+1. **ARM 64 Tool Chain**
+
+ For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu.tar.xz>`_.
+
+2. **Linux Kernel**
+
+ It can be obtained from `NXP's Github hosting <https://source.codeaurora.org/external/qoriq/qoriq-components/linux>`_.
+
+3. **Rootfile system**
+
+ Any *aarch64* supporting filesystem can be used. For example,
+ Ubuntu 16.04 LTS (Xenial) or 18.04 (Bionic) userland which can be obtained
+ from `here
+ <http://cdimage.ubuntu.com/ubuntu-base/releases/18.04/release/ubuntu-base-18.04.1-base-arm64.tar.gz>`_.
+
+4. **Resource Scripts**
+
+ DPAA2 based resources can be configured easily with the help of ready scripts
+ as provided in the DPDK Extra repository.
+
+As an alternative method, DPAA2 PMD can also be executed using images provided
+as part of SDK from NXP. The SDK includes all the above prerequisites necessary
+to bring up a DPAA2 board.
+
+The following dependencies are not part of DPDK and must be installed
+separately:
+
+- **NXP Linux SDK**
+
+ NXP Linux software development kit (SDK) includes support for family
+ of QorIQ® ARM-Architecture-based system on chip (SoC) processors
+ and corresponding boards.
+
+ It includes the Linux board support packages (BSPs) for NXP SoCs,
+ a fully operational tool chain, kernel and board specific modules.
+
+ SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
+
+
+.. _extra_scripts:
+
+- **DPDK Extra Scripts**
+
+ DPAA2 based resources can be configured easily with the help of ready scripts
+ as provided in the DPDK Extra repository.
+
+ `DPDK Extras Scripts <https://source.codeaurora.org/external/qoriq/qoriq-components/dpdk-extras>`_.
+
+Currently supported by DPDK:
+
+- NXP SDK **2.0+** (preferred: LSDK 18.09).
+- MC Firmware version **10.10.0** and higher.
+- Supported architectures: **arm64 LE**.
+
+- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>`
+ to setup the basic DPDK environment.
diff --git a/doc/guides/platform/index.rst b/doc/guides/platform/index.rst
index ca6113d6..98c66389 100644
--- a/doc/guides/platform/index.rst
+++ b/doc/guides/platform/index.rst
@@ -10,4 +10,6 @@ The following are platform specific guides and setup information.
:maxdepth: 2
:numbered:
+ dpaa
+ dpaa2
octeontx
diff --git a/doc/guides/platform/octeontx.rst b/doc/guides/platform/octeontx.rst
index 9f75d2a8..3bde91f9 100644
--- a/doc/guides/platform/octeontx.rst
+++ b/doc/guides/platform/octeontx.rst
@@ -15,11 +15,15 @@ More information about SoC can be found at `Cavium, Inc Official Website
Common Offload HW Block Drivers
-------------------------------
-1. **Eventdev Driver**
+1. **Crypto Driver**
+ See :doc:`../cryptodevs/octeontx` for octeontx crypto driver
+ information.
+
+2. **Eventdev Driver**
See :doc:`../eventdevs/octeontx` for octeontx ssovf eventdev driver
information.
-2. **Mempool Driver**
+3. **Mempool Driver**
See :doc:`../mempool/octeontx` for octeontx fpavf mempool driver
information.
@@ -35,6 +39,12 @@ OCTEON TX compatible board:
Platform drivers) are available on Github at `octeontx-kmod <https://github.com/caviumnetworks/octeontx-kmod>`_
along with build, install and dpdk usage instructions.
+.. note::
+
+ The PF driver and the required microcode for the crypto offload block will be
+ available with OCTEON TX SDK only. So for using crypto offload, follow the steps
+ mentioned in :ref:`setup_platform_using_OCTEON_TX_SDK`.
+
2. **ARM64 Tool Chain**
For example, the *aarch64* Linaro Toolchain, which can be obtained from
@@ -48,8 +58,104 @@ OCTEON TX compatible board:
As an alternative method, Platform drivers can also be executed using images provided
as part of SDK from Cavium. The SDK includes all the above prerequisites necessary
- to bring up a OCTEON TX board.
-
- SDK and related information can be obtained from: `Cavium support site <https://support.cavium.com/>`_.
+ to bring up a OCTEON TX board. Please refer :ref:`setup_platform_using_OCTEON_TX_SDK`.
- Follow the DPDK :doc:`../linux_gsg/index` to setup the basic DPDK environment.
+
+.. _setup_platform_using_OCTEON_TX_SDK:
+
+Setup Platform Using OCTEON TX SDK
+----------------------------------
+
+The OCTEON TX platform drivers can be compiled either natively on
+**OCTEON TX** :sup:`®` board or cross-compiled on an x86 based platform.
+
+The **OCTEON TX** :sup:`®` board must be running the linux kernel based on
+OCTEON TX SDK 6.2.0 patch 3. In this, the PF drivers for all hardware
+offload blocks are already built in.
+
+Native Compilation
+~~~~~~~~~~~~~~~~~~
+
+If the kernel and modules are cross-compiled and copied to the target board,
+some intermediate binaries required for native build would be missing on the
+target board. To make sure all the required binaries are available in the
+native architecture, the linux sources need to be compiled once natively.
+
+.. code-block:: console
+
+ cd /lib/modules/$(uname -r)/source
+ make menuconfig
+ make
+
+The above steps would rebuild the modules and the required intermediate binaries.
+Once the target is ready for native compilation, the OCTEON TX platform
+drivers can be compiled with the following steps,
+
+.. code-block:: console
+
+ cd <dpdk directory>
+ make config T=arm64-thunderx-linuxapp-gcc
+ make
+
+The example applications can be compiled using the following:
+
+.. code-block:: console
+
+ cd <dpdk directory>
+ export RTE_SDK=$PWD
+ export RTE_TARGET=build
+ cd examples/<application>
+ make
+
+Cross Compilation
+~~~~~~~~~~~~~~~~~
+
+The DPDK applications can be cross-compiled on any x86 based platform. The
+OCTEON TX SDK need to be installed on the build system. The SDK package will
+provide the required toolchain etc.
+
+Refer to :doc:`../linux_gsg/cross_build_dpdk_for_arm64` for further steps on
+compilation. The 'host' & 'CC' to be used in the commands would change,
+in addition to the paths to which libnuma related files have to be
+copied.
+
+The following steps can be used to perform cross-compilation with OCTEON TX
+SDK 6.2.0 patch 3:
+
+.. code-block:: console
+
+ cd <sdk_install_dir>
+ source env-setup
+
+ git clone https://github.com/numactl/numactl.git
+ cd numactl
+ git checkout v2.0.11 -b v2.0.11
+ ./autogen.sh
+ autoconf -i
+ ./configure --host=aarch64-thunderx-linux CC=aarch64-thunderx-linux-gnu-gcc --prefix=<numa install dir>
+ make install
+
+The above steps will prepare build system with numa additions. Now this build system can be used
+to build applications for **OCTEON TX** :sup:`®` platforms.
+
+.. code-block:: console
+
+ cd <dpdk directory>
+ export RTE_SDK=$PWD
+ export RTE_KERNELDIR=$THUNDER_ROOT/linux/kernel/linux
+ make config T=arm64-thunderx-linuxapp-gcc
+ make -j CROSS=aarch64-thunderx-linux-gnu- CONFIG_RTE_KNI_KMOD=n CONFIG_RTE_EAL_IGB_UIO=n EXTRA_CFLAGS="-isystem <numa_install_dir>/include" EXTRA_LDFLAGS="-L<numa_install_dir>/lib -lnuma"
+
+If NUMA support is not required, it can be disabled as explained in
+:doc:`../linux_gsg/cross_build_dpdk_for_arm64`.
+
+Following steps could be used in that case.
+
+.. code-block:: console
+
+ make config T=arm64-thunderx-linuxapp-gcc
+ make CROSS=aarch64-thunderx-linux-gnu-
+
+
+SDK and related information can be obtained from: `Cavium support site <https://support.cavium.com/>`_.
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
index 5cbe17c9..e68e4e74 100644
--- a/doc/guides/prog_guide/metrics_lib.rst
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -271,3 +271,12 @@ de-initialise the latency library.
.. code-block:: c
rte_latencystats_uninit();
+
+Timestamp and latency calculation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Latency stats library marks the time in the timestamp field of the
+mbuf for the ingress packets and sets the ``PKT_RX_TIMESTAMP`` flag of
+``ol_flags`` for the mbuf to indicate the marked time as a valid one.
+At the egress, the mbufs with the flag set are considered having valid
+timestamp and are used for the latency calculation.
diff --git a/doc/guides/rawdevs/dpaa2_cmdif.rst b/doc/guides/rawdevs/dpaa2_cmdif.rst
index 20a60993..bebda833 100644
--- a/doc/guides/rawdevs/dpaa2_cmdif.rst
+++ b/doc/guides/rawdevs/dpaa2_cmdif.rst
@@ -29,52 +29,12 @@ Supported DPAA2 SoCs
Prerequisites
-------------
-There are three main pre-requisities for executing DPAA2 CMDIF on a DPAA2
-compatible board:
-
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/aarch64-linux-gnu>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile system**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-As an alternative method, DPAA2 CMDIF can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA2 board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-- **DPDK Extra Scripts**
-
- DPAA2 based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa2` for setup information
Currently supported by DPDK:
-- NXP SDK **2.0+**.
-- MC Firmware version **10.0.0** and higher.
+- NXP SDK **18.09+**.
+- MC Firmware version **10.10.0** and higher.
- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
diff --git a/doc/guides/rawdevs/dpaa2_qdma.rst b/doc/guides/rawdevs/dpaa2_qdma.rst
index b9bc4ec6..793a8513 100644
--- a/doc/guides/rawdevs/dpaa2_qdma.rst
+++ b/doc/guides/rawdevs/dpaa2_qdma.rst
@@ -25,6 +25,7 @@ The DPAA2 QDMA implements following features in the rawdev API;
Supported DPAA2 SoCs
--------------------
+- LX2160A
- LS2084A/LS2044A
- LS2088A/LS2048A
- LS1088A/LS1048A
@@ -32,52 +33,12 @@ Supported DPAA2 SoCs
Prerequisites
-------------
-There are three main pre-requisities for executing DPAA2 QDMA on a DPAA2
-compatible board:
-
-1. **ARM 64 Tool Chain**
-
- For example, the `*aarch64* Linaro Toolchain <https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/aarch64-linux-gnu>`_.
-
-2. **Linux Kernel**
-
- It can be obtained from `NXP's Github hosting <https://github.com/qoriq-open-source/linux>`_.
-
-3. **Rootfile system**
-
- Any *aarch64* supporting filesystem can be used. For example,
- Ubuntu 15.10 (Wily) or 16.04 LTS (Xenial) userland which can be obtained
- from `here <http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04.1-base-arm64.tar.gz>`_.
-
-As an alternative method, DPAA2 QDMA can also be executed using images provided
-as part of SDK from NXP. The SDK includes all the above prerequisites necessary
-to bring up a DPAA2 board.
-
-The following dependencies are not part of DPDK and must be installed
-separately:
-
-- **NXP Linux SDK**
-
- NXP Linux software development kit (SDK) includes support for family
- of QorIQ® ARM-Architecture-based system on chip (SoC) processors
- and corresponding boards.
-
- It includes the Linux board support packages (BSPs) for NXP SoCs,
- a fully operational tool chain, kernel and board specific modules.
-
- SDK and related information can be obtained from: `NXP QorIQ SDK <http://www.nxp.com/products/software-and-tools/run-time-software/linux-sdk/linux-sdk-for-qoriq-processors:SDKLINUX>`_.
-
-- **DPDK Extra Scripts**
-
- DPAA2 based resources can be configured easily with the help of ready scripts
- as provided in the DPDK Extra repository.
-
- `DPDK Extras Scripts <https://github.com/qoriq-open-source/dpdk-extras>`_.
+See :doc:`../platform/dpaa2` for setup information
Currently supported by DPDK:
-- NXP LSDK **17.12+**.
-- MC Firmware version **10.3.0** and higher.
+- NXP SDK **18.09+**.
+- MC Firmware version **10.10.0** and higher.
- Supported architectures: **arm64 LE**.
- Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 51d00758..32ff0e5c 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -279,6 +279,25 @@ New Features
their telemetry via a UNIX socket in JSON. The JSON can be consumed by any
Service Assurance agent, such as CollectD.
+* **Updated KNI kernel module, rte_kni library, and KNI sample application.**
+
+ Updated the KNI kernel module with a new kernel module parameter,
+ ``carrier=[on|off]`` to allow the user to control the default carrier
+ state of KNI kernel network interfaces. The default carrier state
+ is now set to ``off``, so the interfaces cannot be used until the
+ carrier state is set to ``on`` via ``rte_kni_update_link`` or
+ by writing ``1`` to ``/sys/devices/virtual/net/<iface>/carrier``.
+ In previous versions the default carrier state was left undefined.
+ See :doc:`../prog_guide/kernel_nic_interface` for more information.
+
+ Added the new API function ``rte_kni_update_link`` to allow the user
+ to set the carrier state of the KNI kernel network interface.
+
+ Added a new command line flag ``-m`` to the KNI sample application to
+ monitor and automatically reflect the physical NIC carrier state to the
+ KNI kernel network interface with the new ``rte_kni_update_link`` API.
+ See :doc:`../sample_app_ug/kernel_nic_interface` for more information.
+
* **Added ability to switch queue deferred start flag on testpmd app.**
Added a console command to testpmd app, giving ability to switch
@@ -385,6 +404,20 @@ API Changes
* eventdev: Type of 2nd parameter to ``rte_event_eth_rx_adapter_caps_get()``
has been changed from uint8_t to uint16_t.
+* kni: By default, interface carrier status is ``off`` which means there won't
+ be any traffic. It can be set to ``on`` via ``rte_kni_update_link()`` API
+ or via ``sysfs`` interface:
+ ``echo 1 > /sys/class/net/vEth0/carrier``.
+ Note interface should be ``up`` to be able to read/write sysfs interface.
+ When KNI sample application is used, ``-m`` parameter can be used to
+ automatically update the carrier status for the interface.
+
+* kni: When ethtool support enabled (``CONFIG_RTE_KNI_KMOD_ETHTOOL=y``)
+ ethtool commands ``ETHTOOL_GSET & ETHTOOL_SSET`` are no more supported for the
+ kernels that has ``ETHTOOL_GLINKSETTINGS & ETHTOOL_SLINKSETTINGS`` support.
+ This means ``ethtool "-a|--show-pause", "-s|--change"`` won't work, and
+ ``ethtool <iface>`` output will have less information.
+
ABI Changes
-----------
@@ -532,6 +565,8 @@ Known Issues
driver; the Linux netvsc device must be brought up before the netvsc device is
unbound and passed to the DPDK.
+* IBM Power8 is not supported by this release of DPDK. IBM Power9 is supported.
+
Tested Platforms
----------------
diff --git a/doc/guides/sample_app_ug/compiling.rst b/doc/guides/sample_app_ug/compiling.rst
index a2d75ed2..6f04743c 100644
--- a/doc/guides/sample_app_ug/compiling.rst
+++ b/doc/guides/sample_app_ug/compiling.rst
@@ -9,7 +9,6 @@ This section explains how to compile the DPDK sample applications.
To compile all the sample applications
--------------------------------------
-
Set the path to DPDK source code if its not set:
.. code-block:: console
@@ -93,3 +92,17 @@ Build the application:
export RTE_TARGET=build
make
+
+To cross compile the sample application(s)
+------------------------------------------
+
+For cross compiling the sample application(s), please append 'CROSS=$(CROSS_COMPILER_PREFIX)' to the 'make' command.
+In example of AARCH64 cross compiling:
+
+ .. code-block:: console
+
+ export RTE_TARGET=build
+ export RTE_SDK=/path/to/rte_sdk
+ make -C examples CROSS=aarch64-linux-gnu-
+ or
+ make CROSS=aarch64-linux-gnu-
diff --git a/doc/guides/sample_app_ug/flow_filtering.rst b/doc/guides/sample_app_ug/flow_filtering.rst
index 0d6fe2bb..840d557c 100644
--- a/doc/guides/sample_app_ug/flow_filtering.rst
+++ b/doc/guides/sample_app_ug/flow_filtering.rst
@@ -367,7 +367,7 @@ The forwarding loop can be interrupted and the application closed using
The generate_ipv4_flow function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The generate_ipv4_rule function is responsible for creating the flow rule.
+The generate_ipv4_flow function is responsible for creating the flow rule.
This function is located in the ``flow_blocks.c`` file.
.. code-block:: c
diff --git a/doc/guides/sample_app_ug/ip_reassembly.rst b/doc/guides/sample_app_ug/ip_reassembly.rst
index 18912cd2..e1b56d7b 100644
--- a/doc/guides/sample_app_ug/ip_reassembly.rst
+++ b/doc/guides/sample_app_ug/ip_reassembly.rst
@@ -23,8 +23,8 @@ There are two key differences from the L2 Forwarding sample application:
* The second difference is that the application differentiates between IP and non-IP traffic by means of offload flags.
-The Longest Prefix Match (LPM for IPv4, LPM6 for IPv6) table is used to store/lookup an outgoing port number, associated with that IPv4 address. Any unmatched packets are forwarded to the originating port.Compiling the Application
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+The Longest Prefix Match (LPM for IPv4, LPM6 for IPv6) table is used to store/lookup an outgoing port number,
+associated with that IPv4 address. Any unmatched packets are forwarded to the originating port.
Compiling the Application
diff --git a/doc/guides/sample_app_ug/ipv4_multicast.rst b/doc/guides/sample_app_ug/ipv4_multicast.rst
index ce1474ec..f6efa7f6 100644
--- a/doc/guides/sample_app_ug/ipv4_multicast.rst
+++ b/doc/guides/sample_app_ug/ipv4_multicast.rst
@@ -319,7 +319,6 @@ It is the mcast_out_pkt() function that performs the packet duplication (either
hdr->pkt.in_port = pkt->pkt.in_port;
hdr->pkt.vlan_macip = pkt->pkt.vlan_macip;
hdr->pkt.hash = pkt->pkt.hash;
- hdr->ol_flags = pkt->ol_flags;
rte_mbuf_sanity_check(hdr, RTE_MBUF_PKT, 1);
return hdr;
diff --git a/doc/guides/sample_app_ug/vm_power_management.rst b/doc/guides/sample_app_ug/vm_power_management.rst
index 1ad4f149..5be9f24d 100644
--- a/doc/guides/sample_app_ug/vm_power_management.rst
+++ b/doc/guides/sample_app_ug/vm_power_management.rst
@@ -657,6 +657,31 @@ To build just the ``guest_vm_power_manager`` application using ``make``:
The resulting binary will be ${RTE_SDK}/build/examples/guest_cli
+.. Note::
+ This sample application conditionally links in the Jansson JSON
+ library, so if you are using a multilib or cross compile environment you
+ may need to set the ``PKG_CONFIG_LIBDIR`` environmental variable to point to
+ the relevant pkgconfig folder so that the correct library is linked in.
+
+ For example, if you are building for a 32-bit target, you could find the
+ correct directory using the following ``find`` command:
+
+ .. code-block:: console
+
+ # find /usr -type d -name pkgconfig
+ /usr/lib/i386-linux-gnu/pkgconfig
+ /usr/lib/x86_64-linux-gnu/pkgconfig
+
+ Then use:
+
+ .. code-block:: console
+
+ export PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig
+
+ You then use the make command as normal, which should find the 32-bit
+ version of the library, if it installed. If not, the application will
+ be built without the JSON interface functionality.
+
To build just the ``vm_power_manager`` application using ``meson/ninja``:
.. code-block:: console
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index 305cc060..ffd26f19 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c
@@ -19,6 +19,7 @@
#include <rte_vfio.h>
#include <rte_eal.h>
#include <rte_bus.h>
+#include <rte_spinlock.h>
#include "eal_filesystem.h"
@@ -282,6 +283,14 @@ pci_vfio_setup_interrupts(struct rte_pci_device *dev, int vfio_dev_fd)
}
#ifdef HAVE_VFIO_DEV_REQ_INTERFACE
+/*
+ * Spinlock for device hot-unplug failure handling.
+ * If it tries to access bus or device, such as handle sigbus on bus
+ * or handle memory failure for device, just need to use this lock.
+ * It could protect the bus and the device to avoid race condition.
+ */
+static rte_spinlock_t failure_handle_lock = RTE_SPINLOCK_INITIALIZER;
+
static void
pci_vfio_req_handler(void *param)
{
@@ -289,11 +298,12 @@ pci_vfio_req_handler(void *param)
int ret;
struct rte_device *device = (struct rte_device *)param;
+ rte_spinlock_lock(&failure_handle_lock);
bus = rte_bus_find_by_device(device);
if (bus == NULL) {
RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
device->name);
- return;
+ goto handle_end;
}
/*
@@ -306,6 +316,8 @@ pci_vfio_req_handler(void *param)
RTE_LOG(ERR, EAL,
"Can not handle hot-unplug for device (%s)\n",
device->name);
+handle_end:
+ rte_spinlock_unlock(&failure_handle_lock);
}
/* enable notifier (only enable req now) */
diff --git a/drivers/common/cpt/cpt_ucode.h b/drivers/common/cpt/cpt_ucode.h
index c5a9f34b..5933ea77 100644
--- a/drivers/common/cpt/cpt_ucode.h
+++ b/drivers/common/cpt/cpt_ucode.h
@@ -3449,32 +3449,27 @@ find_kasumif9_direction_and_length(uint8_t *src,
uint8_t *addr_direction)
{
uint8_t found = 0;
+ uint32_t pos;
+ uint8_t last_byte;
while (!found && counter_num_bytes > 0) {
counter_num_bytes--;
if (src[counter_num_bytes] == 0x00)
continue;
- if (src[counter_num_bytes] == 0x80) {
- *addr_direction = src[counter_num_bytes - 1] & 0x1;
- *addr_length_in_bits = counter_num_bytes * 8 - 1;
- found = 1;
- } else {
- int i = 0;
- uint8_t last_byte = src[counter_num_bytes];
- for (i = 0; i < 8 && found == 0; i++) {
- if (last_byte & (1 << i)) {
- *addr_direction = (last_byte >> (i+1))
- & 0x1;
- if (i != 6)
- *addr_length_in_bits =
- counter_num_bytes * 8
- + (8 - (i + 2));
- else
- *addr_length_in_bits =
- counter_num_bytes * 8;
- found = 1;
- }
- }
+ pos = rte_bsf32(src[counter_num_bytes]);
+ if (pos == 7) {
+ if (likely(counter_num_bytes > 0)) {
+ last_byte = src[counter_num_bytes - 1];
+ *addr_direction = last_byte & 0x1;
+ *addr_length_in_bits = counter_num_bytes * 8
+ - 1;
}
+ } else {
+ last_byte = src[counter_num_bytes];
+ *addr_direction = (last_byte >> (pos + 1)) & 0x1;
+ *addr_length_in_bits = counter_num_bytes * 8
+ + (8 - (pos + 2));
+ }
+ found = 1;
}
}
diff --git a/drivers/net/avf/avf_rxtx.h b/drivers/net/avf/avf_rxtx.h
index 898d2f38..ffc835d4 100644
--- a/drivers/net/avf/avf_rxtx.h
+++ b/drivers/net/avf/avf_rxtx.h
@@ -43,6 +43,10 @@
PKT_TX_TCP_SEG)
#define AVF_TX_OFFLOAD_MASK ( \
+ PKT_TX_OUTER_IPV6 | \
+ PKT_TX_OUTER_IPV4 | \
+ PKT_TX_IPV6 | \
+ PKT_TX_IPV4 | \
PKT_TX_VLAN_PKT | \
PKT_TX_IP_CKSUM | \
PKT_TX_L4_MASK | \
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 2661620a..44deaf11 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3423,9 +3423,16 @@ bond_ethdev_configure(struct rte_eth_dev *dev)
"Failed to parse agg selection mode for bonded device %s",
name);
}
- if (internals->mode == BONDING_MODE_8023AD)
- rte_eth_bond_8023ad_agg_selection_set(port_id,
- agg_mode);
+ if (internals->mode == BONDING_MODE_8023AD) {
+ int ret = rte_eth_bond_8023ad_agg_selection_set(port_id,
+ agg_mode);
+ if (ret < 0) {
+ RTE_BOND_LOG(ERR,
+ "Invalid args for agg selection set for bonded device %s",
+ name);
+ return -1;
+ }
+ }
}
/* Parse/add slave ports to bonded device */
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index 05a4fbe0..3690afe3 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1096,6 +1096,7 @@ static int ena_create_io_queue(struct ena_ring *ring)
{ ENA_ADMIN_PLACEMENT_POLICY_HOST,
0, 0, 0, 0, 0 };
uint16_t ena_qid;
+ unsigned int i;
int rc;
adapter = ring->adapter;
@@ -1106,10 +1107,14 @@ static int ena_create_io_queue(struct ena_ring *ring)
ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_TX;
ctx.mem_queue_type = ena_dev->tx_mem_queue_type;
ctx.queue_size = adapter->tx_ring_size;
+ for (i = 0; i < ring->ring_size; i++)
+ ring->empty_tx_reqs[i] = i;
} else {
ena_qid = ENA_IO_RXQ_IDX(ring->id);
ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_RX;
ctx.queue_size = adapter->rx_ring_size;
+ for (i = 0; i < ring->ring_size; i++)
+ ring->empty_rx_reqs[i] = i;
}
ctx.qid = ena_qid;
ctx.msix_vector = -1; /* interrupts not used */
@@ -1152,6 +1157,8 @@ static void ena_free_io_queues_all(struct ena_adapter *adapter)
for (i = 0; i < nb_txq; ++i) {
ena_qid = ENA_IO_TXQ_IDX(i);
ena_com_destroy_io_queue(ena_dev, ena_qid);
+
+ ena_tx_queue_release_bufs(&adapter->tx_ring[i]);
}
for (i = 0; i < nb_rxq; ++i) {
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 790ecc3c..7030eb1f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -11609,6 +11609,32 @@ i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
return 0;
}
+/**
+ * This function is used to check if the register is valid.
+ * Below is the valid registers list for X722 only:
+ * 0x2b800--0x2bb00
+ * 0x38700--0x38a00
+ * 0x3d800--0x3db00
+ * 0x208e00--0x209000
+ * 0x20be00--0x20c000
+ * 0x263c00--0x264000
+ * 0x265c00--0x266000
+ */
+static inline int i40e_valid_regs(enum i40e_mac_type type, uint32_t reg_offset)
+{
+ if ((type != I40E_MAC_X722) &&
+ ((reg_offset >= 0x2b800 && reg_offset <= 0x2bb00) ||
+ (reg_offset >= 0x38700 && reg_offset <= 0x38a00) ||
+ (reg_offset >= 0x3d800 && reg_offset <= 0x3db00) ||
+ (reg_offset >= 0x208e00 && reg_offset <= 0x209000) ||
+ (reg_offset >= 0x20be00 && reg_offset <= 0x20c000) ||
+ (reg_offset >= 0x263c00 && reg_offset <= 0x264000) ||
+ (reg_offset >= 0x265c00 && reg_offset <= 0x266000)))
+ return 0;
+ else
+ return 1;
+}
+
static int i40e_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs)
{
@@ -11650,8 +11676,11 @@ static int i40e_get_regs(struct rte_eth_dev *dev,
reg_offset = arr_idx * reg_info->stride1 +
arr_idx2 * reg_info->stride2;
reg_offset += reg_info->base_addr;
- ptr_data[reg_offset >> 2] =
- I40E_READ_REG(hw, reg_offset);
+ if (!i40e_valid_regs(hw->mac.type, reg_offset))
+ ptr_data[reg_offset >> 2] = 0;
+ else
+ ptr_data[reg_offset >> 2] =
+ I40E_READ_REG(hw, reg_offset);
}
}
@@ -12554,8 +12583,6 @@ i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,
return -EINVAL;
if (!in->key && in->key_len)
return -EINVAL;
- if (in->key)
- out->conf.key = memcpy(out->key, in->key, in->key_len);
out->conf = (struct rte_flow_action_rss){
.func = in->func,
.level = in->level,
@@ -12565,6 +12592,8 @@ i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,
.queue = memcpy(out->queue, in->queue,
sizeof(*in->queue) * in->queue_num),
};
+ if (in->key)
+ out->conf.key = memcpy(out->key, in->key, in->key_len);
return 0;
}
diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c
index 21f973e5..fb50719f 100644
--- a/drivers/net/ixgbe/base/ixgbe_common.c
+++ b/drivers/net/ixgbe/base/ixgbe_common.c
@@ -5259,7 +5259,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_flap_tx_laser(hw);
/* Wait for the controller to acquire link. Per IEEE 802.3ap,
- * Section 73.10.2, we may have to wait up to 500ms if KR is
+ * Section 73.10.2, we may have to wait up to 1000ms if KR is
* attempted. 82599 uses the same timing for 10g SFI.
*/
for (i = 0; i < 10; i++) {
diff --git a/drivers/net/mlx4/mlx4_mr.c b/drivers/net/mlx4/mlx4_mr.c
index bee85864..a0094483 100644
--- a/drivers/net/mlx4/mlx4_mr.c
+++ b/drivers/net/mlx4/mlx4_mr.c
@@ -354,8 +354,9 @@ mr_insert_dev_cache(struct rte_eth_dev *dev, struct mlx4_mr *mr)
DEBUG("port %u inserting MR(%p) to global cache",
dev->data->port_id, (void *)mr);
for (n = 0; n < mr->ms_bmp_n; ) {
- struct mlx4_mr_cache entry = { 0, };
+ struct mlx4_mr_cache entry;
+ memset(&entry, 0, sizeof(entry));
/* Find a contiguous chunk and advance the index. */
n = mr_find_next_chunk(mr, &entry, n);
if (!entry.end)
@@ -398,8 +399,9 @@ mr_lookup_dev_list(struct rte_eth_dev *dev, struct mlx4_mr_cache *entry,
if (mr->ms_n == 0)
continue;
for (n = 0; n < mr->ms_bmp_n; ) {
- struct mlx4_mr_cache ret = { 0, };
+ struct mlx4_mr_cache ret;
+ memset(&ret, 0, sizeof(ret));
n = mr_find_next_chunk(mr, &ret, n);
if (addr >= ret.start && addr < ret.end) {
/* Found. */
@@ -571,7 +573,7 @@ mlx4_mr_create(struct rte_eth_dev *dev, struct mlx4_mr_cache *entry,
* Find out a contiguous virtual address chunk in use, to which the
* given address belongs, in order to register maximum range. In the
* best case where mempools are not dynamically recreated and
- * '--socket-mem' is speicified as an EAL option, it is very likely to
+ * '--socket-mem' is specified as an EAL option, it is very likely to
* have only one MR(LKey) per a socket and per a hugepage-size even
* though the system memory is highly fragmented.
*/
@@ -688,8 +690,9 @@ alloc_resources:
*/
for (n = 0; n < ms_n; ++n) {
uintptr_t start;
- struct mlx4_mr_cache ret = { 0, };
+ struct mlx4_mr_cache ret;
+ memset(&ret, 0, sizeof(ret));
start = data_re.start + n * msl->page_sz;
/* Exclude memsegs already registered by other MRs. */
if (mr_lookup_dev(dev, &ret, start) == UINT32_MAX) {
@@ -1039,7 +1042,7 @@ mlx4_rx_addr2mr_bh(struct rxq *rxq, uintptr_t addr)
* @return
* Searched LKey on success, UINT32_MAX on no match.
*/
-uint32_t
+static uint32_t
mlx4_tx_addr2mr_bh(struct txq *txq, uintptr_t addr)
{
struct mlx4_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
@@ -1051,6 +1054,32 @@ mlx4_tx_addr2mr_bh(struct txq *txq, uintptr_t addr)
}
/**
+ * Bottom-half of LKey search on Tx. If it can't be searched in the memseg
+ * list, register the mempool of the mbuf as externally allocated memory.
+ *
+ * @param txq
+ * Pointer to Tx queue structure.
+ * @param mb
+ * Pointer to mbuf.
+ *
+ * @return
+ * Searched LKey on success, UINT32_MAX on no match.
+ */
+uint32_t
+mlx4_tx_mb2mr_bh(struct txq *txq, struct rte_mbuf *mb)
+{
+ uintptr_t addr = (uintptr_t)mb->buf_addr;
+ uint32_t lkey;
+
+ lkey = mlx4_tx_addr2mr_bh(txq, addr);
+ if (lkey == UINT32_MAX && rte_errno == ENXIO) {
+ /* Mempool may have externally allocated memory. */
+ return mlx4_tx_update_ext_mp(txq, addr, mlx4_mb2mp(mb));
+ }
+ return lkey;
+}
+
+/**
* Flush all of the local cache entries.
*
* @param mr_ctrl
@@ -1277,8 +1306,9 @@ mlx4_mr_dump_dev(struct rte_eth_dev *dev)
if (mr->ms_n == 0)
continue;
for (n = 0; n < mr->ms_bmp_n; ) {
- struct mlx4_mr_cache ret = { 0, };
+ struct mlx4_mr_cache ret;
+ memset(&ret, 0, sizeof(ret));
n = mr_find_next_chunk(mr, &ret, n);
if (!ret.end)
break;
diff --git a/drivers/net/mlx4/mlx4_rxtx.h b/drivers/net/mlx4/mlx4_rxtx.h
index 1be060cd..d7ec4e0c 100644
--- a/drivers/net/mlx4/mlx4_rxtx.h
+++ b/drivers/net/mlx4/mlx4_rxtx.h
@@ -162,7 +162,7 @@ void mlx4_tx_queue_release(void *dpdk_txq);
void mlx4_mr_flush_local_cache(struct mlx4_mr_ctrl *mr_ctrl);
uint32_t mlx4_rx_addr2mr_bh(struct rxq *rxq, uintptr_t addr);
-uint32_t mlx4_tx_addr2mr_bh(struct txq *txq, uintptr_t addr);
+uint32_t mlx4_tx_mb2mr_bh(struct txq *txq, struct rte_mbuf *mb);
uint32_t mlx4_tx_update_ext_mp(struct txq *txq, uintptr_t addr,
struct rte_mempool *mp);
@@ -176,7 +176,7 @@ uint32_t mlx4_tx_update_ext_mp(struct txq *txq, uintptr_t addr,
* @return
* Memory pool where data is located for given mbuf.
*/
-static struct rte_mempool *
+static inline struct rte_mempool *
mlx4_mb2mp(struct rte_mbuf *buf)
{
if (unlikely(RTE_MBUF_INDIRECT(buf)))
@@ -225,9 +225,10 @@ mlx4_rx_addr2mr(struct rxq *rxq, uintptr_t addr)
* Searched LKey on success, UINT32_MAX on no match.
*/
static __rte_always_inline uint32_t
-mlx4_tx_addr2mr(struct txq *txq, uintptr_t addr)
+mlx4_tx_mb2mr(struct txq *txq, struct rte_mbuf *mb)
{
struct mlx4_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
+ uintptr_t addr = (uintptr_t)mb->buf_addr;
uint32_t lkey;
/* Check generation bit to see if there's any change on existing MRs. */
@@ -238,23 +239,8 @@ mlx4_tx_addr2mr(struct txq *txq, uintptr_t addr)
MLX4_MR_CACHE_N, addr);
if (likely(lkey != UINT32_MAX))
return lkey;
- /* Take slower bottom-half (binary search) on miss. */
- return mlx4_tx_addr2mr_bh(txq, addr);
-}
-
-static __rte_always_inline uint32_t
-mlx4_tx_mb2mr(struct txq *txq, struct rte_mbuf *mb)
-{
- uintptr_t addr = (uintptr_t)mb->buf_addr;
- uint32_t lkey = mlx4_tx_addr2mr(txq, addr);
-
- if (likely(lkey != UINT32_MAX))
- return lkey;
- if (rte_errno == ENXIO) {
- /* Mempool may have externally allocated memory. */
- lkey = mlx4_tx_update_ext_mp(txq, addr, mlx4_mb2mp(mb));
- }
- return lkey;
+ /* Take slower bottom-half on miss. */
+ return mlx4_tx_mb2mr_bh(txq, mb);
}
#endif /* MLX4_RXTX_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 5ad3a11a..97dc3e1f 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -294,7 +294,7 @@ static struct mlx5_flow_tunnel_info tunnels_info[] = {
},
{
.tunnel = MLX5_FLOW_LAYER_MPLS | MLX5_FLOW_LAYER_OUTER_L4_UDP,
- .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_GRE | RTE_PTYPE_L4_UDP,
+ .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_UDP | RTE_PTYPE_L4_UDP,
},
{
.tunnel = MLX5_FLOW_LAYER_MPLS,
@@ -1593,12 +1593,14 @@ mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
/**
* Validate MPLS item.
*
+ * @param[in] dev
+ * Pointer to the rte_eth_dev structure.
* @param[in] item
* Item specification.
* @param[in] item_flags
* Bit-fields that holds the items detected until now.
- * @param[in] target_protocol
- * The next protocol in the previous item.
+ * @param[in] prev_layer
+ * The protocol layer indicated in previous item.
* @param[out] error
* Pointer to error structure.
*
@@ -1606,16 +1608,27 @@ mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
int
-mlx5_flow_validate_item_mpls(const struct rte_flow_item *item __rte_unused,
+mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused,
+ const struct rte_flow_item *item __rte_unused,
uint64_t item_flags __rte_unused,
- uint8_t target_protocol __rte_unused,
+ uint64_t prev_layer __rte_unused,
struct rte_flow_error *error)
{
#ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT
const struct rte_flow_item_mpls *mask = item->mask;
+ struct priv *priv = dev->data->dev_private;
int ret;
- if (target_protocol != 0xff && target_protocol != IPPROTO_MPLS)
+ if (!priv->config.mpls_en)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "MPLS not supported or"
+ " disabled in firmware"
+ " configuration.");
+ /* MPLS over IP, UDP, GRE is allowed */
+ if (!(prev_layer & (MLX5_FLOW_LAYER_OUTER_L3 |
+ MLX5_FLOW_LAYER_OUTER_L4_UDP |
+ MLX5_FLOW_LAYER_GRE)))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM, item,
"protocol filtering not compatible"
@@ -2127,14 +2140,14 @@ static void
flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list,
struct rte_flow *flow)
{
- flow_drv_destroy(dev, flow);
- TAILQ_REMOVE(list, flow, next);
/*
* Update RX queue flags only if port is started, otherwise it is
* already clean.
*/
if (dev->data->dev_started)
flow_rxq_flags_trim(dev, flow);
+ flow_drv_destroy(dev, flow);
+ TAILQ_REMOVE(list, flow, next);
rte_free(flow->fdir);
rte_free(flow);
}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 51ab47fe..4a7c0529 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -114,6 +114,9 @@
#define IPPROTO_MPLS 137
#endif
+/* UDP port number for MPLS */
+#define MLX5_UDP_PORT_MPLS 6635
+
/* UDP port numbers for VxLAN. */
#define MLX5_UDP_PORT_VXLAN 4789
#define MLX5_UDP_PORT_VXLAN_GPE 4790
@@ -219,6 +222,7 @@ struct mlx5_flow_dv {
struct mlx5_flow_tcf {
struct nlmsghdr *nlh;
struct tcmsg *tcm;
+ uint32_t *ptc_flags; /**< tc rule applied flags. */
union { /**< Tunnel encap/decap descriptor. */
struct flow_tcf_tunnel_hdr *tunnel;
struct flow_tcf_vxlan_decap *vxlan_decap;
@@ -381,9 +385,10 @@ int mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item,
int mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
uint64_t item_flags,
struct rte_flow_error *error);
-int mlx5_flow_validate_item_mpls(const struct rte_flow_item *item,
+int mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev,
+ const struct rte_flow_item *item,
uint64_t item_flags,
- uint8_t target_protocol,
+ uint64_t prev_layer,
struct rte_flow_error *error);
int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
uint64_t item_flags,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index a2edd168..1f318748 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -775,6 +775,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
int ret;
uint64_t action_flags = 0;
uint64_t item_flags = 0;
+ uint64_t last_item = 0;
int tunnel = 0;
uint8_t next_protocol = 0xff;
int actions_n = 0;
@@ -794,24 +795,24 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
- MLX5_FLOW_LAYER_OUTER_L2;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
+ MLX5_FLOW_LAYER_OUTER_L2;
break;
case RTE_FLOW_ITEM_TYPE_VLAN:
ret = mlx5_flow_validate_item_vlan(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
- MLX5_FLOW_LAYER_OUTER_VLAN;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
+ MLX5_FLOW_LAYER_OUTER_VLAN;
break;
case RTE_FLOW_ITEM_TYPE_IPV4:
ret = mlx5_flow_validate_item_ipv4(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV4;
if (items->mask != NULL &&
((const struct rte_flow_item_ipv4 *)
items->mask)->hdr.next_proto_id) {
@@ -831,8 +832,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV6;
if (items->mask != NULL &&
((const struct rte_flow_item_ipv6 *)
items->mask)->hdr.proto) {
@@ -855,8 +856,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
- MLX5_FLOW_LAYER_OUTER_L4_TCP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
+ MLX5_FLOW_LAYER_OUTER_L4_TCP;
break;
case RTE_FLOW_ITEM_TYPE_UDP:
ret = mlx5_flow_validate_item_udp(items, item_flags,
@@ -864,8 +865,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
- MLX5_FLOW_LAYER_OUTER_L4_UDP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
+ MLX5_FLOW_LAYER_OUTER_L4_UDP;
break;
case RTE_FLOW_ITEM_TYPE_GRE:
case RTE_FLOW_ITEM_TYPE_NVGRE:
@@ -873,14 +874,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
next_protocol, error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_GRE;
+ last_item = MLX5_FLOW_LAYER_GRE;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN:
ret = mlx5_flow_validate_item_vxlan(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_VXLAN;
+ last_item = MLX5_FLOW_LAYER_VXLAN;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
ret = mlx5_flow_validate_item_vxlan_gpe(items,
@@ -888,20 +889,29 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
+ last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
+ break;
+ case RTE_FLOW_ITEM_TYPE_MPLS:
+ ret = mlx5_flow_validate_item_mpls(dev, items,
+ item_flags,
+ last_item, error);
+ if (ret < 0)
+ return ret;
+ last_item = MLX5_FLOW_LAYER_MPLS;
break;
case RTE_FLOW_ITEM_TYPE_META:
ret = flow_dv_validate_item_meta(dev, items, attr,
error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_ITEM_METADATA;
+ last_item = MLX5_FLOW_ITEM_METADATA;
break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM,
NULL, "item not supported");
}
+ item_flags |= last_item;
}
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
@@ -1609,6 +1619,96 @@ flow_dv_translate_item_vxlan(void *matcher, void *key,
}
/**
+ * Add MPLS item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ * Flow matcher.
+ * @param[in, out] key
+ * Flow matcher value.
+ * @param[in] item
+ * Flow pattern to translate.
+ * @param[in] prev_layer
+ * The protocol layer indicated in previous item.
+ * @param[in] inner
+ * Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_mpls(void *matcher, void *key,
+ const struct rte_flow_item *item,
+ uint64_t prev_layer,
+ int inner)
+{
+ const uint32_t *in_mpls_m = item->mask;
+ const uint32_t *in_mpls_v = item->spec;
+ uint32_t *out_mpls_m = 0;
+ uint32_t *out_mpls_v = 0;
+ void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+ void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+ void *misc2_m = MLX5_ADDR_OF(fte_match_param, matcher,
+ misc_parameters_2);
+ void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+ void *headers_m = MLX5_ADDR_OF(fte_match_param, matcher, outer_headers);
+ void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+
+ switch (prev_layer) {
+ case MLX5_FLOW_LAYER_OUTER_L4_UDP:
+ MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xffff);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
+ MLX5_UDP_PORT_MPLS);
+ break;
+ case MLX5_FLOW_LAYER_GRE:
+ MLX5_SET(fte_match_set_misc, misc_m, gre_protocol, 0xffff);
+ MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
+ ETHER_TYPE_MPLS);
+ break;
+ default:
+ MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
+ IPPROTO_MPLS);
+ break;
+ }
+ if (!in_mpls_v)
+ return;
+ if (!in_mpls_m)
+ in_mpls_m = (const uint32_t *)&rte_flow_item_mpls_mask;
+ switch (prev_layer) {
+ case MLX5_FLOW_LAYER_OUTER_L4_UDP:
+ out_mpls_m =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m,
+ outer_first_mpls_over_udp);
+ out_mpls_v =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
+ outer_first_mpls_over_udp);
+ break;
+ case MLX5_FLOW_LAYER_GRE:
+ out_mpls_m =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m,
+ outer_first_mpls_over_gre);
+ out_mpls_v =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
+ outer_first_mpls_over_gre);
+ break;
+ default:
+ /* Inner MPLS not over GRE is not supported. */
+ if (!inner) {
+ out_mpls_m =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
+ misc2_m,
+ outer_first_mpls);
+ out_mpls_v =
+ (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
+ misc2_v,
+ outer_first_mpls);
+ }
+ break;
+ }
+ if (out_mpls_m && out_mpls_v) {
+ *out_mpls_m = *in_mpls_m;
+ *out_mpls_v = *in_mpls_v & *in_mpls_m;
+ }
+}
+
+/**
* Add META item to matcher
*
* @param[in, out] matcher
@@ -1786,6 +1886,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
struct priv *priv = dev->data->dev_private;
struct rte_flow *flow = dev_flow->flow;
uint64_t item_flags = 0;
+ uint64_t last_item = 0;
uint64_t action_flags = 0;
uint64_t priority = attr->priority;
struct mlx5_flow_dv_matcher matcher = {
@@ -1940,17 +2041,17 @@ flow_dv_translate(struct rte_eth_dev *dev,
flow_dv_translate_item_eth(match_mask, match_value,
items, tunnel);
matcher.priority = MLX5_PRIORITY_MAP_L2;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
- MLX5_FLOW_LAYER_OUTER_L2;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
+ MLX5_FLOW_LAYER_OUTER_L2;
break;
case RTE_FLOW_ITEM_TYPE_VLAN:
flow_dv_translate_item_vlan(match_mask, match_value,
items, tunnel);
matcher.priority = MLX5_PRIORITY_MAP_L2;
- item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
- MLX5_FLOW_LAYER_INNER_VLAN) :
- (MLX5_FLOW_LAYER_OUTER_L2 |
- MLX5_FLOW_LAYER_OUTER_VLAN);
+ last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
+ MLX5_FLOW_LAYER_INNER_VLAN) :
+ (MLX5_FLOW_LAYER_OUTER_L2 |
+ MLX5_FLOW_LAYER_OUTER_VLAN);
break;
case RTE_FLOW_ITEM_TYPE_IPV4:
flow_dv_translate_item_ipv4(match_mask, match_value,
@@ -1961,8 +2062,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
(dev_flow, tunnel,
MLX5_IPV4_LAYER_TYPES,
MLX5_IPV4_IBV_RX_HASH);
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV4;
break;
case RTE_FLOW_ITEM_TYPE_IPV6:
flow_dv_translate_item_ipv6(match_mask, match_value,
@@ -1973,8 +2074,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
(dev_flow, tunnel,
MLX5_IPV6_LAYER_TYPES,
MLX5_IPV6_IBV_RX_HASH);
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV6;
break;
case RTE_FLOW_ITEM_TYPE_TCP:
flow_dv_translate_item_tcp(match_mask, match_value,
@@ -1985,8 +2086,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
(dev_flow, tunnel, ETH_RSS_TCP,
IBV_RX_HASH_SRC_PORT_TCP |
IBV_RX_HASH_DST_PORT_TCP);
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
- MLX5_FLOW_LAYER_OUTER_L4_TCP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
+ MLX5_FLOW_LAYER_OUTER_L4_TCP;
break;
case RTE_FLOW_ITEM_TYPE_UDP:
flow_dv_translate_item_udp(match_mask, match_value,
@@ -1997,37 +2098,43 @@ flow_dv_translate(struct rte_eth_dev *dev,
(dev_flow, tunnel, ETH_RSS_UDP,
IBV_RX_HASH_SRC_PORT_UDP |
IBV_RX_HASH_DST_PORT_UDP);
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
- MLX5_FLOW_LAYER_OUTER_L4_UDP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
+ MLX5_FLOW_LAYER_OUTER_L4_UDP;
break;
case RTE_FLOW_ITEM_TYPE_GRE:
flow_dv_translate_item_gre(match_mask, match_value,
items, tunnel);
- item_flags |= MLX5_FLOW_LAYER_GRE;
+ last_item = MLX5_FLOW_LAYER_GRE;
break;
case RTE_FLOW_ITEM_TYPE_NVGRE:
flow_dv_translate_item_nvgre(match_mask, match_value,
items, tunnel);
- item_flags |= MLX5_FLOW_LAYER_GRE;
+ last_item = MLX5_FLOW_LAYER_GRE;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN:
flow_dv_translate_item_vxlan(match_mask, match_value,
items, tunnel);
- item_flags |= MLX5_FLOW_LAYER_VXLAN;
+ last_item = MLX5_FLOW_LAYER_VXLAN;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
flow_dv_translate_item_vxlan(match_mask, match_value,
items, tunnel);
- item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
+ last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
+ break;
+ case RTE_FLOW_ITEM_TYPE_MPLS:
+ flow_dv_translate_item_mpls(match_mask, match_value,
+ items, last_item, tunnel);
+ last_item = MLX5_FLOW_LAYER_MPLS;
break;
case RTE_FLOW_ITEM_TYPE_META:
flow_dv_translate_item_meta(match_mask, match_value,
items);
- item_flags |= MLX5_FLOW_ITEM_METADATA;
+ last_item = MLX5_FLOW_ITEM_METADATA;
break;
default:
break;
}
+ item_flags |= last_item;
}
assert(!flow_dv_check_valid_spec(matcher.mask.buf,
dev_flow->dv.value.buf));
@@ -2275,8 +2382,10 @@ flow_dv_query(struct rte_eth_dev *dev __rte_unused,
void *data __rte_unused,
struct rte_flow_error *error __rte_unused)
{
- rte_errno = ENOTSUP;
- return -rte_errno;
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "flow query with DV is not supported");
}
diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c
index 97d2a54c..2f6b7d63 100644
--- a/drivers/net/mlx5/mlx5_flow_tcf.c
+++ b/drivers/net/mlx5/mlx5_flow_tcf.c
@@ -160,6 +160,9 @@ struct tc_tunnel_key {
#ifndef TCA_CLS_FLAGS_SKIP_SW
#define TCA_CLS_FLAGS_SKIP_SW (1 << 1)
#endif
+#ifndef TCA_CLS_FLAGS_IN_HW
+#define TCA_CLS_FLAGS_IN_HW (1 << 2)
+#endif
#ifndef HAVE_TCA_CHAIN
#define TCA_CHAIN 11
#endif
@@ -3699,6 +3702,8 @@ override_na_vlan_priority:
assert(na_flower);
assert(na_flower_act);
mnl_attr_nest_end(nlh, na_flower_act);
+ dev_flow->tcf.ptc_flags = mnl_attr_get_payload
+ (mnl_nlmsg_get_payload_tail(nlh));
mnl_attr_put_u32(nlh, TCA_FLOWER_FLAGS, decap.vxlan ?
0 : TCA_CLS_FLAGS_SKIP_SW);
mnl_attr_nest_end(nlh, na_flower);
@@ -3717,10 +3722,6 @@ override_na_vlan_priority:
* @param nlh
* Message to send. This function always raises the NLM_F_ACK flag before
* sending.
- * @param[in] msglen
- * Message length. Message buffer may contain multiple commands and
- * nlmsg_len field not always corresponds to actual message length.
- * If 0 specified the nlmsg_len field in header is used as message length.
* @param[in] cb
* Callback handler for received message.
* @param[in] arg
@@ -3732,52 +3733,64 @@ override_na_vlan_priority:
static int
flow_tcf_nl_ack(struct mlx5_flow_tcf_context *tcf,
struct nlmsghdr *nlh,
- uint32_t msglen,
mnl_cb_t cb, void *arg)
{
unsigned int portid = mnl_socket_get_portid(tcf->nl);
uint32_t seq = tcf->seq++;
- int err, ret;
+ int ret, err = 0;
assert(tcf->nl);
assert(tcf->buf);
- if (!seq)
+ if (!seq) {
/* seq 0 is reserved for kernel event-driven notifications. */
seq = tcf->seq++;
+ }
nlh->nlmsg_seq = seq;
- if (!msglen) {
- msglen = nlh->nlmsg_len;
- nlh->nlmsg_flags |= NLM_F_ACK;
+ nlh->nlmsg_flags |= NLM_F_ACK;
+ ret = mnl_socket_sendto(tcf->nl, nlh, nlh->nlmsg_len);
+ if (ret <= 0) {
+ /* Message send error occurres. */
+ rte_errno = errno;
+ return -rte_errno;
}
- ret = mnl_socket_sendto(tcf->nl, nlh, msglen);
- err = (ret <= 0) ? errno : 0;
nlh = (struct nlmsghdr *)(tcf->buf);
/*
* The following loop postpones non-fatal errors until multipart
* messages are complete.
*/
- if (ret > 0)
- while (true) {
- ret = mnl_socket_recvfrom(tcf->nl, tcf->buf,
- tcf->buf_size);
+ while (true) {
+ ret = mnl_socket_recvfrom(tcf->nl, tcf->buf, tcf->buf_size);
+ if (ret < 0) {
+ err = errno;
+ /*
+ * In case of overflow Will receive till
+ * end of multipart message. We may lost part
+ * of reply messages but mark and return an error.
+ */
+ if (err != ENOSPC ||
+ !(nlh->nlmsg_flags & NLM_F_MULTI) ||
+ nlh->nlmsg_type == NLMSG_DONE)
+ break;
+ } else {
+ ret = mnl_cb_run(nlh, ret, seq, portid, cb, arg);
+ if (!ret) {
+ /*
+ * libmnl returns 0 if DONE or
+ * success ACK message found.
+ */
+ break;
+ }
if (ret < 0) {
+ /*
+ * ACK message with error found
+ * or some error occurred.
+ */
err = errno;
- if (err != ENOSPC)
- break;
- }
- if (!err) {
- ret = mnl_cb_run(nlh, ret, seq, portid,
- cb, arg);
- if (ret < 0) {
- err = errno;
- break;
- }
- }
- /* Will receive till end of multipart message */
- if (!(nlh->nlmsg_flags & NLM_F_MULTI) ||
- nlh->nlmsg_type == NLMSG_DONE)
break;
+ }
+ /* We should continue receiving. */
}
+ }
if (!err)
return 0;
rte_errno = err;
@@ -3886,7 +3899,7 @@ flow_tcf_send_nlcmd(struct mlx5_flow_tcf_context *tcf,
nlh = (struct nlmsghdr *)&bc->msg[msg];
assert((bc->size - msg) >= nlh->nlmsg_len);
msg += nlh->nlmsg_len;
- rc = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL);
+ rc = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);
if (rc) {
DRV_LOG(WARNING,
"netlink: cleanup error %d", rc);
@@ -4019,7 +4032,7 @@ flow_tcf_encap_local_cleanup(struct mlx5_flow_tcf_context *tcf,
ifa->ifa_family = AF_UNSPEC;
ifa->ifa_index = ifindex;
ifa->ifa_scope = RT_SCOPE_LINK;
- ret = flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_local_cb, &ctx);
+ ret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_local_cb, &ctx);
if (ret)
DRV_LOG(WARNING, "netlink: query device list error %d", ret);
ret = flow_tcf_send_nlcmd(tcf, &ctx);
@@ -4140,7 +4153,7 @@ flow_tcf_encap_neigh_cleanup(struct mlx5_flow_tcf_context *tcf,
ndm->ndm_family = AF_UNSPEC;
ndm->ndm_ifindex = ifindex;
ndm->ndm_state = NUD_PERMANENT;
- ret = flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_neigh_cb, &ctx);
+ ret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_neigh_cb, &ctx);
if (ret)
DRV_LOG(WARNING, "netlink: query device list error %d", ret);
ret = flow_tcf_send_nlcmd(tcf, &ctx);
@@ -4269,7 +4282,7 @@ flow_tcf_encap_iface_cleanup(struct mlx5_flow_tcf_context *tcf,
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
ifm->ifi_family = AF_UNSPEC;
- ret = flow_tcf_nl_ack(tcf, nlh, 0, flow_tcf_collect_vxlan_cb, &ctx);
+ ret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_vxlan_cb, &ctx);
if (ret)
DRV_LOG(WARNING, "netlink: query device list error %d", ret);
ret = flow_tcf_send_nlcmd(tcf, &ctx);
@@ -4341,7 +4354,7 @@ flow_tcf_rule_local(struct mlx5_flow_tcf_context *tcf,
sizeof(encap->ipv6.dst),
&encap->ipv6.dst);
}
- if (!flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL))
+ if (!flow_tcf_nl_ack(tcf, nlh, NULL, NULL))
return 0;
return rte_flow_error_set(error, rte_errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -4404,7 +4417,7 @@ flow_tcf_rule_neigh(struct mlx5_flow_tcf_context *tcf,
if (encap->mask & FLOW_TCF_ENCAP_ETH_DST)
mnl_attr_put(nlh, NDA_LLADDR, sizeof(encap->eth.dst),
&encap->eth.dst);
- if (!flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL))
+ if (!flow_tcf_nl_ack(tcf, nlh, NULL, NULL))
return 0;
return rte_flow_error_set(error, rte_errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -4679,7 +4692,7 @@ flow_tcf_vtep_delete(struct mlx5_flow_tcf_context *tcf,
ifm->ifi_family = AF_UNSPEC;
ifm->ifi_index = vtep->ifindex;
assert(sizeof(buf) >= nlh->nlmsg_len);
- ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL);
+ ret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);
if (ret)
DRV_LOG(WARNING, "netlink: error deleting vxlan"
" encap/decap ifindex %u",
@@ -4769,7 +4782,7 @@ flow_tcf_vtep_create(struct mlx5_flow_tcf_context *tcf,
mnl_attr_nest_end(nlh, na_vxlan);
mnl_attr_nest_end(nlh, na_info);
assert(sizeof(buf) >= nlh->nlmsg_len);
- ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL);
+ ret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);
if (ret) {
DRV_LOG(WARNING,
"netlink: VTEP %s create failure (%d)",
@@ -4811,7 +4824,7 @@ flow_tcf_vtep_create(struct mlx5_flow_tcf_context *tcf,
ifm->ifi_index = vtep->ifindex;
ifm->ifi_flags = IFF_UP;
ifm->ifi_change = IFF_UP;
- ret = flow_tcf_nl_ack(tcf, nlh, 0, NULL, NULL);
+ ret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);
if (ret) {
rte_flow_error_set(error, -errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -5069,6 +5082,172 @@ flow_tcf_vtep_release(struct mlx5_flow_tcf_context *tcf,
pthread_mutex_unlock(&vtep_list_mutex);
}
+struct tcf_nlcb_query {
+ uint32_t handle;
+ uint32_t tc_flags;
+ uint32_t flags_valid:1;
+};
+
+/**
+ * Collect queried rule attributes. This is callback routine called by
+ * libmnl mnl_cb_run() in loop for every message in received packet.
+ * Current implementation collects the flower flags only.
+ *
+ * @param[in] nlh
+ * Pointer to reply header.
+ * @param[in, out] arg
+ * Context pointer for this callback.
+ *
+ * @return
+ * A positive, nonzero value on success (required by libmnl
+ * to continue messages processing).
+ */
+static int
+flow_tcf_collect_query_cb(const struct nlmsghdr *nlh, void *arg)
+{
+ struct tcf_nlcb_query *query = arg;
+ struct tcmsg *tcm = mnl_nlmsg_get_payload(nlh);
+ struct nlattr *na, *na_opt;
+ bool flower = false;
+
+ if (nlh->nlmsg_type != RTM_NEWTFILTER ||
+ tcm->tcm_handle != query->handle)
+ return 1;
+ mnl_attr_for_each(na, nlh, sizeof(*tcm)) {
+ switch (mnl_attr_get_type(na)) {
+ case TCA_KIND:
+ if (strcmp(mnl_attr_get_payload(na), "flower")) {
+ /* Not flower filter, drop entire message. */
+ return 1;
+ }
+ flower = true;
+ break;
+ case TCA_OPTIONS:
+ if (!flower) {
+ /* Not flower options, drop entire message. */
+ return 1;
+ }
+ /* Check nested flower options. */
+ mnl_attr_for_each_nested(na_opt, na) {
+ switch (mnl_attr_get_type(na_opt)) {
+ case TCA_FLOWER_FLAGS:
+ query->flags_valid = 1;
+ query->tc_flags =
+ mnl_attr_get_u32(na_opt);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/**
+ * Query a TC flower rule flags via netlink.
+ *
+ * @param[in] tcf
+ * Context object initialized by mlx5_flow_tcf_context_create().
+ * @param[in] dev_flow
+ * Pointer to the flow.
+ * @param[out] pflags
+ * pointer to the data retrieved by the query.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise.
+ */
+static int
+flow_tcf_query_flags(struct mlx5_flow_tcf_context *tcf,
+ struct mlx5_flow *dev_flow,
+ uint32_t *pflags)
+{
+ struct nlmsghdr *nlh;
+ struct tcmsg *tcm;
+ struct tcf_nlcb_query query = {
+ .handle = dev_flow->tcf.tcm->tcm_handle,
+ };
+
+ nlh = mnl_nlmsg_put_header(tcf->buf);
+ nlh->nlmsg_type = RTM_GETTFILTER;
+ nlh->nlmsg_flags = NLM_F_REQUEST;
+ tcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm));
+ memcpy(tcm, dev_flow->tcf.tcm, sizeof(*tcm));
+ /*
+ * Ignore Netlink error for filter query operations.
+ * The reply length is sent by kernel as errno.
+ * Just check we got the flags option.
+ */
+ flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_query_cb, &query);
+ if (!query.flags_valid) {
+ *pflags = 0;
+ return -ENOENT;
+ }
+ *pflags = query.tc_flags;
+ return 0;
+}
+
+/**
+ * Query and check the in_hw set for specified rule.
+ *
+ * @param[in] tcf
+ * Context object initialized by mlx5_flow_tcf_context_create().
+ * @param[in] dev_flow
+ * Pointer to the flow to check.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise.
+ */
+static int
+flow_tcf_check_inhw(struct mlx5_flow_tcf_context *tcf,
+ struct mlx5_flow *dev_flow)
+{
+ uint32_t flags;
+ int ret;
+
+ ret = flow_tcf_query_flags(tcf, dev_flow, &flags);
+ if (ret)
+ return ret;
+ return (flags & TCA_CLS_FLAGS_IN_HW) ? 0 : -ENOENT;
+}
+
+/**
+ * Remove flow from E-Switch by sending Netlink message.
+ *
+ * @param[in] dev
+ * Pointer to Ethernet device.
+ * @param[in, out] flow
+ * Pointer to the sub flow.
+ */
+static void
+flow_tcf_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
+{
+ struct priv *priv = dev->data->dev_private;
+ struct mlx5_flow_tcf_context *ctx = priv->tcf_context;
+ struct mlx5_flow *dev_flow;
+ struct nlmsghdr *nlh;
+
+ if (!flow)
+ return;
+ dev_flow = LIST_FIRST(&flow->dev_flows);
+ if (!dev_flow)
+ return;
+ /* E-Switch flow can't be expanded. */
+ assert(!LIST_NEXT(dev_flow, next));
+ if (dev_flow->tcf.applied) {
+ nlh = dev_flow->tcf.nlh;
+ nlh->nlmsg_type = RTM_DELTFILTER;
+ nlh->nlmsg_flags = NLM_F_REQUEST;
+ flow_tcf_nl_ack(ctx, nlh, NULL, NULL);
+ if (dev_flow->tcf.tunnel) {
+ assert(dev_flow->tcf.tunnel->vtep);
+ flow_tcf_vtep_release(ctx,
+ dev_flow->tcf.tunnel->vtep,
+ dev_flow);
+ dev_flow->tcf.tunnel->vtep = NULL;
+ }
+ dev_flow->tcf.applied = 0;
+ }
+}
/**
* Apply flow to E-Switch by sending Netlink message.
@@ -5120,8 +5299,22 @@ flow_tcf_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
*dev_flow->tcf.tunnel->ifindex_ptr =
dev_flow->tcf.tunnel->vtep->ifindex;
}
- if (!flow_tcf_nl_ack(ctx, nlh, 0, NULL, NULL)) {
+ if (!flow_tcf_nl_ack(ctx, nlh, NULL, NULL)) {
dev_flow->tcf.applied = 1;
+ if (*dev_flow->tcf.ptc_flags & TCA_CLS_FLAGS_SKIP_SW)
+ return 0;
+ /*
+ * Rule was applied without skip_sw flag set.
+ * We should check whether the rule was acctually
+ * accepted by hardware (have look at in_hw flag).
+ */
+ if (flow_tcf_check_inhw(ctx, dev_flow)) {
+ flow_tcf_remove(dev, flow);
+ return rte_flow_error_set
+ (error, ENOENT,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "netlink: rule has no in_hw flag set");
+ }
return 0;
}
if (dev_flow->tcf.tunnel) {
@@ -5137,45 +5330,6 @@ flow_tcf_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
}
/**
- * Remove flow from E-Switch by sending Netlink message.
- *
- * @param[in] dev
- * Pointer to Ethernet device.
- * @param[in, out] flow
- * Pointer to the sub flow.
- */
-static void
-flow_tcf_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
-{
- struct priv *priv = dev->data->dev_private;
- struct mlx5_flow_tcf_context *ctx = priv->tcf_context;
- struct mlx5_flow *dev_flow;
- struct nlmsghdr *nlh;
-
- if (!flow)
- return;
- dev_flow = LIST_FIRST(&flow->dev_flows);
- if (!dev_flow)
- return;
- /* E-Switch flow can't be expanded. */
- assert(!LIST_NEXT(dev_flow, next));
- if (dev_flow->tcf.applied) {
- nlh = dev_flow->tcf.nlh;
- nlh->nlmsg_type = RTM_DELTFILTER;
- nlh->nlmsg_flags = NLM_F_REQUEST;
- flow_tcf_nl_ack(ctx, nlh, 0, NULL, NULL);
- if (dev_flow->tcf.tunnel) {
- assert(dev_flow->tcf.tunnel->vtep);
- flow_tcf_vtep_release(ctx,
- dev_flow->tcf.tunnel->vtep,
- dev_flow);
- dev_flow->tcf.tunnel->vtep = NULL;
- }
- dev_flow->tcf.applied = 0;
- }
-}
-
-/**
* Remove flow from E-Switch and release resources of the device flow.
*
* @param[in] dev
@@ -5494,7 +5648,7 @@ flow_tcf_nl_filter_parse_and_get(struct nlmsghdr *cnlh,
* Message received from Netlink.
* @param[out] data
* Pointer to data area to be filled by the parsing routine.
- * assumed to be a pinter to struct flow_tcf_stats_basic.
+ * assumed to be a pointer to struct flow_tcf_stats_basic.
*
* @return
* MNL_CB_OK value.
@@ -5542,7 +5696,7 @@ flow_tcf_query_count(struct rte_eth_dev *dev,
void *data,
struct rte_flow_error *error)
{
- struct flow_tcf_stats_basic sb_data = { 0 };
+ struct flow_tcf_stats_basic sb_data;
struct rte_flow_query_count *qc = data;
struct priv *priv = dev->data->dev_private;
struct mlx5_flow_tcf_context *ctx = priv->tcf_context;
@@ -5553,6 +5707,7 @@ flow_tcf_query_count(struct rte_eth_dev *dev,
ssize_t ret;
assert(qc);
+ memset(&sb_data, 0, sizeof(sb_data));
dev_flow = LIST_FIRST(&flow->dev_flows);
/* E-Switch flow can't be expanded. */
assert(!LIST_NEXT(dev_flow, next));
@@ -5714,7 +5869,7 @@ mlx5_flow_tcf_init(struct mlx5_flow_tcf_context *ctx,
tcm->tcm_parent = TC_H_INGRESS;
assert(sizeof(buf) >= nlh->nlmsg_len);
/* Ignore errors when qdisc is already absent. */
- if (flow_tcf_nl_ack(ctx, nlh, 0, NULL, NULL) &&
+ if (flow_tcf_nl_ack(ctx, nlh, NULL, NULL) &&
rte_errno != EINVAL && rte_errno != ENOENT)
return rte_flow_error_set(error, rte_errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -5731,7 +5886,7 @@ mlx5_flow_tcf_init(struct mlx5_flow_tcf_context *ctx,
tcm->tcm_parent = TC_H_INGRESS;
mnl_attr_put_strz_check(nlh, sizeof(buf), TCA_KIND, "ingress");
assert(sizeof(buf) >= nlh->nlmsg_len);
- if (flow_tcf_nl_ack(ctx, nlh, 0, NULL, NULL))
+ if (flow_tcf_nl_ack(ctx, nlh, NULL, NULL))
return rte_flow_error_set(error, rte_errno,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"netlink: failed to create ingress"
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index d6d95db5..81ec59d7 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -68,9 +68,10 @@ flow_verbs_counter_create(struct rte_eth_dev *dev,
#elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
struct priv *priv = dev->data->dev_private;
struct ibv_counters_init_attr init = {0};
- struct ibv_counter_attach_attr attach = {0};
+ struct ibv_counter_attach_attr attach;
int ret;
+ memset(&attach, 0, sizeof(attach));
counter->cs = mlx5_glue->create_counters(priv->ctx, &init);
if (!counter->cs) {
rte_errno = ENOTSUP;
@@ -1017,6 +1018,7 @@ flow_verbs_validate(struct rte_eth_dev *dev,
int ret;
uint64_t action_flags = 0;
uint64_t item_flags = 0;
+ uint64_t last_item = 0;
uint8_t next_protocol = 0xff;
if (items == NULL)
@@ -1036,26 +1038,26 @@ flow_verbs_validate(struct rte_eth_dev *dev,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
- MLX5_FLOW_LAYER_OUTER_L2;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
+ MLX5_FLOW_LAYER_OUTER_L2;
break;
case RTE_FLOW_ITEM_TYPE_VLAN:
ret = mlx5_flow_validate_item_vlan(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
- MLX5_FLOW_LAYER_INNER_VLAN) :
- (MLX5_FLOW_LAYER_OUTER_L2 |
- MLX5_FLOW_LAYER_OUTER_VLAN);
+ last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
+ MLX5_FLOW_LAYER_INNER_VLAN) :
+ (MLX5_FLOW_LAYER_OUTER_L2 |
+ MLX5_FLOW_LAYER_OUTER_VLAN);
break;
case RTE_FLOW_ITEM_TYPE_IPV4:
ret = mlx5_flow_validate_item_ipv4(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV4;
if (items->mask != NULL &&
((const struct rte_flow_item_ipv4 *)
items->mask)->hdr.next_proto_id) {
@@ -1075,8 +1077,8 @@ flow_verbs_validate(struct rte_eth_dev *dev,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
- MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
+ MLX5_FLOW_LAYER_OUTER_L3_IPV6;
if (items->mask != NULL &&
((const struct rte_flow_item_ipv6 *)
items->mask)->hdr.proto) {
@@ -1097,8 +1099,8 @@ flow_verbs_validate(struct rte_eth_dev *dev,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
- MLX5_FLOW_LAYER_OUTER_L4_UDP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
+ MLX5_FLOW_LAYER_OUTER_L4_UDP;
break;
case RTE_FLOW_ITEM_TYPE_TCP:
ret = mlx5_flow_validate_item_tcp
@@ -1108,15 +1110,15 @@ flow_verbs_validate(struct rte_eth_dev *dev,
error);
if (ret < 0)
return ret;
- item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
- MLX5_FLOW_LAYER_OUTER_L4_TCP;
+ last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
+ MLX5_FLOW_LAYER_OUTER_L4_TCP;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN:
ret = mlx5_flow_validate_item_vxlan(items, item_flags,
error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_VXLAN;
+ last_item = MLX5_FLOW_LAYER_VXLAN;
break;
case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
ret = mlx5_flow_validate_item_vxlan_gpe(items,
@@ -1124,28 +1126,29 @@ flow_verbs_validate(struct rte_eth_dev *dev,
dev, error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
+ last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
break;
case RTE_FLOW_ITEM_TYPE_GRE:
ret = mlx5_flow_validate_item_gre(items, item_flags,
next_protocol, error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_GRE;
+ last_item = MLX5_FLOW_LAYER_GRE;
break;
case RTE_FLOW_ITEM_TYPE_MPLS:
- ret = mlx5_flow_validate_item_mpls(items, item_flags,
- next_protocol,
- error);
+ ret = mlx5_flow_validate_item_mpls(dev, items,
+ item_flags,
+ last_item, error);
if (ret < 0)
return ret;
- item_flags |= MLX5_FLOW_LAYER_MPLS;
+ last_item = MLX5_FLOW_LAYER_MPLS;
break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ITEM,
NULL, "item not supported");
}
+ item_flags |= last_item;
}
for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
switch (actions->type) {
diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c
index f4b15d3f..442b2d23 100644
--- a/drivers/net/mlx5/mlx5_mr.c
+++ b/drivers/net/mlx5/mlx5_mr.c
@@ -342,8 +342,9 @@ mr_insert_dev_cache(struct rte_eth_dev *dev, struct mlx5_mr *mr)
DRV_LOG(DEBUG, "port %u inserting MR(%p) to global cache",
dev->data->port_id, (void *)mr);
for (n = 0; n < mr->ms_bmp_n; ) {
- struct mlx5_mr_cache entry = { 0, };
+ struct mlx5_mr_cache entry;
+ memset(&entry, 0, sizeof(entry));
/* Find a contiguous chunk and advance the index. */
n = mr_find_next_chunk(mr, &entry, n);
if (!entry.end)
@@ -386,8 +387,9 @@ mr_lookup_dev_list(struct rte_eth_dev *dev, struct mlx5_mr_cache *entry,
if (mr->ms_n == 0)
continue;
for (n = 0; n < mr->ms_bmp_n; ) {
- struct mlx5_mr_cache ret = { 0, };
+ struct mlx5_mr_cache ret;
+ memset(&ret, 0, sizeof(ret));
n = mr_find_next_chunk(mr, &ret, n);
if (addr >= ret.start && addr < ret.end) {
/* Found. */
@@ -570,7 +572,7 @@ mlx5_mr_create(struct rte_eth_dev *dev, struct mlx5_mr_cache *entry,
* Find out a contiguous virtual address chunk in use, to which the
* given address belongs, in order to register maximum range. In the
* best case where mempools are not dynamically recreated and
- * '--socket-mem' is speicified as an EAL option, it is very likely to
+ * '--socket-mem' is specified as an EAL option, it is very likely to
* have only one MR(LKey) per a socket and per a hugepage-size even
* though the system memory is highly fragmented.
*/
@@ -688,8 +690,9 @@ alloc_resources:
*/
for (n = 0; n < ms_n; ++n) {
uintptr_t start;
- struct mlx5_mr_cache ret = { 0, };
+ struct mlx5_mr_cache ret;
+ memset(&ret, 0, sizeof(ret));
start = data_re.start + n * msl->page_sz;
/* Exclude memsegs already registered by other MRs. */
if (mr_lookup_dev(dev, &ret, start) == UINT32_MAX) {
@@ -1042,7 +1045,7 @@ mlx5_rx_addr2mr_bh(struct mlx5_rxq_data *rxq, uintptr_t addr)
* @return
* Searched LKey on success, UINT32_MAX on no match.
*/
-uint32_t
+static uint32_t
mlx5_tx_addr2mr_bh(struct mlx5_txq_data *txq, uintptr_t addr)
{
struct mlx5_txq_ctrl *txq_ctrl =
@@ -1057,6 +1060,32 @@ mlx5_tx_addr2mr_bh(struct mlx5_txq_data *txq, uintptr_t addr)
}
/**
+ * Bottom-half of LKey search on Tx. If it can't be searched in the memseg
+ * list, register the mempool of the mbuf as externally allocated memory.
+ *
+ * @param txq
+ * Pointer to Tx queue structure.
+ * @param mb
+ * Pointer to mbuf.
+ *
+ * @return
+ * Searched LKey on success, UINT32_MAX on no match.
+ */
+uint32_t
+mlx5_tx_mb2mr_bh(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
+{
+ uintptr_t addr = (uintptr_t)mb->buf_addr;
+ uint32_t lkey;
+
+ lkey = mlx5_tx_addr2mr_bh(txq, addr);
+ if (lkey == UINT32_MAX && rte_errno == ENXIO) {
+ /* Mempool may have externally allocated memory. */
+ return mlx5_tx_update_ext_mp(txq, addr, mlx5_mb2mp(mb));
+ }
+ return lkey;
+}
+
+/**
* Flush all of the local cache entries.
*
* @param mr_ctrl
diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c
index eef48502..183da0e2 100644
--- a/drivers/net/mlx5/mlx5_rxq.c
+++ b/drivers/net/mlx5/mlx5_rxq.c
@@ -1468,6 +1468,8 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
tmpl->rxq.mp = mp;
tmpl->rxq.stats.idx = idx;
tmpl->rxq.elts_n = log2above(desc);
+ tmpl->rxq.rq_repl_thresh =
+ MLX5_VPMD_RXQ_RPLNSH_THRESH(1 << tmpl->rxq.elts_n);
tmpl->rxq.elts =
(struct rte_mbuf *(*)[1 << tmpl->rxq.elts_n])(tmpl + 1);
#ifndef RTE_ARCH_64
@@ -1782,7 +1784,7 @@ mlx5_hrxq_new(struct rte_eth_dev *dev,
struct mlx5_ind_table_ibv *ind_tbl;
struct ibv_qp *qp;
#ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
- struct mlx5dv_qp_init_attr qp_init_attr = {0};
+ struct mlx5dv_qp_init_attr qp_init_attr;
#endif
int err;
@@ -1795,6 +1797,7 @@ mlx5_hrxq_new(struct rte_eth_dev *dev,
return NULL;
}
#ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
+ memset(&qp_init_attr, 0, sizeof(qp_init_attr));
if (tunnel) {
qp_init_attr.comp_mask =
MLX5DV_QP_INIT_ATTR_MASK_QP_CREATE_FLAGS;
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 1b6200f6..f47d327c 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -101,6 +101,7 @@ struct mlx5_rxq_data {
uint16_t consumed_strd; /* Number of consumed strides in WQE. */
uint32_t rq_pi;
uint32_t cq_ci;
+ uint16_t rq_repl_thresh; /* Threshold for buffer replenishment. */
struct mlx5_mr_ctrl mr_ctrl; /* MR control descriptor. */
uint16_t mprq_max_memcpy_len; /* Maximum size of packet to memcpy. */
volatile void *wqes;
@@ -363,7 +364,7 @@ uint16_t mlx5_rx_burst_vec(void *dpdk_txq, struct rte_mbuf **pkts,
void mlx5_mr_flush_local_cache(struct mlx5_mr_ctrl *mr_ctrl);
uint32_t mlx5_rx_addr2mr_bh(struct mlx5_rxq_data *rxq, uintptr_t addr);
-uint32_t mlx5_tx_addr2mr_bh(struct mlx5_txq_data *txq, uintptr_t addr);
+uint32_t mlx5_tx_mb2mr_bh(struct mlx5_txq_data *txq, struct rte_mbuf *mb);
uint32_t mlx5_tx_update_ext_mp(struct mlx5_txq_data *txq, uintptr_t addr,
struct rte_mempool *mp);
@@ -379,17 +380,16 @@ uint32_t mlx5_tx_update_ext_mp(struct mlx5_txq_data *txq, uintptr_t addr,
* Address of the lock to use for that UAR access.
*/
static __rte_always_inline void
-__mlx5_uar_write64_relaxed(uint64_t val, volatile void *addr,
+__mlx5_uar_write64_relaxed(uint64_t val, void *addr,
rte_spinlock_t *lock __rte_unused)
{
#ifdef RTE_ARCH_64
- rte_write64_relaxed(val, addr);
+ *(uint64_t *)addr = val;
#else /* !RTE_ARCH_64 */
rte_spinlock_lock(lock);
- rte_write32_relaxed(val, addr);
+ *(uint32_t *)addr = val;
rte_io_wmb();
- rte_write32_relaxed(val >> 32,
- (volatile void *)((volatile char *)addr + 4));
+ *((uint32_t *)addr + 1) = val >> 32;
rte_spinlock_unlock(lock);
#endif
}
@@ -407,7 +407,7 @@ __mlx5_uar_write64_relaxed(uint64_t val, volatile void *addr,
* Address of the lock to use for that UAR access.
*/
static __rte_always_inline void
-__mlx5_uar_write64(uint64_t val, volatile void *addr, rte_spinlock_t *lock)
+__mlx5_uar_write64(uint64_t val, void *addr, rte_spinlock_t *lock)
{
rte_io_wmb();
__mlx5_uar_write64_relaxed(val, addr, lock);
@@ -619,7 +619,7 @@ mlx5_tx_complete(struct mlx5_txq_data *txq)
* @return
* Memory pool where data is located for given mbuf.
*/
-static struct rte_mempool *
+static inline struct rte_mempool *
mlx5_mb2mp(struct rte_mbuf *buf)
{
if (unlikely(RTE_MBUF_INDIRECT(buf)))
@@ -668,9 +668,10 @@ mlx5_rx_addr2mr(struct mlx5_rxq_data *rxq, uintptr_t addr)
* Searched LKey on success, UINT32_MAX on no match.
*/
static __rte_always_inline uint32_t
-mlx5_tx_addr2mr(struct mlx5_txq_data *txq, uintptr_t addr)
+mlx5_tx_mb2mr(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
{
struct mlx5_mr_ctrl *mr_ctrl = &txq->mr_ctrl;
+ uintptr_t addr = (uintptr_t)mb->buf_addr;
uint32_t lkey;
/* Check generation bit to see if there's any change on existing MRs. */
@@ -681,23 +682,8 @@ mlx5_tx_addr2mr(struct mlx5_txq_data *txq, uintptr_t addr)
MLX5_MR_CACHE_N, addr);
if (likely(lkey != UINT32_MAX))
return lkey;
- /* Take slower bottom-half (binary search) on miss. */
- return mlx5_tx_addr2mr_bh(txq, addr);
-}
-
-static __rte_always_inline uint32_t
-mlx5_tx_mb2mr(struct mlx5_txq_data *txq, struct rte_mbuf *mb)
-{
- uintptr_t addr = (uintptr_t)mb->buf_addr;
- uint32_t lkey = mlx5_tx_addr2mr(txq, addr);
-
- if (likely(lkey != UINT32_MAX))
- return lkey;
- if (rte_errno == ENXIO) {
- /* Mempool may have externally allocated memory. */
- lkey = mlx5_tx_update_ext_mp(txq, addr, mlx5_mb2mp(mb));
- }
- return lkey;
+ /* Take slower bottom-half on miss. */
+ return mlx5_tx_mb2mr_bh(txq, mb);
}
/**
diff --git a/drivers/net/mlx5/mlx5_rxtx_vec_neon.h b/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
index 0b729f18..883fe1bf 100644
--- a/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
+++ b/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
@@ -732,7 +732,7 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
* N - (rq_ci - rq_pi) := # of buffers consumed (to be replenished).
*/
repl_n = q_n - (rxq->rq_ci - rxq->rq_pi);
- if (repl_n >= MLX5_VPMD_RXQ_RPLNSH_THRESH(q_n))
+ if (repl_n >= rxq->rq_repl_thresh)
mlx5_rx_replenish_bulk_mbuf(rxq, repl_n);
/* See if there're unreturned mbufs from compressed CQE. */
rcvd_pkt = rxq->cq_ci - rxq->rq_pi;
diff --git a/drivers/net/mlx5/mlx5_rxtx_vec_sse.h b/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
index e0f95f92..14117c4b 100644
--- a/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
+++ b/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
@@ -716,7 +716,7 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
* N - (rq_ci - rq_pi) := # of buffers consumed (to be replenished).
*/
repl_n = q_n - (rxq->rq_ci - rxq->rq_pi);
- if (repl_n >= MLX5_VPMD_RXQ_RPLNSH_THRESH(q_n))
+ if (repl_n >= rxq->rq_repl_thresh)
mlx5_rx_replenish_bulk_mbuf(rxq, repl_n);
/* See if there're unreturned mbufs from compressed CQE. */
rcvd_pkt = rxq->cq_ci - rxq->rq_pi;
diff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c
index a14d1e49..fccb9af0 100644
--- a/drivers/net/mlx5/mlx5_stats.c
+++ b/drivers/net/mlx5/mlx5_stats.c
@@ -354,10 +354,11 @@ int
mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
struct priv *priv = dev->data->dev_private;
- struct rte_eth_stats tmp = {0};
+ struct rte_eth_stats tmp;
unsigned int i;
unsigned int idx;
+ memset(&tmp, 0, sizeof(tmp));
/* Add software counters. */
for (i = 0; (i != priv->rxqs_n); ++i) {
struct mlx5_rxq_data *rxq = (*priv->rxqs)[i];
diff --git a/drivers/net/mvpp2/mrvl_mtr.c b/drivers/net/mvpp2/mrvl_mtr.c
index 9cd53bed..9adcd975 100644
--- a/drivers/net/mvpp2/mrvl_mtr.c
+++ b/drivers/net/mvpp2/mrvl_mtr.c
@@ -422,7 +422,7 @@ mrvl_meter_profile_update(struct rte_eth_dev *dev, uint32_t mtr_id,
struct mrvl_priv *priv = dev->data->dev_private;
struct mrvl_mtr_profile *profile;
struct mrvl_mtr *mtr;
- int ret, enabled;
+ int ret, enabled = 0;
if (!priv->ppio)
return -rte_mtr_error_set(error, EPERM,
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
index a3063be4..046e1298 100644
--- a/drivers/net/octeontx/octeontx_ethdev.c
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -1238,15 +1238,8 @@ octeontx_probe(struct rte_vdev_device *dev)
res = -EINVAL;
goto parse_error;
}
- if (pnum > qnum) {
- /*
- * We don't poll on event ports
- * that do not have any queues assigned.
- */
- pnum = qnum;
- PMD_INIT_LOG(INFO,
- "reducing number of active event ports to %d", pnum);
- }
+
+ /* Enable all queues available */
for (i = 0; i < qnum; i++) {
res = rte_event_queue_setup(evdev, i, NULL);
if (res < 0) {
@@ -1256,6 +1249,7 @@ octeontx_probe(struct rte_vdev_device *dev)
}
}
+ /* Enable all ports available */
for (i = 0; i < pnum; i++) {
res = rte_event_port_setup(evdev, i, NULL);
if (res < 0) {
@@ -1264,6 +1258,14 @@ octeontx_probe(struct rte_vdev_device *dev)
i, res);
goto parse_error;
}
+ }
+
+ /*
+ * Do 1:1 links for ports & queues. All queues would be mapped to
+ * one port. If there are more ports than queues, then some ports
+ * won't be linked to any queue.
+ */
+ for (i = 0; i < qnum; i++) {
/* Link one queue to one event port */
qlist = i;
res = rte_event_port_link(evdev, i, &qlist, NULL, 1);
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 7bbe72e2..9fd93277 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -58,8 +58,8 @@ struct queue_stat {
};
struct pcap_rx_queue {
- pcap_t *pcap;
- uint16_t in_port;
+ uint16_t port_id;
+ uint16_t queue_id;
struct rte_mempool *mb_pool;
struct queue_stat rx_stat;
char name[PATH_MAX];
@@ -67,8 +67,8 @@ struct pcap_rx_queue {
};
struct pcap_tx_queue {
- pcap_dumper_t *dumper;
- pcap_t *pcap;
+ uint16_t port_id;
+ uint16_t queue_id;
struct queue_stat tx_stat;
char name[PATH_MAX];
char type[ETH_PCAP_ARG_MAXLEN];
@@ -77,12 +77,19 @@ struct pcap_tx_queue {
struct pmd_internals {
struct pcap_rx_queue rx_queue[RTE_PMD_PCAP_MAX_QUEUES];
struct pcap_tx_queue tx_queue[RTE_PMD_PCAP_MAX_QUEUES];
+ char devargs[ETH_PCAP_ARG_MAXLEN];
struct ether_addr eth_addr;
int if_index;
int single_iface;
int phy_mac;
};
+struct pmd_process_private {
+ pcap_t *rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+ pcap_t *tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
+ pcap_dumper_t *tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
+};
+
struct pmd_devargs {
unsigned int num_of_queue;
struct devargs_queue {
@@ -176,14 +183,19 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
unsigned int i;
struct pcap_pkthdr header;
+ struct pmd_process_private *pp;
const u_char *packet;
struct rte_mbuf *mbuf;
struct pcap_rx_queue *pcap_q = queue;
uint16_t num_rx = 0;
uint16_t buf_size;
uint32_t rx_bytes = 0;
+ pcap_t *pcap;
+
+ pp = rte_eth_devices[pcap_q->port_id].process_private;
+ pcap = pp->rx_pcap[pcap_q->queue_id];
- if (unlikely(pcap_q->pcap == NULL || nb_pkts == 0))
+ if (unlikely(pcap == NULL || nb_pkts == 0))
return 0;
/* Reads the given number of packets from the pcap file one by one
@@ -191,7 +203,7 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
*/
for (i = 0; i < nb_pkts; i++) {
/* Get the next PCAP packet */
- packet = pcap_next(pcap_q->pcap, &header);
+ packet = pcap_next(pcap, &header);
if (unlikely(packet == NULL))
break;
@@ -220,7 +232,7 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
}
mbuf->pkt_len = (uint16_t)header.caplen;
- mbuf->port = pcap_q->in_port;
+ mbuf->port = pcap_q->port_id;
bufs[num_rx] = mbuf;
num_rx++;
rx_bytes += header.caplen;
@@ -250,12 +262,17 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
unsigned int i;
struct rte_mbuf *mbuf;
+ struct pmd_process_private *pp;
struct pcap_tx_queue *dumper_q = queue;
uint16_t num_tx = 0;
uint32_t tx_bytes = 0;
struct pcap_pkthdr header;
+ pcap_dumper_t *dumper;
+
+ pp = rte_eth_devices[dumper_q->port_id].process_private;
+ dumper = pp->tx_dumper[dumper_q->queue_id];
- if (dumper_q->dumper == NULL || nb_pkts == 0)
+ if (dumper == NULL || nb_pkts == 0)
return 0;
/* writes the nb_pkts packets to the previously opened pcap file
@@ -267,12 +284,12 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
header.caplen = header.len;
if (likely(mbuf->nb_segs == 1)) {
- pcap_dump((u_char *)dumper_q->dumper, &header,
+ pcap_dump((u_char *)dumper, &header,
rte_pktmbuf_mtod(mbuf, void*));
} else {
if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) {
eth_pcap_gather_data(tx_pcap_data, mbuf);
- pcap_dump((u_char *)dumper_q->dumper, &header,
+ pcap_dump((u_char *)dumper, &header,
tx_pcap_data);
} else {
PMD_LOG(ERR,
@@ -295,7 +312,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
* process stops and to make sure the pcap file is actually written,
* we flush the pcap dumper within each burst.
*/
- pcap_dump_flush(dumper_q->dumper);
+ pcap_dump_flush(dumper);
dumper_q->tx_stat.pkts += num_tx;
dumper_q->tx_stat.bytes += tx_bytes;
dumper_q->tx_stat.err_pkts += nb_pkts - num_tx;
@@ -312,24 +329,29 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
unsigned int i;
int ret;
struct rte_mbuf *mbuf;
+ struct pmd_process_private *pp;
struct pcap_tx_queue *tx_queue = queue;
uint16_t num_tx = 0;
uint32_t tx_bytes = 0;
+ pcap_t *pcap;
- if (unlikely(nb_pkts == 0 || tx_queue->pcap == NULL))
+ pp = rte_eth_devices[tx_queue->port_id].process_private;
+ pcap = pp->tx_pcap[tx_queue->queue_id];
+
+ if (unlikely(nb_pkts == 0 || pcap == NULL))
return 0;
for (i = 0; i < nb_pkts; i++) {
mbuf = bufs[i];
if (likely(mbuf->nb_segs == 1)) {
- ret = pcap_sendpacket(tx_queue->pcap,
+ ret = pcap_sendpacket(pcap,
rte_pktmbuf_mtod(mbuf, u_char *),
mbuf->pkt_len);
} else {
if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) {
eth_pcap_gather_data(tx_pcap_data, mbuf);
- ret = pcap_sendpacket(tx_queue->pcap,
+ ret = pcap_sendpacket(pcap,
tx_pcap_data, mbuf->pkt_len);
} else {
PMD_LOG(ERR,
@@ -430,6 +452,7 @@ eth_dev_start(struct rte_eth_dev *dev)
{
unsigned int i;
struct pmd_internals *internals = dev->data->dev_private;
+ struct pmd_process_private *pp = dev->process_private;
struct pcap_tx_queue *tx;
struct pcap_rx_queue *rx;
@@ -438,10 +461,11 @@ eth_dev_start(struct rte_eth_dev *dev)
tx = &internals->tx_queue[0];
rx = &internals->rx_queue[0];
- if (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {
- if (open_single_iface(tx->name, &tx->pcap) < 0)
+ if (!pp->tx_pcap[0] &&
+ strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {
+ if (open_single_iface(tx->name, &pp->tx_pcap[0]) < 0)
return -1;
- rx->pcap = tx->pcap;
+ pp->rx_pcap[0] = pp->tx_pcap[0];
}
goto status_up;
@@ -451,13 +475,14 @@ eth_dev_start(struct rte_eth_dev *dev)
for (i = 0; i < dev->data->nb_tx_queues; i++) {
tx = &internals->tx_queue[i];
- if (!tx->dumper &&
+ if (!pp->tx_dumper[i] &&
strcmp(tx->type, ETH_PCAP_TX_PCAP_ARG) == 0) {
- if (open_single_tx_pcap(tx->name, &tx->dumper) < 0)
+ if (open_single_tx_pcap(tx->name,
+ &pp->tx_dumper[i]) < 0)
return -1;
- } else if (!tx->pcap &&
+ } else if (!pp->tx_pcap[i] &&
strcmp(tx->type, ETH_PCAP_TX_IFACE_ARG) == 0) {
- if (open_single_iface(tx->name, &tx->pcap) < 0)
+ if (open_single_iface(tx->name, &pp->tx_pcap[i]) < 0)
return -1;
}
}
@@ -466,14 +491,14 @@ eth_dev_start(struct rte_eth_dev *dev)
for (i = 0; i < dev->data->nb_rx_queues; i++) {
rx = &internals->rx_queue[i];
- if (rx->pcap != NULL)
+ if (pp->rx_pcap[i] != NULL)
continue;
if (strcmp(rx->type, ETH_PCAP_RX_PCAP_ARG) == 0) {
- if (open_single_rx_pcap(rx->name, &rx->pcap) < 0)
+ if (open_single_rx_pcap(rx->name, &pp->rx_pcap[i]) < 0)
return -1;
} else if (strcmp(rx->type, ETH_PCAP_RX_IFACE_ARG) == 0) {
- if (open_single_iface(rx->name, &rx->pcap) < 0)
+ if (open_single_iface(rx->name, &pp->rx_pcap[i]) < 0)
return -1;
}
}
@@ -500,39 +525,32 @@ eth_dev_stop(struct rte_eth_dev *dev)
{
unsigned int i;
struct pmd_internals *internals = dev->data->dev_private;
- struct pcap_tx_queue *tx;
- struct pcap_rx_queue *rx;
+ struct pmd_process_private *pp = dev->process_private;
/* Special iface case. Single pcap is open and shared between tx/rx. */
if (internals->single_iface) {
- tx = &internals->tx_queue[0];
- rx = &internals->rx_queue[0];
- pcap_close(tx->pcap);
- tx->pcap = NULL;
- rx->pcap = NULL;
+ pcap_close(pp->tx_pcap[0]);
+ pp->tx_pcap[0] = NULL;
+ pp->rx_pcap[0] = NULL;
goto status_down;
}
for (i = 0; i < dev->data->nb_tx_queues; i++) {
- tx = &internals->tx_queue[i];
-
- if (tx->dumper != NULL) {
- pcap_dump_close(tx->dumper);
- tx->dumper = NULL;
+ if (pp->tx_dumper[i] != NULL) {
+ pcap_dump_close(pp->tx_dumper[i]);
+ pp->tx_dumper[i] = NULL;
}
- if (tx->pcap != NULL) {
- pcap_close(tx->pcap);
- tx->pcap = NULL;
+ if (pp->tx_pcap[i] != NULL) {
+ pcap_close(pp->tx_pcap[i]);
+ pp->tx_pcap[i] = NULL;
}
}
for (i = 0; i < dev->data->nb_rx_queues; i++) {
- rx = &internals->rx_queue[i];
-
- if (rx->pcap != NULL) {
- pcap_close(rx->pcap);
- rx->pcap = NULL;
+ if (pp->rx_pcap[i] != NULL) {
+ pcap_close(pp->rx_pcap[i]);
+ pp->rx_pcap[i] = NULL;
}
}
@@ -649,8 +667,9 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
struct pcap_rx_queue *pcap_q = &internals->rx_queue[rx_queue_id];
pcap_q->mb_pool = mb_pool;
+ pcap_q->port_id = dev->data->port_id;
+ pcap_q->queue_id = rx_queue_id;
dev->data->rx_queues[rx_queue_id] = pcap_q;
- pcap_q->in_port = dev->data->port_id;
return 0;
}
@@ -663,8 +682,11 @@ eth_tx_queue_setup(struct rte_eth_dev *dev,
const struct rte_eth_txconf *tx_conf __rte_unused)
{
struct pmd_internals *internals = dev->data->dev_private;
+ struct pcap_tx_queue *pcap_q = &internals->tx_queue[tx_queue_id];
- dev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id];
+ pcap_q->port_id = dev->data->port_id;
+ pcap_q->queue_id = tx_queue_id;
+ dev->data->tx_queues[tx_queue_id] = pcap_q;
return 0;
}
@@ -896,16 +918,29 @@ pmd_init_internals(struct rte_vdev_device *vdev,
struct rte_eth_dev **eth_dev)
{
struct rte_eth_dev_data *data;
+ struct pmd_process_private *pp;
unsigned int numa_node = vdev->device.numa_node;
PMD_LOG(INFO, "Creating pcap-backed ethdev on numa socket %d",
numa_node);
+ pp = (struct pmd_process_private *)
+ rte_zmalloc(NULL, sizeof(struct pmd_process_private),
+ RTE_CACHE_LINE_SIZE);
+
+ if (pp == NULL) {
+ PMD_LOG(ERR,
+ "Failed to allocate memory for process private");
+ return -1;
+ }
+
/* reserve an ethdev entry */
*eth_dev = rte_eth_vdev_allocate(vdev, sizeof(**internals));
- if (!(*eth_dev))
+ if (!(*eth_dev)) {
+ rte_free(pp);
return -1;
-
+ }
+ (*eth_dev)->process_private = pp;
/* now put it all together
* - store queue data in internals,
* - store numa_node info in eth_dev
@@ -934,6 +969,9 @@ pmd_init_internals(struct rte_vdev_device *vdev,
*/
(*eth_dev)->dev_ops = &ops;
+ strlcpy((*internals)->devargs, rte_vdev_device_args(vdev),
+ ETH_PCAP_ARG_MAXLEN);
+
return 0;
}
@@ -1027,6 +1065,7 @@ eth_from_pcaps_common(struct rte_vdev_device *vdev,
struct pmd_devargs *tx_queues, const unsigned int nb_tx_queues,
struct pmd_internals **internals, struct rte_eth_dev **eth_dev)
{
+ struct pmd_process_private *pp;
unsigned int i;
/* do some parameter checking */
@@ -1039,11 +1078,12 @@ eth_from_pcaps_common(struct rte_vdev_device *vdev,
eth_dev) < 0)
return -1;
+ pp = (*eth_dev)->process_private;
for (i = 0; i < nb_rx_queues; i++) {
struct pcap_rx_queue *rx = &(*internals)->rx_queue[i];
struct devargs_queue *queue = &rx_queues->queue[i];
- rx->pcap = queue->pcap;
+ pp->rx_pcap[i] = queue->pcap;
snprintf(rx->name, sizeof(rx->name), "%s", queue->name);
snprintf(rx->type, sizeof(rx->type), "%s", queue->type);
}
@@ -1052,8 +1092,8 @@ eth_from_pcaps_common(struct rte_vdev_device *vdev,
struct pcap_tx_queue *tx = &(*internals)->tx_queue[i];
struct devargs_queue *queue = &tx_queues->queue[i];
- tx->dumper = queue->dumper;
- tx->pcap = queue->pcap;
+ pp->tx_dumper[i] = queue->dumper;
+ pp->tx_pcap[i] = queue->pcap;
snprintf(tx->name, sizeof(tx->name), "%s", queue->name);
snprintf(tx->type, sizeof(tx->type), "%s", queue->type);
}
@@ -1111,7 +1151,8 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
struct rte_kvargs *kvlist;
struct pmd_devargs pcaps = {0};
struct pmd_devargs dumpers = {0};
- struct rte_eth_dev *eth_dev;
+ struct rte_eth_dev *eth_dev = NULL;
+ struct pmd_internals *internal;
int single_iface = 0;
int ret;
@@ -1128,16 +1169,18 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
PMD_LOG(ERR, "Failed to probe %s", name);
return -1;
}
- /* TODO: request info from primary to set up Rx and Tx */
- eth_dev->dev_ops = &ops;
- eth_dev->device = &dev->device;
- rte_eth_dev_probing_finish(eth_dev);
- return 0;
- }
- kvlist = rte_kvargs_parse(rte_vdev_device_args(dev), valid_arguments);
- if (kvlist == NULL)
- return -1;
+ internal = eth_dev->data->dev_private;
+
+ kvlist = rte_kvargs_parse(internal->devargs, valid_arguments);
+ if (kvlist == NULL)
+ return -1;
+ } else {
+ kvlist = rte_kvargs_parse(rte_vdev_device_args(dev),
+ valid_arguments);
+ if (kvlist == NULL)
+ return -1;
+ }
/*
* If iface argument is passed we open the NICs and use them for
@@ -1202,6 +1245,45 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
goto free_kvlist;
create_eth:
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+ struct pmd_process_private *pp;
+ unsigned int i;
+
+ internal = eth_dev->data->dev_private;
+ pp = (struct pmd_process_private *)
+ rte_zmalloc(NULL,
+ sizeof(struct pmd_process_private),
+ RTE_CACHE_LINE_SIZE);
+
+ if (pp == NULL) {
+ PMD_LOG(ERR,
+ "Failed to allocate memory for process private");
+ return -1;
+ }
+
+ eth_dev->dev_ops = &ops;
+ eth_dev->device = &dev->device;
+
+ /* setup process private */
+ for (i = 0; i < pcaps.num_of_queue; i++)
+ pp->rx_pcap[i] = pcaps.queue[i].pcap;
+
+ for (i = 0; i < dumpers.num_of_queue; i++) {
+ pp->tx_dumper[i] = dumpers.queue[i].dumper;
+ pp->tx_pcap[i] = dumpers.queue[i].pcap;
+ }
+
+ eth_dev->process_private = pp;
+ eth_dev->rx_pkt_burst = eth_pcap_rx;
+ if (is_tx_pcap)
+ eth_dev->tx_pkt_burst = eth_pcap_tx_dumper;
+ else
+ eth_dev->tx_pkt_burst = eth_pcap_tx;
+
+ rte_eth_dev_probing_finish(eth_dev);
+ return 0;
+ }
+
ret = eth_from_pcaps(dev, &pcaps, pcaps.num_of_queue, &dumpers,
dumpers.num_of_queue, single_iface, is_tx_pcap);
@@ -1235,6 +1317,7 @@ pmd_pcap_remove(struct rte_vdev_device *dev)
eth_dev->data->mac_addrs = NULL;
}
+ rte_free(eth_dev->process_private);
rte_eth_dev_release_port(eth_dev);
return 0;
diff --git a/examples/ipv4_multicast/main.c b/examples/ipv4_multicast/main.c
index 4073a490..428ca469 100644
--- a/examples/ipv4_multicast/main.c
+++ b/examples/ipv4_multicast/main.c
@@ -266,8 +266,6 @@ mcast_out_pkt(struct rte_mbuf *pkt, int use_clone)
hdr->tx_offload = pkt->tx_offload;
hdr->hash = pkt->hash;
- hdr->ol_flags = pkt->ol_flags;
-
__rte_mbuf_sanity_check(hdr, 1);
return hdr;
}
diff --git a/examples/vhost_crypto/main.c b/examples/vhost_crypto/main.c
index cbb5e49d..f08babd9 100644
--- a/examples/vhost_crypto/main.c
+++ b/examples/vhost_crypto/main.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <assert.h>
@@ -442,6 +443,9 @@ free_resource(void)
struct lcore_option *lo = &options.los[i];
struct vhost_crypto_info *info = options.infos[i];
+ if (!info)
+ continue;
+
rte_mempool_free(info->cop_pool);
rte_mempool_free(info->sess_pool);
@@ -493,6 +497,19 @@ main(int argc, char *argv[])
info->nb_vids = lo->nb_sockets;
rte_cryptodev_info_get(info->cid, &dev_info);
+ if (options.zero_copy == RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE) {
+#define VHOST_CRYPTO_CDEV_NAME_AESNI_MB_PMD crypto_aesni_mb
+#define VHOST_CRYPTO_CDEV_NAME_AESNI_GCM_PMD crypto_aesni_gcm
+ if (strstr(dev_info.driver_name,
+ RTE_STR(VHOST_CRYPTO_CDEV_NAME_AESNI_MB_PMD)) ||
+ strstr(dev_info.driver_name,
+ RTE_STR(VHOST_CRYPTO_CDEV_NAME_AESNI_GCM_PMD)))
+ RTE_LOG(ERR, USER1, "Cannot enable zero-copy in %s\n",
+ dev_info.driver_name);
+ ret = -EPERM;
+ goto error_exit;
+ }
+
if (dev_info.max_nb_queue_pairs < info->qid + 1) {
RTE_LOG(ERR, USER1, "Number of queues cannot over %u",
dev_info.max_nb_queue_pairs);
diff --git a/lib/librte_eal/common/eal_common_memalloc.c b/lib/librte_eal/common/eal_common_memalloc.c
index 1d41ea11..37127197 100644
--- a/lib/librte_eal/common/eal_common_memalloc.c
+++ b/lib/librte_eal/common/eal_common_memalloc.c
@@ -77,7 +77,7 @@ eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start,
const struct rte_memseg *ms;
/* for IOVA_VA, it's always contiguous */
- if (rte_eal_iova_mode() == RTE_IOVA_VA)
+ if (rte_eal_iova_mode() == RTE_IOVA_VA && !msl->external)
return true;
/* for legacy memory, it's always contiguous */
diff --git a/lib/librte_eal/common/eal_filesystem.h b/lib/librte_eal/common/eal_filesystem.h
index b3e8ae5e..6e0331fd 100644
--- a/lib/librte_eal/common/eal_filesystem.h
+++ b/lib/librte_eal/common/eal_filesystem.h
@@ -25,10 +25,6 @@
int
eal_create_runtime_dir(void);
-/* returns runtime dir */
-const char *
-rte_eal_get_runtime_dir(void);
-
#define RUNTIME_CONFIG_FNAME "config"
static inline const char *
eal_runtime_config_path(void)
diff --git a/lib/librte_eal/common/include/rte_version.h b/lib/librte_eal/common/include/rte_version.h
index fc26e97a..45b89430 100644
--- a/lib/librte_eal/common/include/rte_version.h
+++ b/lib/librte_eal/common/include/rte_version.h
@@ -49,7 +49,7 @@ extern "C" {
* 0-15 = release candidates
* 16 = release
*/
-#define RTE_VER_RELEASE 3
+#define RTE_VER_RELEASE 4
/**
* Macro to compute a version number usable for comparisons
diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
index 1a74660d..9d3dcb6a 100644
--- a/lib/librte_eal/common/malloc_elem.c
+++ b/lib/librte_eal/common/malloc_elem.c
@@ -316,13 +316,15 @@ remove_elem(struct malloc_elem *elem)
static int
next_elem_is_adjacent(struct malloc_elem *elem)
{
- return elem->next == RTE_PTR_ADD(elem, elem->size);
+ return elem->next == RTE_PTR_ADD(elem, elem->size) &&
+ elem->next->msl == elem->msl;
}
static int
prev_elem_is_adjacent(struct malloc_elem *elem)
{
- return elem == RTE_PTR_ADD(elem->prev, elem->prev->size);
+ return elem == RTE_PTR_ADD(elem->prev, elem->prev->size) &&
+ elem->prev->msl == elem->msl;
}
/*
diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c b/lib/librte_eal/linuxapp/eal/eal_dev.c
index d589c692..2830c868 100644
--- a/lib/librte_eal/linuxapp/eal/eal_dev.c
+++ b/lib/librte_eal/linuxapp/eal/eal_dev.c
@@ -258,7 +258,7 @@ dev_uev_handler(__rte_unused void *param)
if (bus == NULL) {
RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n",
busname);
- return;
+ goto failure_handle_err;
}
dev = bus->find_device(NULL, cmp_dev_name,
@@ -266,19 +266,23 @@ dev_uev_handler(__rte_unused void *param)
if (dev == NULL) {
RTE_LOG(ERR, EAL, "Cannot find device (%s) on "
"bus (%s)\n", uevent.devname, busname);
- return;
+ goto failure_handle_err;
}
ret = bus->hot_unplug_handler(dev);
- rte_spinlock_unlock(&failure_handle_lock);
if (ret) {
RTE_LOG(ERR, EAL, "Can not handle hot-unplug "
"for device (%s)\n", dev->name);
- return;
}
+ rte_spinlock_unlock(&failure_handle_lock);
}
rte_dev_event_callback_process(uevent.devname, uevent.type);
}
+
+ return;
+
+failure_handle_err:
+ rte_spinlock_unlock(&failure_handle_lock);
}
int __rte_experimental
diff --git a/lib/librte_eal/linuxapp/eal/eal_memalloc.c b/lib/librte_eal/linuxapp/eal/eal_memalloc.c
index 48b9c736..78493956 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memalloc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memalloc.c
@@ -753,9 +753,6 @@ mapped:
munmap(addr, alloc_sz);
unmapped:
flags = MAP_FIXED;
-#ifdef RTE_ARCH_PPC_64
- flags |= MAP_HUGETLB;
-#endif
new_addr = eal_get_virtual_area(addr, &alloc_sz, alloc_sz, 0, flags);
if (new_addr != addr) {
if (new_addr != NULL)
diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c
index 48b23ce1..6f94621d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memory.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c
@@ -847,10 +847,6 @@ alloc_va_space(struct rte_memseg_list *msl)
void *addr;
int flags = 0;
-#ifdef RTE_ARCH_PPC_64
- flags |= MAP_HUGETLB;
-#endif
-
page_sz = msl->page_sz;
mem_sz = page_sz * msl->memseg_arr.len;
diff --git a/lib/librte_efd/rte_efd.c b/lib/librte_efd/rte_efd.c
index a780e2fe..e6e5cfda 100644
--- a/lib/librte_efd/rte_efd.c
+++ b/lib/librte_efd/rte_efd.c
@@ -692,7 +692,8 @@ rte_efd_create(const char *name, uint32_t max_num_rules, uint32_t key_len,
offline_cpu_socket, 0);
if (r == NULL) {
RTE_LOG(ERR, EFD, "memory allocation failed\n");
- goto error_unlock_exit;
+ rte_efd_free(table);
+ return NULL;
}
/* Populate free slots ring. Entry zero is reserved for key misses. */
diff --git a/lib/librte_security/Makefile b/lib/librte_security/Makefile
index 8daebea4..bd92343b 100644
--- a/lib/librte_security/Makefile
+++ b/lib/librte_security/Makefile
@@ -10,7 +10,6 @@ LIB = librte_security.a
LIBABIVER := 1
# build flags
-CFLAGS += -DALLOW_EXPERIMENTAL_API
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
LDLIBS += -lrte_eal -lrte_mempool
diff --git a/lib/librte_security/meson.build b/lib/librte_security/meson.build
index 4c85894c..532953fc 100644
--- a/lib/librte_security/meson.build
+++ b/lib/librte_security/meson.build
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation
-allow_experimental_apis = true
sources = files('rte_security.c')
headers = files('rte_security.h', 'rte_security_driver.h')
deps += ['mempool', 'cryptodev']
diff --git a/lib/librte_security/rte_security.c b/lib/librte_security/rte_security.c
index c6355de9..bc81ce15 100644
--- a/lib/librte_security/rte_security.c
+++ b/lib/librte_security/rte_security.c
@@ -10,7 +10,7 @@
#include "rte_security_driver.h"
struct rte_security_session *
-__rte_experimental rte_security_session_create(struct rte_security_ctx *instance,
+rte_security_session_create(struct rte_security_ctx *instance,
struct rte_security_session_conf *conf,
struct rte_mempool *mp)
{
@@ -33,7 +33,7 @@ __rte_experimental rte_security_session_create(struct rte_security_ctx *instance
return sess;
}
-int __rte_experimental
+int
rte_security_session_update(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_security_session_conf *conf)
@@ -42,14 +42,14 @@ rte_security_session_update(struct rte_security_ctx *instance,
return instance->ops->session_update(instance->device, sess, conf);
}
-unsigned int __rte_experimental
+unsigned int
rte_security_session_get_size(struct rte_security_ctx *instance)
{
RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_get_size, 0);
return instance->ops->session_get_size(instance->device);
}
-int __rte_experimental
+int
rte_security_session_stats_get(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_security_stats *stats)
@@ -58,7 +58,7 @@ rte_security_session_stats_get(struct rte_security_ctx *instance,
return instance->ops->session_stats_get(instance->device, sess, stats);
}
-int __rte_experimental
+int
rte_security_session_destroy(struct rte_security_ctx *instance,
struct rte_security_session *sess)
{
@@ -76,7 +76,7 @@ rte_security_session_destroy(struct rte_security_ctx *instance,
return ret;
}
-int __rte_experimental
+int
rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_mbuf *m, void *params)
@@ -86,7 +86,7 @@ rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
sess, m, params);
}
-void * __rte_experimental
+void *
rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md)
{
void *userdata = NULL;
@@ -98,14 +98,14 @@ rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md)
return userdata;
}
-const struct rte_security_capability * __rte_experimental
+const struct rte_security_capability *
rte_security_capabilities_get(struct rte_security_ctx *instance)
{
RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->capabilities_get, NULL);
return instance->ops->capabilities_get(instance->device);
}
-const struct rte_security_capability * __rte_experimental
+const struct rte_security_capability *
rte_security_capability_get(struct rte_security_ctx *instance,
struct rte_security_capability_idx *idx)
{
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 1431b4df..e07b1328 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -8,7 +8,6 @@
/**
* @file rte_security.h
- * @b EXPERIMENTAL: this API may change without prior notice
*
* RTE Security Common Definitions
*
@@ -330,7 +329,7 @@ struct rte_security_session {
* - On success, pointer to session
* - On failure, NULL
*/
-struct rte_security_session * __rte_experimental
+struct rte_security_session *
rte_security_session_create(struct rte_security_ctx *instance,
struct rte_security_session_conf *conf,
struct rte_mempool *mp);
@@ -345,7 +344,7 @@ rte_security_session_create(struct rte_security_ctx *instance,
* - On success returns 0
* - On failure return errno
*/
-int __rte_experimental
+int
rte_security_session_update(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_security_session_conf *conf);
@@ -359,7 +358,7 @@ rte_security_session_update(struct rte_security_ctx *instance,
* - Size of the private data, if successful
* - 0 if device is invalid or does not support the operation.
*/
-unsigned int __rte_experimental
+unsigned int
rte_security_session_get_size(struct rte_security_ctx *instance);
/**
@@ -374,7 +373,7 @@ rte_security_session_get_size(struct rte_security_ctx *instance);
* - -EINVAL if session is NULL.
* - -EBUSY if not all device private data has been freed.
*/
-int __rte_experimental
+int
rte_security_session_destroy(struct rte_security_ctx *instance,
struct rte_security_session *sess);
@@ -391,7 +390,7 @@ rte_security_session_destroy(struct rte_security_ctx *instance,
* - On success, zero.
* - On failure, a negative value.
*/
-int __rte_experimental
+int
rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_mbuf *mb, void *params);
@@ -413,7 +412,7 @@ rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
* - On success, userdata
* - On failure, NULL
*/
-void * __rte_experimental
+void *
rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md);
/**
@@ -422,7 +421,7 @@ rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md);
* @param sym_op crypto operation
* @param sess security session
*/
-static inline int __rte_experimental
+static inline int
__rte_security_attach_session(struct rte_crypto_sym_op *sym_op,
struct rte_security_session *sess)
{
@@ -431,13 +430,13 @@ __rte_security_attach_session(struct rte_crypto_sym_op *sym_op,
return 0;
}
-static inline void * __rte_experimental
+static inline void *
get_sec_session_private_data(const struct rte_security_session *sess)
{
return sess->sess_private_data;
}
-static inline void __rte_experimental
+static inline void
set_sec_session_private_data(struct rte_security_session *sess,
void *private_data)
{
@@ -453,7 +452,7 @@ set_sec_session_private_data(struct rte_security_session *sess,
* @param op crypto operation
* @param sess security session
*/
-static inline int __rte_experimental
+static inline int
rte_security_attach_session(struct rte_crypto_op *op,
struct rte_security_session *sess)
{
@@ -500,7 +499,7 @@ struct rte_security_stats {
* - On success return 0
* - On failure errno
*/
-int __rte_experimental
+int
rte_security_session_stats_get(struct rte_security_ctx *instance,
struct rte_security_session *sess,
struct rte_security_stats *stats);
@@ -608,7 +607,7 @@ struct rte_security_capability_idx {
* - Returns array of security capabilities.
* - Return NULL if no capabilities available.
*/
-const struct rte_security_capability * __rte_experimental
+const struct rte_security_capability *
rte_security_capabilities_get(struct rte_security_ctx *instance);
/**
@@ -622,7 +621,7 @@ rte_security_capabilities_get(struct rte_security_ctx *instance);
* index criteria.
* - Return NULL if the capability not matched on security instance.
*/
-const struct rte_security_capability * __rte_experimental
+const struct rte_security_capability *
rte_security_capability_get(struct rte_security_ctx *instance,
struct rte_security_capability_idx *idx);
diff --git a/lib/librte_security/rte_security_driver.h b/lib/librte_security/rte_security_driver.h
index 42f42ffe..1b561f85 100644
--- a/lib/librte_security/rte_security_driver.h
+++ b/lib/librte_security/rte_security_driver.h
@@ -8,7 +8,6 @@
/**
* @file rte_security_driver.h
- * @b EXPERIMENTAL: this API may change without prior notice
*
* RTE Security Common Definitions
*
diff --git a/lib/librte_security/rte_security_version.map b/lib/librte_security/rte_security_version.map
index 5a1c8ae3..a77ca4bc 100644
--- a/lib/librte_security/rte_security_version.map
+++ b/lib/librte_security/rte_security_version.map
@@ -1,4 +1,4 @@
-EXPERIMENTAL {
+DPDK_18.11 {
global:
rte_security_attach_session;
diff --git a/meson.build b/meson.build
index a72237e1..1547e918 100644
--- a/meson.build
+++ b/meson.build
@@ -2,7 +2,7 @@
# Copyright(c) 2017 Intel Corporation
project('DPDK', 'C',
- version: '18.11.0-rc3',
+ version: '18.11.0-rc4',
license: 'BSD',
default_options: ['buildtype=release', 'default_library=static'],
meson_version: '>= 0.41'
diff --git a/test/test/test_eal_flags.c b/test/test/test_eal_flags.c
index 3a990766..2acab9d6 100644
--- a/test/test/test_eal_flags.c
+++ b/test/test/test_eal_flags.c
@@ -951,10 +951,15 @@ test_file_prefix(void)
* 2. try to run secondary process without a corresponding primary process
* (while failing to run, it will also remove any unused hugepage files)
* 3. check if current process hugefiles are still in place and are locked
- * 4. run a primary process with memtest1 prefix
- * 5. check if memtest1 hugefiles are created
- * 6. run a primary process with memtest2 prefix
- * 7. check that only memtest2 hugefiles are present in the hugedir
+ * 4. run a primary process with memtest1 prefix in default and legacy
+ * mem mode
+ * 5. check if memtest1 hugefiles are created in case of legacy mem
+ * mode, and deleted in case of default mem mode
+ * 6. run a primary process with memtest2 prefix in default and legacy
+ * mem modes
+ * 7. check that memtest2 hugefiles are present in the hugedir after a
+ * run in legacy mode, and not present at all after run in default
+ * mem mode
*/
char prefix[PATH_MAX] = "";
@@ -971,13 +976,23 @@ test_file_prefix(void)
const char *argv0[] = {prgname, mp_flag, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE,
"--file-prefix=" memtest };
- /* primary process with memtest1 */
- const char *argv1[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE,
- "--file-prefix=" memtest1 };
+ /* primary process with memtest1 and default mem mode */
+ const char *argv1[] = {prgname, "-c", "1", "-n", "2", "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest1 };
- /* primary process with memtest2 */
- const char *argv2[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE,
- "--file-prefix=" memtest2 };
+ /* primary process with memtest1 and legacy mem mode */
+ const char *argv2[] = {prgname, "-c", "1", "-n", "2", "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest1,
+ "--legacy-mem" };
+
+ /* primary process with memtest2 and legacy mem mode */
+ const char *argv3[] = {prgname, "-c", "1", "-n", "2", "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest2,
+ "--legacy-mem" };
+
+ /* primary process with memtest2 and default mem mode */
+ const char *argv4[] = {prgname, "-c", "1", "-n", "2", "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest2 };
/* check if files for current prefix are present */
if (process_hugefiles(prefix, HUGEPAGE_CHECK_EXISTS) != 1) {
@@ -1024,31 +1039,78 @@ test_file_prefix(void)
return -1;
}
+ /* we're running this process in default memory mode, which means it
+ * should clean up after itself on exit and leave no hugepages behind.
+ */
if (launch_proc(argv1) != 0) {
- printf("Error - failed to run with --file-prefix=%s\n", memtest);
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest1);
return -1;
}
/* check if memtest1_map0 is present */
- if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 1) {
- printf("Error - hugepage files for %s were not created!\n", memtest1);
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
return -1;
}
+ /* now, we're running a process under the same prefix, but with legacy
+ * mem mode - this should leave behind hugepage files.
+ */
if (launch_proc(argv2) != 0) {
- printf("Error - failed to run with --file-prefix=%s\n", memtest2);
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest1);
+ return -1;
+ }
+
+ /* check if memtest1_map0 is present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 1) {
+ printf("Error - hugepage files for %s were not created!\n",
+ memtest1);
+ return -1;
+ }
+
+ if (launch_proc(argv3) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest2);
return -1;
}
/* check if hugefiles for memtest2 are present */
if (process_hugefiles(memtest2, HUGEPAGE_CHECK_EXISTS) != 1) {
- printf("Error - hugepage files for %s were not created!\n", memtest2);
+ printf("Error - hugepage files for %s were not created!\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest1 are present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ /* this process will run in default mem mode, so it should not leave any
+ * hugepage files behind.
+ */
+ if (launch_proc(argv4) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest2 are present */
+ if (process_hugefiles(memtest2, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest2);
return -1;
}
/* check if hugefiles for memtest1 are present */
if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
- printf("Error - hugepage files for %s were not deleted!\n", memtest1);
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
return -1;
}
diff --git a/test/test/test_interrupts.c b/test/test/test_interrupts.c
index dc19175d..4e82e9a2 100644
--- a/test/test/test_interrupts.c
+++ b/test/test/test_interrupts.c
@@ -424,7 +424,7 @@ test_interrupt(void)
printf("Check valid alarm interrupt full path\n");
if (test_interrupt_full_path_check(
- TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) {
+ TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) {
printf("failure occurred during checking valid alarm "
"interrupt full path\n");
goto out;
diff --git a/test/test/test_pmd_ring_perf.c b/test/test/test_pmd_ring_perf.c
index ad5004a6..6318da18 100644
--- a/test/test/test_pmd_ring_perf.c
+++ b/test/test/test_pmd_ring_perf.c
@@ -10,6 +10,7 @@
#include <rte_launch.h>
#include <rte_ethdev.h>
#include <rte_eth_ring.h>
+#include <rte_bus_vdev.h>
#include "test.h"
@@ -135,6 +136,8 @@ test_bulk_enqueue_dequeue(void)
static int
test_ring_pmd_perf(void)
{
+ char name[RTE_ETH_NAME_MAX_LEN];
+
r = rte_ring_create(RING_NAME, RING_SIZE, rte_socket_id(),
RING_F_SP_ENQ|RING_F_SC_DEQ);
if (r == NULL && (r = rte_ring_lookup(RING_NAME)) == NULL)
@@ -151,6 +154,11 @@ test_ring_pmd_perf(void)
printf("\n### Testing using a single lcore ###\n");
test_bulk_enqueue_dequeue();
+ /* release port and ring resources */
+ rte_eth_dev_stop(ring_ethdev_port);
+ rte_eth_dev_get_name_by_port(ring_ethdev_port, name);
+ rte_vdev_uninit(name);
+ rte_ring_free(r);
return 0;
}
diff --git a/test/test/test_power_kvm_vm.c b/test/test/test_power_kvm_vm.c
index bce706de..785cd048 100644
--- a/test/test/test_power_kvm_vm.c
+++ b/test/test/test_power_kvm_vm.c
@@ -101,7 +101,7 @@ test_power_kvm_vm(void)
"Power management environment\n",
TEST_POWER_VM_LCORE_ID);
rte_power_unset_env();
- return -1;
+ return TEST_SKIPPED;
}
/* Test initialisation of previously initialised lcore */
diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py
index 7d564634..40dc28a7 100755
--- a/usertools/dpdk-devbind.py
+++ b/usertools/dpdk-devbind.py
@@ -655,6 +655,13 @@ def do_arg_actions():
def main():
'''program main function'''
+ # check if lspci is installed, suppress any output
+ with open(os.devnull, 'w') as devnull:
+ ret = subprocess.call(['which', 'lspci'],
+ stdout=devnull, stderr=devnull)
+ if ret != 0:
+ print("'lspci' not found - please install 'pciutils'")
+ sys.exit(1)
parse_args()
check_modules()
clear_data()