From: Cristian Dumitrescu Date: Wed, 6 Apr 2022 18:55:30 +0000 (+0100) Subject: port: support packet mirroring X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=b94eb6cd35490c24f01aa14c1131b7206835f609;p=dpdk.git port: support packet mirroring Add packet clone operation to the output ports in order to support packet mirroring. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R --- diff --git a/lib/port/rte_swx_port.h b/lib/port/rte_swx_port.h index ecf109d2ca..5e29100f59 100644 --- a/lib/port/rte_swx_port.h +++ b/lib/port/rte_swx_port.h @@ -147,6 +147,33 @@ 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. + * @param[in] truncation_length + * Packet length to be cloned. + */ +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 +190,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 +221,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, };