summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/automake.mk1
-rw-r--r--Documentation/topics/dpdk/index.rst1
-rw-r--r--Documentation/topics/dpdk/ring.rst92
-rw-r--r--NEWS1
-rw-r--r--lib/netdev-dpdk.c189
-rw-r--r--rhel/README.RHEL.rst3
-rwxr-xr-xrhel/etc_sysconfig_network-scripts_ifdown-ovs2
-rwxr-xr-xrhel/etc_sysconfig_network-scripts_ifup-ovs7
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/automake.mk7
-rw-r--r--tests/dpdk/ring_client.c200
11 files changed, 2 insertions, 502 deletions
diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 691f345ec..f85c4320e 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -39,7 +39,6 @@ DOC_SOURCE = \
Documentation/topics/dpdk/phy.rst \
Documentation/topics/dpdk/pmd.rst \
Documentation/topics/dpdk/qos.rst \
- Documentation/topics/dpdk/ring.rst \
Documentation/topics/dpdk/vdev.rst \
Documentation/topics/dpdk/vhost-user.rst \
Documentation/topics/fuzzing/index.rst \
diff --git a/Documentation/topics/dpdk/index.rst b/Documentation/topics/dpdk/index.rst
index 336dcc56b..a5be5e344 100644
--- a/Documentation/topics/dpdk/index.rst
+++ b/Documentation/topics/dpdk/index.rst
@@ -34,7 +34,6 @@ DPDK Support
/topics/dpdk/bridge
/topics/dpdk/phy
/topics/dpdk/vhost-user
- /topics/dpdk/ring
/topics/dpdk/vdev
/topics/dpdk/pmd
/topics/dpdk/qos
diff --git a/Documentation/topics/dpdk/ring.rst b/Documentation/topics/dpdk/ring.rst
deleted file mode 100644
index 9d91498c7..000000000
--- a/Documentation/topics/dpdk/ring.rst
+++ /dev/null
@@ -1,92 +0,0 @@
-..
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- Convention for heading levels in Open vSwitch documentation:
-
- ======= Heading 0 (reserved for the title in a document)
- ------- Heading 1
- ~~~~~~~ Heading 2
- +++++++ Heading 3
- ''''''' Heading 4
-
- Avoid deeper levels because they do not render well.
-
-===============
-DPDK Ring Ports
-===============
-
-.. warning::
-
- DPDK ring ports are considered *deprecated*. Please migrate to
- virtio-based interfaces, e.g. :doc:`vhost-user <vhost-user>` ports,
- ``net_virtio_user`` :doc:`DPDK vdev <vdev>`.
-
-.. warning::
-
- DPDK ring interfaces cannot be used for guest communication and are retained
- mainly for backwards compatibility purposes. In nearly all cases,
- :doc:`vhost-user ports <vhost-user>` are a better choice and should be used
- instead.
-
-OVS userspace switching supports ring ports implemented using DPDK's
-``librte_ring`` library. For more information on this library, refer
-to the `DPDK documentation`_.
-
-.. important::
-
- To use any DPDK-backed interface, you must ensure your bridge is configured
- correctly. For more information, refer to :doc:`bridge`.
-
-Quick Example
--------------
-
-This example demonstrates how to add a ``dpdkr`` port to an existing bridge
-called ``br0``::
-
- $ ovs-vsctl add-port br0 dpdkr0 -- set Interface dpdkr0 type=dpdkr
-
-dpdkr
------
-
-To use ring ports, you must first add said ports to the switch. Unlike
-:doc:`vhost-user ports <vhost-user>`, ring port names must take a specific
-format, ``dpdkrNN``, where ``NN`` is the port ID. For example::
-
- $ ovs-vsctl add-port br0 dpdkr0 -- set Interface dpdkr0 type=dpdkr
-
-Once the port has been added to the switch, they can be used by host processes.
-A sample loopback application - ``test-dpdkr`` - is included with Open vSwitch.
-To use this, run the following::
-
- $ ./tests/test-dpdkr -c 1 -n 4 --proc-type=secondary -- -n 0
-
-Further functionality would require developing your own application. Refer to
-the `DPDK documentation`_ for more information on how to do this.
-
-Adding dpdkr ports to the guest
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is **not** recommended to use ring ports from guests. Historically, this was
-possible using a patched version of QEMU and the IVSHMEM feature provided with
-DPDK. However, this functionality was removed because:
-
-- The IVSHMEM library was removed from DPDK in DPDK 16.11
-
-- Support for IVSHMEM was never upstreamed to QEMU and has been publicly
- rejected by the QEMU community
-
-- :doc:`vhost-user interfaces <vhost-user>` are the de facto DPDK-based path to
- guests
-
-.. _DPDK documentation:
- https://doc.dpdk.org/guides-19.11/prog_guide/ring_lib.html
diff --git a/NEWS b/NEWS
index c58a9014e..8710a0233 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Post-v2.13.0
value of other-config:dp-sn in the Bridge table.
- DPDK:
* Deprecated DPDK pdump packet capture support removed.
+ * Deprecated DPDK ring ports (dpdkr) are no longer supported.
v2.13.0 - 14 Feb 2020
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 7ab81864d..44ebf96da 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -36,7 +36,6 @@
#include <rte_config.h>
#include <rte_cycles.h>
#include <rte_errno.h>
-#include <rte_eth_ring.h>
#include <rte_ethdev.h>
#include <rte_flow.h>
#include <rte_malloc.h>
@@ -216,10 +215,6 @@ struct netdev_dpdk_sw_stats {
uint64_t tx_invalid_hwol_drops;
};
-enum { DPDK_RING_SIZE = 256 };
-BUILD_ASSERT_DECL(IS_POW2(DPDK_RING_SIZE));
-enum { DRAIN_TSC = 200000ULL };
-
enum dpdk_dev_type {
DPDK_DEV_ETH = 0,
DPDK_DEV_VHOST = 1,
@@ -397,22 +392,6 @@ struct dpdk_tx_queue {
);
};
-/* dpdk has no way to remove dpdk ring ethernet devices
- so we have to keep them around once they've been created
-*/
-
-static struct ovs_list dpdk_ring_list OVS_GUARDED_BY(dpdk_mutex)
- = OVS_LIST_INITIALIZER(&dpdk_ring_list);
-
-struct dpdk_ring {
- /* For the client rings */
- struct rte_ring *cring_tx;
- struct rte_ring *cring_rx;
- unsigned int user_port_id; /* User given port no, parsed from port name */
- dpdk_port_t eth_port_id; /* ethernet device port id */
- struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);
-};
-
struct ingress_policer {
struct rte_meter_srtcm_params app_srtcm_params;
struct rte_meter_srtcm in_policer;
@@ -1299,27 +1278,6 @@ common_construct(struct netdev *netdev, dpdk_port_t port_no,
return 0;
}
-/* dev_name must be the prefix followed by a positive decimal number.
- * (no leading + or - signs are allowed) */
-static int
-dpdk_dev_parse_name(const char dev_name[], const char prefix[],
- unsigned int *port_no)
-{
- const char *cport;
-
- if (strncmp(dev_name, prefix, strlen(prefix))) {
- return ENODEV;
- }
-
- cport = dev_name + strlen(prefix);
-
- if (str_to_uint(cport, 10, port_no)) {
- return 0;
- } else {
- return ENODEV;
- }
-}
-
/* Get the number of OVS interfaces which have the same DPDK
* rte device (e.g. same pci bus address).
* FIXME: avoid direct access to DPDK internal array rte_eth_devices.
@@ -2060,19 +2018,6 @@ out:
}
static int
-netdev_dpdk_ring_set_config(struct netdev *netdev, const struct smap *args,
- char **errp OVS_UNUSED)
-{
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
-
- ovs_mutex_lock(&dev->mutex);
- dpdk_set_rxq_config(dev, args);
- ovs_mutex_unlock(&dev->mutex);
-
- return 0;
-}
-
-static int
netdev_dpdk_vhost_client_set_config(struct netdev *netdev,
const struct smap *args,
char **errp OVS_UNUSED)
@@ -4257,131 +4202,6 @@ netdev_dpdk_class_init(void)
return 0;
}
-/* Client Rings */
-
-static int
-dpdk_ring_create(const char dev_name[], unsigned int port_no,
- dpdk_port_t *eth_port_id)
-{
- struct dpdk_ring *ring_pair;
- char *ring_name;
- int port_id;
-
- ring_pair = dpdk_rte_mzalloc(sizeof *ring_pair);
- if (!ring_pair) {
- return ENOMEM;
- }
-
- /* XXX: Add support for multiquque ring. */
- ring_name = xasprintf("%s_tx", dev_name);
-
- /* Create single producer tx ring, netdev does explicit locking. */
- ring_pair->cring_tx = rte_ring_create(ring_name, DPDK_RING_SIZE, SOCKET0,
- RING_F_SP_ENQ);
- free(ring_name);
- if (ring_pair->cring_tx == NULL) {
- rte_free(ring_pair);
- return ENOMEM;
- }
-
- ring_name = xasprintf("%s_rx", dev_name);
-
- /* Create single consumer rx ring, netdev does explicit locking. */
- ring_pair->cring_rx = rte_ring_create(ring_name, DPDK_RING_SIZE, SOCKET0,
- RING_F_SC_DEQ);
- free(ring_name);
- if (ring_pair->cring_rx == NULL) {
- rte_free(ring_pair);
- return ENOMEM;
- }
-
- port_id = rte_eth_from_rings(dev_name, &ring_pair->cring_rx, 1,
- &ring_pair->cring_tx, 1, SOCKET0);
-
- if (port_id < 0) {
- rte_free(ring_pair);
- return ENODEV;
- }
-
- ring_pair->user_port_id = port_no;
- ring_pair->eth_port_id = port_id;
- *eth_port_id = port_id;
-
- ovs_list_push_back(&dpdk_ring_list, &ring_pair->list_node);
-
- return 0;
-}
-
-static int
-dpdk_ring_open(const char dev_name[], dpdk_port_t *eth_port_id)
- OVS_REQUIRES(dpdk_mutex)
-{
- struct dpdk_ring *ring_pair;
- unsigned int port_no;
- int err = 0;
-
- /* Names always start with "dpdkr" */
- err = dpdk_dev_parse_name(dev_name, "dpdkr", &port_no);
- if (err) {
- return err;
- }
-
- /* Look through our list to find the device */
- LIST_FOR_EACH (ring_pair, list_node, &dpdk_ring_list) {
- if (ring_pair->user_port_id == port_no) {
- VLOG_INFO("Found dpdk ring device %s:", dev_name);
- /* Really all that is needed */
- *eth_port_id = ring_pair->eth_port_id;
- return 0;
- }
- }
- /* Need to create the device rings */
- return dpdk_ring_create(dev_name, port_no, eth_port_id);
-}
-
-static int
-netdev_dpdk_ring_send(struct netdev *netdev, int qid,
- struct dp_packet_batch *batch, bool concurrent_txq)
-{
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
- struct dp_packet *packet;
-
- /* When using 'dpdkr' and sending to a DPDK ring, we want to ensure that
- * the offload fields are clear. This is because the same mbuf may be
- * modified by the consumer of the ring and return into the datapath
- * without recalculating the RSS hash or revalidating the checksums. */
- DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
- dp_packet_reset_offload(packet);
- }
-
- netdev_dpdk_send__(dev, qid, batch, concurrent_txq);
- return 0;
-}
-
-static int
-netdev_dpdk_ring_construct(struct netdev *netdev)
-{
- dpdk_port_t port_no = 0;
- int err = 0;
-
- VLOG_WARN_ONCE("dpdkr a.k.a. ring ports are considered deprecated. "
- "Please migrate to virtio-based interfaces, e.g. "
- "dpdkvhostuserclient ports, net_virtio_user DPDK vdev.");
-
- ovs_mutex_lock(&dpdk_mutex);
-
- err = dpdk_ring_open(netdev->name, &port_no);
- if (err) {
- goto unlock_dpdk;
- }
-
- err = common_construct(netdev, port_no, DPDK_DEV_ETH,
- rte_eth_dev_socket_id(port_no));
-unlock_dpdk:
- ovs_mutex_unlock(&dpdk_mutex);
- return err;
-}
-
/* QoS Functions */
/*
@@ -5459,14 +5279,6 @@ static const struct netdev_class dpdk_class = {
.send = netdev_dpdk_eth_send,
};
-static const struct netdev_class dpdk_ring_class = {
- .type = "dpdkr",
- NETDEV_DPDK_CLASS_BASE,
- .construct = netdev_dpdk_ring_construct,
- .set_config = netdev_dpdk_ring_set_config,
- .send = netdev_dpdk_ring_send,
-};
-
static const struct netdev_class dpdk_vhost_class = {
.type = "dpdkvhostuser",
NETDEV_DPDK_CLASS_COMMON,
@@ -5502,7 +5314,6 @@ void
netdev_dpdk_register(void)
{
netdev_register_provider(&dpdk_class);
- netdev_register_provider(&dpdk_ring_class);
netdev_register_provider(&dpdk_vhost_class);
netdev_register_provider(&dpdk_vhost_client_class);
}
diff --git a/rhel/README.RHEL.rst b/rhel/README.RHEL.rst
index 1cd2065ef..98175dfd3 100644
--- a/rhel/README.RHEL.rst
+++ b/rhel/README.RHEL.rst
@@ -36,9 +36,6 @@ TYPE
* ``OVSDPDKPort``, if ``<name>`` is a physical DPDK NIC port (name must start
with ``dpdk`` and end with portid, eg ``dpdk0``)
- * ``OVSDPDKRPort``, if ``<name>`` is a DPDK ring port (name must start with
- ``dpdkr`` and end with portid, e.g. ``dpdkr0``)
-
* ``OVSDPDKVhostUserPort`` if ``<name>`` is a DPDK vhost-user port
* ``OVSDPDKBond`` if ``<name>`` is an OVS DPDK bond.
diff --git a/rhel/etc_sysconfig_network-scripts_ifdown-ovs b/rhel/etc_sysconfig_network-scripts_ifdown-ovs
index 63d048b22..343ac0945 100755
--- a/rhel/etc_sysconfig_network-scripts_ifdown-ovs
+++ b/rhel/etc_sysconfig_network-scripts_ifdown-ovs
@@ -59,7 +59,7 @@ case "$TYPE" in
OVSPatchPort|OVSTunnel)
ovs-vsctl -t ${TIMEOUT} -- --if-exists del-port "$OVS_BRIDGE" "$DEVICE"
;;
- OVSDPDKPort|OVSDPDKRPort|OVSDPDKVhostUserPort|OVSDPDKBond)
+ OVSDPDKPort|OVSDPDKVhostUserPort|OVSDPDKBond)
ovs-vsctl -t ${TIMEOUT} -- --if-exists del-port "$OVS_BRIDGE" "$DEVICE"
;;
*)
diff --git a/rhel/etc_sysconfig_network-scripts_ifup-ovs b/rhel/etc_sysconfig_network-scripts_ifup-ovs
index b01461cc4..0955c0e1f 100755
--- a/rhel/etc_sysconfig_network-scripts_ifup-ovs
+++ b/rhel/etc_sysconfig_network-scripts_ifup-ovs
@@ -180,13 +180,6 @@ case "$TYPE" in
${OTHERSCRIPT} "$OVS_BRIDGE"
fi
;;
- OVSDPDKRPort)
- ifup_ovs_bridge
- ovs-vsctl -t ${TIMEOUT} \
- -- --if-exists del-port "$OVS_BRIDGE" "$DEVICE" \
- -- add-port "$OVS_BRIDGE" "$DEVICE" $OVS_OPTIONS \
- -- set Interface "$DEVICE" type=dpdkr ${OVS_EXTRA+-- $OVS_EXTRA}
- ;;
OVSDPDKVhostUserPort)
ifup_ovs_bridge
PORT_TYPE="dpdkvhostuser"
diff --git a/tests/.gitignore b/tests/.gitignore
index c5abb32d0..99fdf70d5 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -7,7 +7,6 @@
/idltest.h
/idltest.ovsidl
/ovstest
-/test-dpdkr
/ovs-pki.log
/ovsdb-cluster-testsuite
/ovsdb-cluster-testsuite.dir/
diff --git a/tests/automake.mk b/tests/automake.mk
index 9c7ebdce9..81eb2a9b8 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -414,13 +414,6 @@ tests/idltest.ovsidl: $(IDLTEST_IDL_FILES)
tests/idltest.c: tests/idltest.h
-if DPDK_NETDEV
-noinst_PROGRAMS += tests/test-dpdkr
-tests_test_dpdkr_SOURCES = \
- tests/dpdk/ring_client.c
-tests_test_dpdkr_LDADD = lib/libopenvswitch.la $(LIBS)
-endif
-
noinst_PROGRAMS += tests/ovstest
tests_ovstest_SOURCES = \
tests/ovstest.c \
diff --git a/tests/dpdk/ring_client.c b/tests/dpdk/ring_client.c
deleted file mode 100644
index 8cc3fb533..000000000
--- a/tests/dpdk/ring_client.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * BSD LICENSE
- *
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <getopt.h>
-
-#include <config.h>
-#include <rte_config.h>
-#include <rte_mbuf.h>
-#include <rte_ether.h>
-#include <rte_string_fns.h>
-#include <rte_ip.h>
-#include <rte_byteorder.h>
-
-#include "util.h"
-
-/* Number of packets to attempt to read from queue. */
-#define PKT_READ_SIZE ((uint16_t)32)
-
-/* Define common names for structures shared between ovs_dpdk and client. */
-#define MP_CLIENT_RXQ_NAME "dpdkr%u_tx"
-#define MP_CLIENT_TXQ_NAME "dpdkr%u_rx"
-
-#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
-
-/* Our client id number - tells us which rx queue to read, and tx
- * queue to write to.
- */
-static unsigned int client_id;
-
-/*
- * Given the rx queue name template above, get the queue name.
- */
-static inline const char *
-get_rx_queue_name(unsigned int id)
-{
- /* Buffer for return value. */
- static char buffer[RTE_RING_NAMESIZE];
-
- snprintf(buffer, sizeof(buffer), MP_CLIENT_RXQ_NAME, id);
- return buffer;
-}
-
-/*
- * Given the tx queue name template above, get the queue name.
- */
-static inline const char *
-get_tx_queue_name(unsigned int id)
-{
- /* Buffer for return value. */
- static char buffer[RTE_RING_NAMESIZE];
-
- snprintf(buffer, sizeof(buffer), MP_CLIENT_TXQ_NAME, id);
- return buffer;
-}
-
-/*
- * Print a usage message.
- */
-static void
-usage(const char *progname)
-{
- printf("\nUsage: %s [EAL args] -- -n <client_id>\n", progname);
-}
-
-/*
- * Convert the client id number from a string to an usigned int.
- */
-static int
-parse_client_num(const char *client)
-{
- if (str_to_uint(client, 10, &client_id)) {
- return 0;
- } else {
- return -1;
- }
-}
-
-/*
- * Parse the application arguments to the client app.
- */
-static int
-parse_app_args(int argc, char *argv[])
-{
- int option_index = 0, opt = 0;
- char **argvopt = argv;
- const char *progname = NULL;
- static struct option lgopts[] = {
- {NULL, 0, NULL, 0 }
- };
- progname = argv[0];
-
- while ((opt = getopt_long(argc, argvopt, "n:", lgopts,
- &option_index)) != EOF) {
- switch (opt) {
- case 'n':
- if (parse_client_num(optarg) != 0) {
- usage(progname);
- return -1;
- }
- break;
- default:
- usage(progname);
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- * Application main function - loops through
- * receiving and processing packets. Never returns
- */
-int
-main(int argc, char *argv[])
-{
- struct rte_ring *rx_ring = NULL;
- struct rte_ring *tx_ring = NULL;
- int retval = 0;
- void *pkts[PKT_READ_SIZE];
- int rslt = 0;
-
- if ((retval = rte_eal_init(argc, argv)) < 0) {
- return -1;
- }
-
- argc -= retval;
- argv += retval;
-
- if (parse_app_args(argc, argv) < 0) {
- rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
- }
-
- rx_ring = rte_ring_lookup(get_rx_queue_name(client_id));
- if (rx_ring == NULL) {
- rte_exit(EXIT_FAILURE,
- "Cannot get RX ring - is server process running?\n");
- }
-
- tx_ring = rte_ring_lookup(get_tx_queue_name(client_id));
- if (tx_ring == NULL) {
- rte_exit(EXIT_FAILURE,
- "Cannot get TX ring - is server process running?\n");
- }
-
- RTE_LOG(INFO, APP, "Finished Process Init.\n");
-
- printf("\nClient process %u handling packets\n", client_id);
- printf("[Press Ctrl-C to quit ...]\n");
-
- for (;;) {
- unsigned rx_pkts = PKT_READ_SIZE;
-
- /* Try dequeuing max possible packets first, if that fails, get the
- * most we can. Loop body should only execute once, maximum.
- */
- while (unlikely(rte_ring_dequeue_bulk(rx_ring, pkts,
- rx_pkts, NULL) != 0) && rx_pkts > 0) {
- rx_pkts = (uint16_t)RTE_MIN(rte_ring_count(rx_ring), PKT_READ_SIZE);
- }
-
- if (rx_pkts > 0) {
- /* blocking enqueue */
- do {
- rslt = rte_ring_enqueue_bulk(tx_ring, pkts, rx_pkts, NULL);
- } while (rslt == -ENOBUFS);
- }
- }
-}