From patchwork Fri Mar 4 18:06:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 108542 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1914BA034E; Fri, 4 Mar 2022 19:06:29 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8BF70427D8; Fri, 4 Mar 2022 19:06:28 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mails.dpdk.org (Postfix) with ESMTP id BC50A427A9 for ; Fri, 4 Mar 2022 19:06:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1646417186; x=1677953186; h=from:to:subject:date:message-id; bh=YXYlQJD0pyYbAW9NOnPJU3/4d3DQQACx2yeMk+s3PE4=; b=m1thyj1r9nv0qLF/qycEEuSNgYFbfU3CTOCJJSBUidV1IwpoDyUl2H9m gDe0DJzLxgtoxdFQcS9CiimQcHm9xNE139KKO8a6/EywKxKXKNBfzPUET 9khQA+AHVT3epv4bpd1/zg3YODMPU9CoOw0XG2s1NBIrC3eDnB7x7HpDT WUkPCWoH0hQEaKgOu9SXD7QC3l4QR4I66vx+5riaHRbbw/Q9ghB2tpcwe mazaZLCPgA7+W618hrg05MFz8/uh/dT1NistmhIyb/4lOTy/TAxXoq+5j 1PvqmrAdHFWXQ0ksjkHS9cTtMsrfhh1v3QNXujLxu0lK5ZjHvg218SaGj w==; X-IronPort-AV: E=McAfee;i="6200,9189,10276"; a="251604396" X-IronPort-AV: E=Sophos;i="5.90,155,1643702400"; d="scan'208";a="251604396" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2022 10:06:25 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,155,1643702400"; d="scan'208";a="552309330" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by orsmga008.jf.intel.com with ESMTP; 04 Mar 2022 10:06:23 -0800 From: Cristian Dumitrescu To: dev@dpdk.org Subject: [PATCH 1/3] port: support packet mirroring Date: Fri, 4 Mar 2022 18:06:21 +0000 Message-Id: <20220304180623.74893-1-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add packet clone operation to the output ports in order to support packet mirroring. Signed-off-by: Cristian Dumitrescu --- lib/pipeline/rte_swx_pipeline.c | 2 ++ lib/pipeline/rte_swx_pipeline_internal.h | 1 + lib/port/rte_swx_port.h | 15 ++++++++++ lib/port/rte_swx_port_ethdev.c | 29 ++++++++++++++++++++ lib/port/rte_swx_port_fd.c | 29 ++++++++++++++++++++ lib/port/rte_swx_port_ring.c | 28 +++++++++++++++++++ lib/port/rte_swx_port_source_sink.c | 35 ++++++++++++++++++++++++ 7 files changed, 139 insertions(+) diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 8c4670e111..bde20c5660 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -423,6 +423,7 @@ rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p, CHECK(ops->create, EINVAL); CHECK(ops->free, EINVAL); CHECK(ops->pkt_tx, EINVAL); + CHECK(ops->pkt_clone_tx, EINVAL); CHECK(ops->stats_read, EINVAL); CHECK(!port_out_type_find(p, name), EEXIST); @@ -509,6 +510,7 @@ port_out_build(struct rte_swx_pipeline *p) struct port_out_runtime *out = &p->out[port->id]; out->pkt_tx = port->type->ops.pkt_tx; + out->pkt_clone_tx = port->type->ops.pkt_clone_tx; out->flush = port->type->ops.flush; out->obj = port->obj; } diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h index da3e88bfa8..6ccd9948fa 100644 --- a/lib/pipeline/rte_swx_pipeline_internal.h +++ b/lib/pipeline/rte_swx_pipeline_internal.h @@ -104,6 +104,7 @@ TAILQ_HEAD(port_out_tailq, port_out); struct port_out_runtime { rte_swx_port_out_pkt_tx_t pkt_tx; + rte_swx_port_out_pkt_clone_tx_t pkt_clone_tx; rte_swx_port_out_flush_t flush; void *obj; }; diff --git a/lib/port/rte_swx_port.h b/lib/port/rte_swx_port.h index ecf109d2ca..e305a580fe 100644 --- a/lib/port/rte_swx_port.h +++ b/lib/port/rte_swx_port.h @@ -147,6 +147,18 @@ typedef void (*rte_swx_port_out_pkt_tx_t)(void *port, struct rte_swx_pkt *pkt); +/** + * Output port packet clone and transmit + * + * @param[in] port + * Output port handle. + * @param[in] pkt + * Packet to be transmitted. + */ +typedef void +(*rte_swx_port_out_pkt_clone_tx_t)(void *port, + struct rte_swx_pkt *pkt); + /** * Output port flush * @@ -188,6 +200,9 @@ struct rte_swx_port_out_ops { /** Packet transmission. Must be non-NULL. */ rte_swx_port_out_pkt_tx_t pkt_tx; + /** Packet clone transmission. Must be non-NULL. */ + rte_swx_port_out_pkt_clone_tx_t pkt_clone_tx; + /** Flush. May be NULL. */ rte_swx_port_out_flush_t flush; diff --git a/lib/port/rte_swx_port_ethdev.c b/lib/port/rte_swx_port_ethdev.c index 18d1c0b5db..a9101e805d 100644 --- a/lib/port/rte_swx_port_ethdev.c +++ b/lib/port/rte_swx_port_ethdev.c @@ -264,6 +264,34 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_clone_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) (clone)\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; + rte_mbuf_refcnt_update(m, 1); + + 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) { @@ -308,6 +336,7 @@ struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_clone_tx = writer_pkt_clone_tx, .flush = writer_flush, .stats_read = writer_stats_read, }; diff --git a/lib/port/rte_swx_port_fd.c b/lib/port/rte_swx_port_fd.c index 51bcd3bb7b..1806772c04 100644 --- a/lib/port/rte_swx_port_fd.c +++ b/lib/port/rte_swx_port_fd.c @@ -249,6 +249,34 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle; + + TRACE("[FD %u] Pkt %u (%u bytes at offset %u) (clone)\n", + (uint32_t)p->params.fd, + 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; + rte_mbuf_refcnt_update(m, 1); + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + + p->pkts[p->n_pkts++] = m; + if (p->n_pkts == p->params.burst_size) + __writer_flush(p); +} + static void writer_flush(void *port) { @@ -293,6 +321,7 @@ struct rte_swx_port_out_ops rte_swx_port_fd_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_clone_tx = writer_pkt_clone_tx, .flush = writer_flush, .stats_read = writer_stats_read, }; diff --git a/lib/port/rte_swx_port_ring.c b/lib/port/rte_swx_port_ring.c index 8a076a2135..f6a36e7fa1 100644 --- a/lib/port/rte_swx_port_ring.c +++ b/lib/port/rte_swx_port_ring.c @@ -264,6 +264,33 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle; + + TRACE("[Ring %s] Pkt %d (%u bytes at offset %u) (clone)\n", + p->params.name, + 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; + rte_mbuf_refcnt_update(m, 1); + + 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) { @@ -312,6 +339,7 @@ struct rte_swx_port_out_ops rte_swx_port_ring_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_clone_tx = writer_pkt_clone_tx, .flush = writer_flush, .stats_read = writer_stats_read, }; diff --git a/lib/port/rte_swx_port_source_sink.c b/lib/port/rte_swx_port_source_sink.c index 93c346cfb1..1dd446f3ab 100644 --- a/lib/port/rte_swx_port_source_sink.c +++ b/lib/port/rte_swx_port_source_sink.c @@ -319,6 +319,40 @@ sink_pkt_tx(void *port, struct rte_swx_pkt *pkt) rte_pktmbuf_free(m); } +static void +sink_pkt_clone_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 +} + static void sink_stats_read(void *port, struct rte_swx_port_out_stats *stats) { @@ -337,6 +371,7 @@ struct rte_swx_port_out_ops rte_swx_port_sink_ops = { .create = sink_create, .free = sink_free, .pkt_tx = sink_pkt_tx, + .pkt_clone_tx = sink_pkt_clone_tx, .flush = NULL, .stats_read = sink_stats_read, };