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 93754A04AA; Mon, 7 Sep 2020 23:46:10 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D90B21C2DB; Mon, 7 Sep 2020 23:41:24 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 7891A1C1EB for ; Mon, 7 Sep 2020 23:41:07 +0200 (CEST) IronPort-SDR: Ub534FnaTyQPcmie1X2vM5U8AiJXCJDuBQsihpct33M0HPbiqKnW0pXUu4uODmNyLWsKDZFRd8 Oc9XGIE81oqg== X-IronPort-AV: E=McAfee;i="6000,8403,9737"; a="176099191" X-IronPort-AV: E=Sophos;i="5.76,403,1592895600"; d="scan'208";a="176099191" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Sep 2020 14:41:07 -0700 IronPort-SDR: 8C6hgB/euTEOfB+bX9DcH0pJEDS0ivCNxIpWQOSX09CBNvMY+5oBYc7bza0DfgH1yQj5jcsalr qNZcpLHvbbAg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,403,1592895600"; d="scan'208";a="336190225" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by fmsmga002.fm.intel.com with ESMTP; 07 Sep 2020 14:41:06 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Date: Mon, 7 Sep 2020 22:40:25 +0100 Message-Id: <20200907214032.95052-35-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200907214032.95052-1-cristian.dumitrescu@intel.com> References: <20200826151445.51500-2-cristian.dumitrescu@intel.com> <20200907214032.95052-1-cristian.dumitrescu@intel.com> Subject: [dpdk-dev] [PATCH v2 34/41] port: add source and sink SWX ports 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 PCAP file-based source (input) and sink (output) port types for the SWX pipeline. The sink port is typically used to implement the packet drop pipeline action. Used under the hood by the pipeline rx and tx instructions. Signed-off-by: Cristian Dumitrescu --- lib/librte_port/Makefile | 2 + lib/librte_port/meson.build | 6 +- lib/librte_port/rte_port_version.map | 2 + lib/librte_port/rte_swx_port_source_sink.c | 335 +++++++++++++++++++++ lib/librte_port/rte_swx_port_source_sink.h | 57 ++++ 5 files changed, 400 insertions(+), 2 deletions(-) create mode 100644 lib/librte_port/rte_swx_port_source_sink.c create mode 100644 lib/librte_port/rte_swx_port_source_sink.h diff --git a/lib/librte_port/Makefile b/lib/librte_port/Makefile index 682336c01..e4a9865d9 100644 --- a/lib/librte_port/Makefile +++ b/lib/librte_port/Makefile @@ -39,6 +39,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_source_sink.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_sym_crypto.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_eventdev.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_swx_port_ethdev.c +SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_swx_port_source_sink.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port.h @@ -58,5 +59,6 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_sym_crypto.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_eventdev.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_swx_port.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_swx_port_ethdev.h +SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_swx_port_source_sink.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_port/meson.build b/lib/librte_port/meson.build index 3d7f309bb..9bbae28b7 100644 --- a/lib/librte_port/meson.build +++ b/lib/librte_port/meson.build @@ -11,7 +11,8 @@ sources = files( 'rte_port_source_sink.c', 'rte_port_sym_crypto.c', 'rte_port_eventdev.c', - 'rte_swx_port_ethdev.c',) + 'rte_swx_port_ethdev.c', + 'rte_swx_port_source_sink.c',) headers = files( 'rte_port_ethdev.h', 'rte_port_fd.h', @@ -24,7 +25,8 @@ headers = files( 'rte_port_sym_crypto.h', 'rte_port_eventdev.h', 'rte_swx_port.h', - 'rte_swx_port_ethdev.h',) + 'rte_swx_port_ethdev.h', + 'rte_swx_port_source_sink.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 6da5c8074..eb4dd9347 100644 --- a/lib/librte_port/rte_port_version.map +++ b/lib/librte_port/rte_port_version.map @@ -39,4 +39,6 @@ EXPERIMENTAL { rte_port_eventdev_writer_nodrop_ops; rte_swx_port_ethdev_reader_ops; rte_swx_port_ethdev_writer_ops; + rte_swx_port_source_ops; + rte_swx_port_sink_ops; }; diff --git a/lib/librte_port/rte_swx_port_source_sink.c b/lib/librte_port/rte_swx_port_source_sink.c new file mode 100644 index 000000000..4180cba1c --- /dev/null +++ b/lib/librte_port/rte_swx_port_source_sink.c @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ +#include +#include +#include +#ifdef RTE_PORT_PCAP +#include +#endif +#include + +#include +#include +#include + +#include "rte_swx_port_source_sink.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 SOURCE + */ +#ifdef RTE_PORT_PCAP + +struct source { + struct { + struct rte_mempool *pool; + } params; + struct rte_swx_port_in_stats stats; + struct rte_mbuf **pkts; + uint32_t n_pkts; + uint32_t pos; +}; + +static void +source_free(void *port) +{ + struct source *p = port; + uint32_t i; + + if (!p) + return; + + for (i = 0; i < p->n_pkts; i++) + rte_pktmbuf_free(p->pkts[i]); + + free(p->pkts); + + free(p); +} + +static void * +source_create(void *args) +{ + char pcap_errbuf[PCAP_ERRBUF_SIZE]; + struct rte_swx_port_source_params *params = args; + struct source *p = NULL; + pcap_t *f = NULL; + uint32_t n_pkts_max, i; + + /* Check input arguments. */ + CHECK(params); + CHECK(params->pool); + CHECK(params->file_name && params->file_name[0]); + n_pkts_max = params->n_pkts_max ? + params->n_pkts_max : + RTE_SWX_PORT_SOURCE_PKTS_MAX; + + /* Resource allocation. */ + f = pcap_open_offline(params->file_name, pcap_errbuf); + if (!f) + goto error; + + p = calloc(1, sizeof(struct source)); + if (!p) + goto error; + + p->pkts = calloc(n_pkts_max, sizeof(struct rte_mbuf *)); + if (!p->pkts) + goto error; + + /* Initialization. */ + p->params.pool = params->pool; + + /* PCAP file. */ + for (i = 0; i < n_pkts_max; i++) { + struct pcap_pkthdr pcap_pkthdr; + const uint8_t *pcap_pktdata; + struct rte_mbuf *m; + uint8_t *m_data; + + /* Read new packet from PCAP file. */ + pcap_pktdata = pcap_next(f, &pcap_pkthdr); + if (!pcap_pktdata) + break; + + /* Allocate new buffer from pool. */ + m = rte_pktmbuf_alloc(params->pool); + if (!m) + goto error; + m_data = rte_pktmbuf_mtod(m, uint8_t *); + + rte_memcpy(m_data, pcap_pktdata, pcap_pkthdr.caplen); + m->data_len = pcap_pkthdr.caplen; + m->pkt_len = pcap_pkthdr.caplen; + + p->pkts[p->n_pkts] = m; + p->n_pkts++; + } + + if (!p->n_pkts) + goto error; + + pcap_close(f); + return p; + +error: + source_free(p); + if (f) + pcap_close(f); + return NULL; +} + +static int +source_pkt_rx(void *port, struct rte_swx_pkt *pkt) +{ + struct source *p = port; + struct rte_mbuf *m_dst, *m_src; + uint8_t *m_dst_data, *m_src_data; + + /* m_src identification. */ + m_src = p->pkts[p->pos]; + m_src_data = rte_pktmbuf_mtod(m_src, uint8_t *); + + /* m_dst allocation from pool. */ + m_dst = rte_pktmbuf_alloc(p->params.pool); + if (!m_dst) + return 0; + + /* m_dst initialization. */ + m_dst->data_len = m_src->data_len; + m_dst->pkt_len = m_src->pkt_len; + m_dst->data_off = m_src->data_off; + + m_dst_data = rte_pktmbuf_mtod(m_dst, uint8_t *); + rte_memcpy(m_dst_data, m_src_data, m_src->data_len); + + /* pkt initialization. */ + pkt->handle = m_dst; + pkt->pkt = m_dst->buf_addr; + pkt->offset = m_dst->data_off; + pkt->length = m_dst->pkt_len; + + TRACE("[Source port] Pkt RX (%u bytes at offset %u)\n", + pkt->length, + pkt->offset); + if (TRACE_LEVEL) + rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + + /* port stats update. */ + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + + /* m_src next. */ + p->pos++; + if (p->pos == p->n_pkts) + p->pos = 0; + + return 1; +} + +static void +source_stats_read(void *port, struct rte_swx_port_in_stats *stats) +{ + struct source *p = port; + + if (!p || !stats) + return; + + memcpy(stats, &p->stats, sizeof(p->stats)); +} + +struct rte_swx_port_in_ops rte_swx_port_source_ops = { + .create = source_create, + .free = source_free, + .pkt_rx = source_pkt_rx, + .stats_read = source_stats_read, +}; + +#else + +struct rte_swx_port_in_ops rte_swx_port_source_ops = { + .create = NULL, + .free = NULL, + .pkt_rx = NULL, + .stats_read = NULL, +}; + +#endif + +/* + * Port SINK + */ +struct sink { + struct rte_swx_port_out_stats stats; + +#ifdef RTE_PORT_PCAP + pcap_t *f_pcap; + pcap_dumper_t *f_dump; +#endif +}; + +static void +sink_free(void *port) +{ + struct sink *p = port; + + if (!p) + return; + +#ifdef RTE_PORT_PCAP + if (p->f_dump) + pcap_dump_close(p->f_dump); + if (p->f_pcap) + pcap_close(p->f_pcap); +#endif + + free(p); +} + +static void * +sink_create(void *args __rte_unused) +{ + struct sink *p; + + /* Memory allocation. */ + p = calloc(1, sizeof(struct sink)); + if (!p) + goto error; + +#ifdef RTE_PORT_PCAP + if (args) { + struct rte_swx_port_sink_params *params = args; + + if (params->file_name && params->file_name[0]) { + p->f_pcap = pcap_open_dead(DLT_EN10MB, 65535); + if (!p->f_pcap) + goto error; + + p->f_dump = pcap_dump_open(p->f_pcap, + params->file_name); + if (!p->f_dump) + goto error; + } + } +#endif + + return p; + +error: + sink_free(p); + return NULL; +} + +static void +sink_pkt_tx(void *port, struct rte_swx_pkt *pkt) +{ + struct sink *p = port; + struct rte_mbuf *m = pkt->handle; + + TRACE("[Sink port] Pkt TX (%u bytes at offset %u)\n", + 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; + +#ifdef RTE_PORT_PCAP + if (p->f_dump) { + struct pcap_pkthdr pcap_pkthdr; + uint8_t *m_data = rte_pktmbuf_mtod(m, uint8_t *); + + pcap_pkthdr.len = m->pkt_len; + pcap_pkthdr.caplen = m->data_len; + gettimeofday(&pcap_pkthdr.ts, NULL); + + pcap_dump((uint8_t *)p->f_dump, &pcap_pkthdr, m_data); + pcap_dump_flush(p->f_dump); + } +#endif + + rte_pktmbuf_free(m); +} + +static void +sink_stats_read(void *port, struct rte_swx_port_out_stats *stats) +{ + struct sink *p = port; + + if (!p || !stats) + return; + + memcpy(stats, &p->stats, sizeof(p->stats)); +} + +/* + * Summary of port operations + */ +struct rte_swx_port_out_ops rte_swx_port_sink_ops = { + .create = sink_create, + .free = sink_free, + .pkt_tx = sink_pkt_tx, + .flush = NULL, + .stats_read = sink_stats_read, +}; diff --git a/lib/librte_port/rte_swx_port_source_sink.h b/lib/librte_port/rte_swx_port_source_sink.h new file mode 100644 index 000000000..88a890c5a --- /dev/null +++ b/lib/librte_port/rte_swx_port_source_sink.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ +#ifndef __INCLUDE_RTE_SWX_PORT_SOURCE_SINK_H__ +#define __INCLUDE_RTE_SWX_PORT_SOURCE_SINK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * RTE SWX Source and Sink Ports + */ + +#include "rte_swx_port.h" + +/** Maximum number of packets to read from the PCAP file. */ +#ifndef RTE_SWX_PORT_SOURCE_PKTS_MAX +#define RTE_SWX_PORT_SOURCE_PKTS_MAX 1024 +#endif + +/** Source port creation parameters. */ +struct rte_swx_port_source_params { + /** Buffer pool. Must be valid. */ + struct rte_mempool *pool; + + /** Name of a valid PCAP file to read the input packets from. */ + const char *file_name; + + /** Maximum number of packets to read from the PCAP file. When 0, it is + * internally set to RTE_SWX_PORT_SOURCE_PKTS_MAX. Once read from the + * PCAP file, the same packets are looped forever. + */ + uint32_t n_pkts_max; +}; + +/** Source port operations. */ +extern struct rte_swx_port_in_ops rte_swx_port_source_ops; + +/** Sink port creation parameters. */ +struct rte_swx_port_sink_params { + /** Name of a valid PCAP file to write the output packets to. When NULL, + * all the output packets are dropped instead of being saved to a PCAP + * file. + */ + const char *file_name; +}; + +/** Sink port operations. */ +extern struct rte_swx_port_out_ops rte_swx_port_sink_ops; + +#ifdef __cplusplus +} +#endif + +#endif -- 2.17.1