From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id E519DA0509; Tue, 5 Apr 2022 14:30:08 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 78E9240F35; Tue, 5 Apr 2022 14:30:08 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 31CEF40DF6 for ; Tue, 5 Apr 2022 14:30:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649161806; x=1680697806; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Xp/wjiLaSYg9aMxxnlefhSoA+Q3Unk5nofpZyZ18sr8=; b=B7OfRoannpzvcEcUuBTaryVy1Jx9IeCp7AiZ66K5lObSrD9zuA73UJcM gBg9QTh/MblSxPmSrro7jMnL9FiZgkzPZlz3+RYIatLm+43DlC/PwTrbz cA35oKyoMk9fPZQnfUUGfeSvB7gVUg/emrFq7Blz5mt28HscFDIikacEI smnxDgQadB/LM/Z9+5u0KDEsvez4naZIPNanKU1ngHFtLWG0kqKj4aC26 8kP3/ft+T4if9hm2riBD9piAGvY+pyISygBcDf9B6Qn5ttswoYU96hn5s WeIdl90ZpTKPhm6nOkEpLfue7kHKOQEce7aoOFe5IBufxUhkF6qnJ6Lw0 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10307"; a="259567319" X-IronPort-AV: E=Sophos;i="5.90,236,1643702400"; d="scan'208";a="259567319" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Apr 2022 05:30:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,236,1643702400"; d="scan'208";a="523441133" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com) ([10.237.223.107]) by orsmga002.jf.intel.com with ESMTP; 05 Apr 2022 05:30:03 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: Kamalakannan R Subject: [PATCH V2 1/3] port: support packet mirroring Date: Tue, 5 Apr 2022 13:30:00 +0100 Message-Id: <20220405123002.40671-1-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220304180623.74893-1-cristian.dumitrescu@intel.com> References: <20220304180623.74893-1-cristian.dumitrescu@intel.com> 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 Signed-off-by: Kamalakannan R --- lib/port/rte_swx_port.h | 37 ++++++++++++++++ lib/port/rte_swx_port_ethdev.c | 67 ++++++++++++++++++++++++++++- lib/port/rte_swx_port_fd.c | 65 +++++++++++++++++++++++++++- lib/port/rte_swx_port_ring.c | 65 +++++++++++++++++++++++++++- lib/port/rte_swx_port_source_sink.c | 51 +++++++++++++++++++++- 5 files changed, 281 insertions(+), 4 deletions(-) diff --git a/lib/port/rte_swx_port.h b/lib/port/rte_swx_port.h index ecf109d2ca..2c94335ffd 100644 --- a/lib/port/rte_swx_port.h +++ b/lib/port/rte_swx_port.h @@ -147,6 +147,31 @@ typedef void (*rte_swx_port_out_pkt_tx_t)(void *port, struct rte_swx_pkt *pkt); +/** + * Output port packet fast clone and transmit + * + * @param[in] port + * Output port handle. + * @param[in] pkt + * Packet to be transmitted. + */ +typedef void +(*rte_swx_port_out_pkt_fast_clone_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, + uint32_t truncation_length); + /** * Output port flush * @@ -163,6 +188,12 @@ struct rte_swx_port_out_stats { /** Number of bytes. */ uint64_t n_bytes; + + /** Number of packets cloned successfully. */ + uint64_t n_pkts_clone; + + /** Number of packets with clone errors. */ + uint64_t n_pkts_clone_err; }; /** @@ -188,6 +219,12 @@ struct rte_swx_port_out_ops { /** Packet transmission. Must be non-NULL. */ rte_swx_port_out_pkt_tx_t pkt_tx; + /** Packet fast clone and transmission. Must be non-NULL. */ + rte_swx_port_out_pkt_fast_clone_tx_t pkt_fast_clone_tx; + + /** Packet clone and 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..ca4a43ac4f 100644 --- a/lib/port/rte_swx_port_ethdev.c +++ b/lib/port/rte_swx_port_ethdev.c @@ -252,8 +252,8 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) if (TRACE_LEVEL) rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); m->pkt_len = pkt->length; - m->data_len = (uint16_t)pkt->length; m->data_off = (uint16_t)pkt->offset; p->stats.n_pkts++; @@ -264,6 +264,69 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_fast_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) (fast 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + rte_pktmbuf_refcnt_update(m, 1); + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m; + if (p->n_pkts == (int)p->params.burst_size) + __writer_flush(p); +} + +static void +writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle, *m_clone; + + 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + + m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length); + if (!m_clone) { + p->stats.n_pkts_clone_err++; + return; + } + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m_clone; + if (p->n_pkts == (int)p->params.burst_size) + __writer_flush(p); +} + static void writer_flush(void *port) { @@ -308,6 +371,8 @@ struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_fast_clone_tx = writer_pkt_fast_clone_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..1ee5086684 100644 --- a/lib/port/rte_swx_port_fd.c +++ b/lib/port/rte_swx_port_fd.c @@ -237,8 +237,8 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) if (TRACE_LEVEL) rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); m->pkt_len = pkt->length; - m->data_len = (uint16_t)pkt->length; m->data_off = (uint16_t)pkt->offset; p->stats.n_pkts++; @@ -249,6 +249,67 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_fast_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) (fast 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + rte_pktmbuf_refcnt_update(m, 1); + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m; + if (p->n_pkts == p->params.burst_size) + __writer_flush(p); +} + +static void +writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle, *m_clone; + + 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + + m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length); + if (!m_clone) { + p->stats.n_pkts_clone_err++; + return; + } + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m_clone; + if (p->n_pkts == p->params.burst_size) + __writer_flush(p); +} + static void writer_flush(void *port) { @@ -293,6 +354,8 @@ struct rte_swx_port_out_ops rte_swx_port_fd_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_fast_clone_tx = writer_pkt_fast_clone_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..c62fb3d8c8 100644 --- a/lib/port/rte_swx_port_ring.c +++ b/lib/port/rte_swx_port_ring.c @@ -252,8 +252,8 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) if (TRACE_LEVEL) rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); m->pkt_len = pkt->length; - m->data_len = (uint16_t)pkt->length; m->data_off = (uint16_t)pkt->offset; p->stats.n_pkts++; @@ -264,6 +264,67 @@ writer_pkt_tx(void *port, struct rte_swx_pkt *pkt) __writer_flush(p); } +static void +writer_pkt_fast_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) (fast 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + rte_pktmbuf_refcnt_update(m, 1); + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m; + if (p->n_pkts == (int)p->params.burst_size) + __writer_flush(p); +} + +static void +writer_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length) +{ + struct writer *p = port; + struct rte_mbuf *m = pkt->handle, *m_clone; + + 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->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + + m_clone = rte_pktmbuf_copy(m, m->pool, 0, truncation_length); + if (!m_clone) { + p->stats.n_pkts_clone_err++; + return; + } + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + + p->pkts[p->n_pkts++] = m_clone; + if (p->n_pkts == (int)p->params.burst_size) + __writer_flush(p); +} + static void writer_flush(void *port) { @@ -312,6 +373,8 @@ struct rte_swx_port_out_ops rte_swx_port_ring_writer_ops = { .create = writer_create, .free = writer_free, .pkt_tx = writer_pkt_tx, + .pkt_fast_clone_tx = writer_pkt_fast_clone_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..d3cf42c30b 100644 --- a/lib/port/rte_swx_port_source_sink.c +++ b/lib/port/rte_swx_port_source_sink.c @@ -295,8 +295,8 @@ sink_pkt_tx(void *port, struct rte_swx_pkt *pkt) if (TRACE_LEVEL) rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); m->pkt_len = pkt->length; - m->data_len = (uint16_t)pkt->length; m->data_off = (uint16_t)pkt->offset; p->stats.n_pkts++; @@ -319,6 +319,53 @@ 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, uint32_t truncation_length __rte_unused) +{ + struct sink *p = port; + struct rte_mbuf *m = pkt->handle; + + TRACE("[Sink port] Pkt TX (%u bytes at offset %u) (clone)\n", + pkt->length, + pkt->offset); + if (TRACE_LEVEL) + rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length); + + m->data_len = (uint16_t)(pkt->length + m->data_len - m->pkt_len); + m->pkt_len = pkt->length; + m->data_off = (uint16_t)pkt->offset; + + p->stats.n_pkts++; + p->stats.n_bytes += pkt->length; + p->stats.n_pkts_clone++; + +#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 = RTE_MIN(m->data_len, truncation_length); + 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_pkt_fast_clone_tx(void *port, struct rte_swx_pkt *pkt) +{ + __sink_pkt_clone_tx(port, pkt, UINT32_MAX); +} + +static void +sink_pkt_clone_tx(void *port, struct rte_swx_pkt *pkt, uint32_t truncation_length) +{ + __sink_pkt_clone_tx(port, pkt, truncation_length); +} + static void sink_stats_read(void *port, struct rte_swx_port_out_stats *stats) { @@ -337,6 +384,8 @@ struct rte_swx_port_out_ops rte_swx_port_sink_ops = { .create = sink_create, .free = sink_free, .pkt_tx = sink_pkt_tx, + .pkt_fast_clone_tx = sink_pkt_fast_clone_tx, + .pkt_clone_tx = sink_pkt_clone_tx, .flush = NULL, .stats_read = sink_stats_read, }; -- 2.17.1