From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id AD8BDA04B1; Tue, 8 Sep 2020 22:24:11 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1866F1C219; Tue, 8 Sep 2020 22:19:42 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 816761C11E for ; Tue, 8 Sep 2020 22:19:05 +0200 (CEST) IronPort-SDR: rvPFurKqX+KqNPelAcceVC7s61sINO5egnT0xUMuHPv4JPTATKlNQYVeTSk/4bPOadGbHk9nr8 OLdTLd59oM+w== X-IronPort-AV: E=McAfee;i="6000,8403,9738"; a="145939449" X-IronPort-AV: E=Sophos;i="5.76,407,1592895600"; d="scan'208";a="145939449" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Sep 2020 13:19:05 -0700 IronPort-SDR: QRPYJ2TC6h5pkkTCZZ6wwZVaQ2Dcx5MKSO0Qni2k85ur7U+jxF3f5+H5DzsAVq+jL5IPpdP/t9 SePdpNi7lrlA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,406,1592895600"; d="scan'208";a="504493539" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by fmsmga006.fm.intel.com with ESMTP; 08 Sep 2020 13:19:04 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Date: Tue, 8 Sep 2020 21:18:22 +0100 Message-Id: <20200908201830.74206-34-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200908201830.74206-1-cristian.dumitrescu@intel.com> References: <20200907214032.95052-2-cristian.dumitrescu@intel.com> <20200908201830.74206-1-cristian.dumitrescu@intel.com> Subject: [dpdk-dev] [PATCH v3 33/41] port: add ethernet device SWX port X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add the Ethernet device input/output port type for the SWX pipeline. Used under the hood by the pipeline rx and tx instructions. Signed-off-by: Cristian Dumitrescu --- lib/librte_port/meson.build | 6 +- lib/librte_port/rte_port_version.map | 3 +- lib/librte_port/rte_swx_port_ethdev.c | 313 ++++++++++++++++++++++++++ lib/librte_port/rte_swx_port_ethdev.h | 54 +++++ 4 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 lib/librte_port/rte_swx_port_ethdev.c create mode 100644 lib/librte_port/rte_swx_port_ethdev.h diff --git a/lib/librte_port/meson.build b/lib/librte_port/meson.build index 5b5fbf6c4..3d7f309bb 100644 --- a/lib/librte_port/meson.build +++ b/lib/librte_port/meson.build @@ -10,7 +10,8 @@ sources = files( 'rte_port_sched.c', 'rte_port_source_sink.c', 'rte_port_sym_crypto.c', - 'rte_port_eventdev.c') + 'rte_port_eventdev.c', + 'rte_swx_port_ethdev.c',) headers = files( 'rte_port_ethdev.h', 'rte_port_fd.h', @@ -22,7 +23,8 @@ headers = files( 'rte_port_source_sink.h', 'rte_port_sym_crypto.h', 'rte_port_eventdev.h', - 'rte_swx_port.h',) + 'rte_swx_port.h', + 'rte_swx_port_ethdev.h',) deps += ['ethdev', 'sched', 'ip_frag', 'cryptodev', 'eventdev'] if dpdk_conf.has('RTE_PORT_PCAP') diff --git a/lib/librte_port/rte_port_version.map b/lib/librte_port/rte_port_version.map index bd1fbb66b..6da5c8074 100644 --- a/lib/librte_port/rte_port_version.map +++ b/lib/librte_port/rte_port_version.map @@ -37,5 +37,6 @@ EXPERIMENTAL { rte_port_eventdev_reader_ops; rte_port_eventdev_writer_ops; rte_port_eventdev_writer_nodrop_ops; - + rte_swx_port_ethdev_reader_ops; + rte_swx_port_ethdev_writer_ops; }; diff --git a/lib/librte_port/rte_swx_port_ethdev.c b/lib/librte_port/rte_swx_port_ethdev.c new file mode 100644 index 000000000..18d1c0b5d --- /dev/null +++ b/lib/librte_port/rte_swx_port_ethdev.c @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ +#include +#include +#include +#include + +#include +#include +#include + +#include "rte_swx_port_ethdev.h" + +#define CHECK(condition) \ +do { \ + if (!(condition)) \ + return NULL; \ +} while (0) + +#ifndef TRACE_LEVEL +#define TRACE_LEVEL 0 +#endif + +#if TRACE_LEVEL +#define TRACE(...) printf(__VA_ARGS__) +#else +#define TRACE(...) +#endif + +/* + * Port ETHDEV Reader + */ +struct reader { + struct { + uint16_t port_id; + uint16_t queue_id; + uint32_t burst_size; + } params; + struct rte_swx_port_in_stats stats; + struct rte_mbuf **pkts; + int n_pkts; + int pos; +}; + +static void * +reader_create(void *args) +{ + struct rte_eth_dev_info info; + struct rte_swx_port_ethdev_reader_params *params = args; + struct reader *p; + int status; + uint16_t port_id; + + /* Check input parameters. */ + CHECK(params); + + CHECK(params->dev_name); + status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id); + CHECK(!status); + + status = rte_eth_dev_info_get(port_id, &info); + CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_rx_queues)); + + CHECK(params->burst_size); + + /* Memory allocation. */ + p = calloc(1, sizeof(struct reader)); + CHECK(p); + + p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *)); + if (!p->pkts) { + free(p); + CHECK(0); + } + + /* Initialization. */ + p->params.port_id = port_id; + p->params.queue_id = params->queue_id; + p->params.burst_size = params->burst_size; + + return p; +} + +static int +reader_pkt_rx(void *port, struct rte_swx_pkt *pkt) +{ + struct reader *p = port; + struct rte_mbuf *m; + + if (p->pos == p->n_pkts) { + int n_pkts; + + n_pkts = rte_eth_rx_burst(p->params.port_id, + p->params.queue_id, + p->pkts, + p->params.burst_size); + if (!n_pkts) { + p->stats.n_empty++; + return 0; + } + + TRACE("[Ethdev RX port %u queue %u] %d packets in\n", + (uint32_t)p->params.port_id, + (uint32_t)p->params.queue_id, + n_pkts); + + p->n_pkts = n_pkts; + p->pos = 0; + } + + m = p->pkts[p->pos++]; + pkt->handle = m; + pkt->pkt = m->buf_addr; + pkt->offset = m->data_off; + pkt->length = m->pkt_len; + + TRACE("[Ethdev RX port %u queue %u] Pkt %d (%u bytes at offset %u)\n", + (uint32_t)p->params.port_id, + (uint32_t)p->params.queue_id, + p->pos - 1, + pkt->length, + pkt->offset); + if (TRACE_LEVEL) + rte_hexdump(stdout, + NULL, + &((uint8_t *)m->buf_addr)[m->data_off], + m->data_len); + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + + return 1; +} + +static void +reader_free(void *port) +{ + struct reader *p = port; + int i; + + if (!p) + return; + + for (i = 0; i < p->n_pkts; i++) { + struct rte_mbuf *pkt = p->pkts[i]; + + rte_pktmbuf_free(pkt); + } + + free(p->pkts); + free(p); +} + +static void +reader_stats_read(void *port, struct rte_swx_port_in_stats *stats) +{ + struct reader *p = port; + + memcpy(stats, &p->stats, sizeof(p->stats)); +} + +/* + * Port ETHDEV Writer + */ +struct writer { + struct { + uint16_t port_id; + uint16_t queue_id; + uint32_t burst_size; + } params; + struct rte_swx_port_out_stats stats; + + struct rte_mbuf **pkts; + int n_pkts; +}; + +static void * +writer_create(void *args) +{ + struct rte_eth_dev_info info; + struct rte_swx_port_ethdev_writer_params *params = args; + struct writer *p; + int status; + uint16_t port_id; + + /* Check input parameters. */ + CHECK(params); + + CHECK(params->dev_name); + status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id); + CHECK(!status); + + status = rte_eth_dev_info_get(port_id, &info); + CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_tx_queues)); + + CHECK(params->burst_size); + + /* Memory allocation. */ + p = calloc(1, sizeof(struct writer)); + CHECK(p); + + p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *)); + if (!p->pkts) { + free(p); + CHECK(0); + } + + /* Initialization. */ + p->params.port_id = port_id; + p->params.queue_id = params->queue_id; + p->params.burst_size = params->burst_size; + + return p; +} + +static void +__writer_flush(struct writer *p) +{ + int n_pkts; + + for (n_pkts = 0; ; ) { + n_pkts += rte_eth_tx_burst(p->params.port_id, + p->params.queue_id, + p->pkts + n_pkts, + p->n_pkts - n_pkts); + + TRACE("[Ethdev TX port %u queue %u] %d packets out\n", + (uint32_t)p->params.port_id, + (uint32_t)p->params.queue_id, + n_pkts); + + if (n_pkts == p->n_pkts) + break; + } + + p->n_pkts = 0; +} + +static void +writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle; + + TRACE("[Ethdev TX port %u queue %u] Pkt %d (%u bytes at offset %u)\n", + (uint32_t)p->params.port_id, + (uint32_t)p->params.queue_id, + p->n_pkts - 1, + pkt->length, + pkt->offset); + if (TRACE_LEVEL) + rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + + m->pkt_len = pkt->length; + m->data_len = (uint16_t)pkt->length; + m->data_off = (uint16_t)pkt->offset; + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + + p->pkts[p->n_pkts++] = m; + if (p->n_pkts == (int)p->params.burst_size) + __writer_flush(p); +} + +static void +writer_flush(void *port) +{ + struct writer *p = port; + + if (p->n_pkts) + __writer_flush(p); +} + +static void +writer_free(void *port) +{ + struct writer *p = port; + + if (!p) + return; + + writer_flush(p); + free(p->pkts); + free(port); +} + +static void +writer_stats_read(void *port, struct rte_swx_port_out_stats *stats) +{ + struct writer *p = port; + + memcpy(stats, &p->stats, sizeof(p->stats)); +} + +/* + * Summary of port operations + */ +struct rte_swx_port_in_ops rte_swx_port_ethdev_reader_ops = { + .create = reader_create, + .free = reader_free, + .pkt_rx = reader_pkt_rx, + .stats_read = reader_stats_read, +}; + +struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops = { + .create = writer_create, + .free = writer_free, + .pkt_tx = writer_pkt_tx, + .flush = writer_flush, + .stats_read = writer_stats_read, +}; diff --git a/lib/librte_port/rte_swx_port_ethdev.h b/lib/librte_port/rte_swx_port_ethdev.h new file mode 100644 index 000000000..cbc2d7b21 --- /dev/null +++ b/lib/librte_port/rte_swx_port_ethdev.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ +#ifndef __INCLUDE_RTE_SWX_PORT_ETHDEV_H__ +#define __INCLUDE_RTE_SWX_PORT_ETHDEV_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * RTE SWX Ethernet Device Input and Output Ports + */ + +#include + +#include "rte_swx_port.h" + +/** Ethernet device input port (reader) creation parameters. */ +struct rte_swx_port_ethdev_reader_params { + /** Name of a valid and fully configured Ethernet device. */ + const char *dev_name; + + /** Ethernet device receive queue ID. */ + uint16_t queue_id; + + /** Ethernet device receive burst size. */ + uint32_t burst_size; +}; + +/** Ethernet device reader operations. */ +extern struct rte_swx_port_in_ops rte_swx_port_ethdev_reader_ops; + +/** Ethernet device output port (writer) creation parameters. */ +struct rte_swx_port_ethdev_writer_params { + /** Name of a valid and fully configured Ethernet device. */ + const char *dev_name; + + /** Ethernet device transmit queue ID. */ + uint16_t queue_id; + + /** Ethernet device transmit burst size. */ + uint32_t burst_size; +}; + +/** Ethernet device writer operations. */ +extern struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops; + +#ifdef __cplusplus +} +#endif + +#endif -- 2.17.1