diff options
-rw-r--r-- | Documentation/automake.mk | 1 | ||||
-rw-r--r-- | Documentation/topics/dpdk/index.rst | 1 | ||||
-rw-r--r-- | Documentation/topics/dpdk/ring.rst | 92 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | lib/netdev-dpdk.c | 189 | ||||
-rw-r--r-- | rhel/README.RHEL.rst | 3 | ||||
-rwxr-xr-x | rhel/etc_sysconfig_network-scripts_ifdown-ovs | 2 | ||||
-rwxr-xr-x | rhel/etc_sysconfig_network-scripts_ifup-ovs | 7 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/automake.mk | 7 | ||||
-rw-r--r-- | tests/dpdk/ring_client.c | 200 |
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 @@ -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); - } - } -} |