DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v3] app/testpmd: expand noisy neighbour forward mode support
@ 2023-04-17 18:55 Mike Pattrick
  2023-05-26 15:34 ` Kevin Traynor
  2023-06-02 18:29 ` [PATCH v4] " Mike Pattrick
  0 siblings, 2 replies; 18+ messages in thread
From: Mike Pattrick @ 2023-04-17 18:55 UTC (permalink / raw)
  To: Aman Singh, Yuying Zhang; +Cc: dev, Mike Pattrick

Previously the noisy neighbour vnf simulation would only operate in io
mode, forwarding packets as is. However, this limited the usefulness of
noisy neighbour simulation.

This feature has now been expanded to supporting mac, macswap, and
5tswap modes. To facilitate adding this support, some new header files
were added.

Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
v2: Reverted changes to random memory lookup
v3: Refactored entire patch
---
 app/test-pmd/5tswap.c                 | 118 +----------------------
 app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
 app/test-pmd/macfwd.c                 |  33 +------
 app/test-pmd/macfwd.h                 |  46 +++++++++
 app/test-pmd/noisy_vnf.c              |  92 +++++++++++++++---
 app/test-pmd/parameters.c             |  17 ++++
 app/test-pmd/testpmd.c                |   5 +
 app/test-pmd/testpmd.h                |   8 ++
 doc/guides/testpmd_app_ug/run_app.rst |   9 ++
 9 files changed, 299 insertions(+), 159 deletions(-)
 create mode 100644 app/test-pmd/5tswap.h
 create mode 100644 app/test-pmd/macfwd.h

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index ff8c2dcde5..8e8de2557a 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -17,64 +17,8 @@
 #include <rte_ip.h>
 #include <rte_flow.h>
 
-#include "macswap_common.h"
 #include "testpmd.h"
-
-
-static inline void
-swap_mac(struct rte_ether_hdr *eth_hdr)
-{
-	struct rte_ether_addr addr;
-
-	/* Swap dest and src mac addresses. */
-	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
-	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
-	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
-}
-
-static inline void
-swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
-{
-	rte_be32_t addr;
-
-	/* Swap dest and src ipv4 addresses. */
-	addr = ipv4_hdr->src_addr;
-	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
-	ipv4_hdr->dst_addr = addr;
-}
-
-static inline void
-swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
-{
-	uint8_t addr[16];
-
-	/* Swap dest and src ipv6 addresses. */
-	memcpy(&addr, &ipv6_hdr->src_addr, 16);
-	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
-	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
-}
-
-static inline void
-swap_tcp(struct rte_tcp_hdr *tcp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src tcp port. */
-	port = tcp_hdr->src_port;
-	tcp_hdr->src_port = tcp_hdr->dst_port;
-	tcp_hdr->dst_port = port;
-}
-
-static inline void
-swap_udp(struct rte_udp_hdr *udp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src udp port */
-	port = udp_hdr->src_port;
-	udp_hdr->src_port = udp_hdr->dst_port;
-	udp_hdr->dst_port = port;
-}
+#include "5tswap.h"
 
 /*
  * 5 tuple swap forwarding mode: Swap the source and the destination of layers
@@ -85,22 +29,7 @@ static bool
 pkt_burst_5tuple_swap(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf *mb;
-	uint16_t next_proto;
-	uint64_t ol_flags;
-	uint16_t proto;
 	uint16_t nb_rx;
-	int i;
-	union {
-		struct rte_ether_hdr *eth;
-		struct rte_vlan_hdr *vlan;
-		struct rte_ipv4_hdr *ipv4;
-		struct rte_ipv6_hdr *ipv6;
-		struct rte_tcp_hdr *tcp;
-		struct rte_udp_hdr *udp;
-		uint8_t *byte;
-	} h;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
-	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
-					void *));
-		mb = pkts_burst[i];
-		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		proto = h.eth->ether_type;
-		swap_mac(h.eth);
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		h.eth++;
-		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			proto = h.vlan->eth_proto;
-			h.vlan++;
-			mb->l2_len += sizeof(struct rte_vlan_hdr);
-		}
-		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
-			swap_ipv4(h.ipv4);
-			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
-			h.byte += mb->l3_len;
-		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
-			swap_ipv6(h.ipv6);
-			next_proto = h.ipv6->proto;
-			h.ipv6++;
-			mb->l3_len = sizeof(struct rte_ipv6_hdr);
-		} else {
-			mbuf_field_set(mb, ol_flags);
-			continue;
-		}
-		if (next_proto == IPPROTO_UDP) {
-			swap_udp(h.udp);
-			mb->l4_len = sizeof(struct rte_udp_hdr);
-		} else if (next_proto == IPPROTO_TCP) {
-			swap_tcp(h.tcp);
-			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
-		}
-		mbuf_field_set(mb, ol_flags);
-	}
+	do_5tswap(pkts_burst, nb_rx, fs);
+
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
 	return true;
diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
new file mode 100644
index 0000000000..48da9236dc
--- /dev/null
+++ b/app/test-pmd/5tswap.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _5TSWAP_H_
+#define _5TSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+swap_mac(struct rte_ether_hdr *eth_hdr)
+{
+	struct rte_ether_addr addr;
+
+	/* Swap dest and src mac addresses. */
+	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
+	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
+	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
+}
+
+static inline void
+swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
+{
+	rte_be32_t addr;
+
+	/* Swap dest and src ipv4 addresses. */
+	addr = ipv4_hdr->src_addr;
+	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
+	ipv4_hdr->dst_addr = addr;
+}
+
+static inline void
+swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
+{
+	uint8_t addr[16];
+
+	/* Swap dest and src ipv6 addresses. */
+	memcpy(&addr, &ipv6_hdr->src_addr, 16);
+	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
+	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
+}
+
+static inline void
+swap_tcp(struct rte_tcp_hdr *tcp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src tcp port. */
+	port = tcp_hdr->src_port;
+	tcp_hdr->src_port = tcp_hdr->dst_port;
+	tcp_hdr->dst_port = port;
+}
+
+static inline void
+swap_udp(struct rte_udp_hdr *udp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src udp port */
+	port = udp_hdr->src_port;
+	udp_hdr->src_port = udp_hdr->dst_port;
+	udp_hdr->dst_port = port;
+}
+
+static inline void
+do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+		  struct fwd_stream *fs)
+{
+	struct rte_port  *txp;
+	struct rte_mbuf *mb;
+	uint16_t next_proto;
+	uint64_t ol_flags;
+	uint16_t proto;
+	int i;
+	union {
+		struct rte_ether_hdr *eth;
+		struct rte_vlan_hdr *vlan;
+		struct rte_ipv4_hdr *ipv4;
+		struct rte_ipv6_hdr *ipv6;
+		struct rte_tcp_hdr *tcp;
+		struct rte_udp_hdr *udp;
+		uint8_t *byte;
+	} h;
+
+	txp = &ports[fs->tx_port];
+	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
+			txp->tx_vlan_id, txp->tx_vlan_id_outer);
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
+					void *));
+		mb = pkts_burst[i];
+		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		proto = h.eth->ether_type;
+		swap_mac(h.eth);
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		h.eth++;
+		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			proto = h.vlan->eth_proto;
+			h.vlan++;
+			mb->l2_len += sizeof(struct rte_vlan_hdr);
+		}
+		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
+			swap_ipv4(h.ipv4);
+			next_proto = h.ipv4->next_proto_id;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
+			h.byte += mb->l3_len;
+		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
+			swap_ipv6(h.ipv6);
+			next_proto = h.ipv6->proto;
+			h.ipv6++;
+			mb->l3_len = sizeof(struct rte_ipv6_hdr);
+		} else {
+			mbuf_field_set(mb, ol_flags);
+			continue;
+		}
+		if (next_proto == IPPROTO_UDP) {
+			swap_udp(h.udp);
+			mb->l4_len = sizeof(struct rte_udp_hdr);
+		} else if (next_proto == IPPROTO_TCP) {
+			swap_tcp(h.tcp);
+			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
+		}
+		mbuf_field_set(mb, ol_flags);
+	}
+}
+
+#endif /* _5TSWAP_H_ */
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index 7316d73315..d19ace7395 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -35,6 +35,7 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#include "macfwd.h"
 
 /*
  * Forwarding of packets in MAC mode.
@@ -45,13 +46,7 @@ static bool
 pkt_burst_mac_forward(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf  *mb;
-	struct rte_ether_hdr *eth_hdr;
 	uint16_t nb_rx;
-	uint16_t i;
-	uint64_t ol_flags = 0;
-	uint64_t tx_offloads;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	tx_offloads = txp->dev_conf.txmode.offloads;
-	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
-		ol_flags = RTE_MBUF_F_TX_VLAN;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_QINQ;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_MACSEC;
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
-						       void *));
-		mb = pkts_burst[i];
-		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
-				&eth_hdr->dst_addr);
-		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
-				&eth_hdr->src_addr);
-		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
-		mb->ol_flags |= ol_flags;
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		mb->l3_len = sizeof(struct rte_ipv4_hdr);
-		mb->vlan_tci = txp->tx_vlan_id;
-		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
-	}
+	do_macfwd(pkts_burst, nb_rx, fs);
 
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
new file mode 100644
index 0000000000..3f3e7189e1
--- /dev/null
+++ b/app/test-pmd/macfwd.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _MACFWD_H_
+#define _MACFWD_H_
+
+static inline void
+do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+		  struct fwd_stream *fs)
+{
+	struct rte_ether_hdr *eth_hdr;
+	uint64_t ol_flags = 0;
+	uint64_t tx_offloads;
+	struct rte_mbuf  *mb;
+	struct rte_port *txp = &ports[fs->tx_port];
+	uint16_t i;
+
+
+	tx_offloads = txp->dev_conf.txmode.offloads;
+	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
+		ol_flags = RTE_MBUF_F_TX_VLAN;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_QINQ;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_MACSEC;
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+						       void *));
+		mb = pkts_burst[i];
+		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+				&eth_hdr->dst_addr);
+		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+				&eth_hdr->src_addr);
+		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
+		mb->ol_flags |= ol_flags;
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		mb->l3_len = sizeof(struct rte_ipv4_hdr);
+		mb->vlan_tci = txp->tx_vlan_id;
+		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+	}
+}
+
+#endif /* _MACFWD_H_ */
diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
index 2bf90a983c..1d5a2e470a 100644
--- a/app/test-pmd/noisy_vnf.c
+++ b/app/test-pmd/noisy_vnf.c
@@ -32,6 +32,18 @@
 #include <rte_malloc.h>
 
 #include "testpmd.h"
+#include "5tswap.h"
+#include "macfwd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(__ARM_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
 
 struct noisy_config {
 	struct rte_ring *f;
@@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
 {
 	uint16_t i, j;
 
-	if (!ncf->do_sim)
-		return;
-
 	for (i = 0; i < nb_pkts; i++) {
 		for (j = 0; j < noisy_lkup_num_writes; j++)
 			do_write(ncf->vnf_mem);
@@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
  *    out of the FIFO
  * 4. Cases 2 and 3 combined
  */
-static bool
-pkt_burst_noisy_vnf(struct fwd_stream *fs)
+static uint16_t
+noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
 {
 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
 	uint16_t nb_deqd = 0;
-	uint16_t nb_rx = 0;
 	uint16_t nb_tx = 0;
 	uint16_t nb_enqd;
 	unsigned int fifo_free;
@@ -126,12 +133,12 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 	bool needs_flush = false;
 	uint64_t now;
 
-	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
 	if (unlikely(nb_rx == 0))
 		goto flush;
 
 	if (!ncf->do_buffering) {
-		sim_memory_lookups(ncf, nb_rx);
+		if (ncf->do_sim)
+			sim_memory_lookups(ncf, nb_rx);
 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 		goto end;
 	}
@@ -169,11 +176,61 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 		ncf->prev_time = rte_get_timer_cycles();
 	}
 end:
+	return nb_tx;
+}
+
+static bool
+pkt_burst_io(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
 	return nb_rx > 0 || nb_tx > 0;
 }
 
-#define NOISY_STRSIZE 256
-#define NOISY_RING "noisy_ring_%d\n"
+static bool
+pkt_burst_mac(struct fwd_stream *fs)
+{
+	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	do_macfwd(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_burst_macswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx = 0;
+	uint16_t nb_tx = 0;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_brust_5tswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx = 0;
+	uint16_t nb_tx = 0;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	do_5tswap(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
 
 static void
 noisy_fwd_end(portid_t pi)
@@ -226,6 +283,15 @@ noisy_fwd_begin(portid_t pi)
 			 "--noisy-lkup-memory-size must be > 0\n");
 	}
 
+	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
+		noisy_vnf_engine.packet_fwd = pkt_burst_io;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
+		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
+
 	return 0;
 }
 
@@ -233,6 +299,6 @@ struct fwd_engine noisy_vnf_engine = {
 	.fwd_mode_name  = "noisy",
 	.port_fwd_begin = noisy_fwd_begin,
 	.port_fwd_end   = noisy_fwd_end,
-	.stream_init    = common_fwd_stream_init,
-	.packet_fwd     = pkt_burst_noisy_vnf,
+	.stream_init	= common_fwd_stream_init,
+	.packet_fwd     = pkt_burst_io,
 };
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3b37809baf..129c55c0ad 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -196,6 +196,7 @@ usage(char* progname)
 	printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
 	printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
 	printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
+	printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
 	printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
 	       "valid only with --mp-alloc=anon\n");
 	printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
@@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
 		{ "noisy-lkup-num-writes",	1, 0, 0 },
 		{ "noisy-lkup-num-reads",	1, 0, 0 },
 		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
+		{ "noisy-fwd-mode",             1, 0, 0 },
 		{ "no-iova-contig",             0, 0, 0 },
 		{ "rx-mq-mode",                 1, 0, 0 },
 		{ "record-core-cycles",         0, 0, 0 },
@@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE,
 						 "noisy-lkup-num-reads-writes must be >= 0\n");
 			}
+			if (!strcmp(lgopts[opt_idx].name,
+				    "noisy-fwd-mode")) {
+				if (!strcmp(optarg, "io"))
+					noisy_fwd_mode = NOISY_FWD_MODE_IO;
+				else if (!strcmp(optarg, "mac"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MAC;
+				else if (!strcmp(optarg, "macswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
+				else if (!strcmp(optarg, "5tswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
+				else
+					rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
+						 " must b a valid fwd mode\n",
+						 optarg);
+			}
 			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
 				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
 
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5cb6f92523..92784873ff 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
  */
 uint64_t noisy_lkup_num_reads_writes;
 
+/*
+ * Configurable forwarding mode in VNF simulation.
+ */
+int noisy_fwd_mode;
+
 /*
  * Receive Side Scaling (RSS) configuration.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..f70397ad26 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -116,6 +116,13 @@ enum {
 	QUEUE_JOB_TYPE_ACTION_QUERY,
 };
 
+enum {
+	NOISY_FWD_MODE_IO,
+	NOISY_FWD_MODE_MAC,
+	NOISY_FWD_MODE_MACSWAP,
+	NOISY_FWD_MODE_5TSWAP
+};
+
 /**
  * The data structure associated with RX and TX packet burst statistics
  * that are recorded for each forwarding stream.
@@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
 extern uint64_t noisy_lkup_num_writes;
 extern uint64_t noisy_lkup_num_reads;
 extern uint64_t noisy_lkup_num_reads_writes;
+extern int noisy_fwd_mode;
 
 extern uint8_t dcb_config;
 
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index 57b23241cf..fcca3e8921 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -519,6 +519,15 @@ The command line options are:
     Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
     Only available with the noisy forwarding mode. The default value is 0.
 
+*   ``--noisy-fwd-mode=mode``
+
+    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
+
+       io (the default)
+       mac
+       macswap
+       5tswap
+
 *   ``--no-iova-contig``
 
     Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] app/testpmd: expand noisy neighbour forward mode support
  2023-04-17 18:55 [PATCH v3] app/testpmd: expand noisy neighbour forward mode support Mike Pattrick
@ 2023-05-26 15:34 ` Kevin Traynor
  2023-05-26 17:32   ` Mike Pattrick
  2023-06-02 18:29 ` [PATCH v4] " Mike Pattrick
  1 sibling, 1 reply; 18+ messages in thread
From: Kevin Traynor @ 2023-05-26 15:34 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: dev, Ferruh Yigit, David Marchand

On 17/04/2023 19:55, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 

Hi Mike,

I think it makes sense to allow these functionalities to be combined. It 
does seem like that noisy neighbour shouldn't have been added as a 
standalone fowarding option in the first place, as it's not mutually 
exclusive with the other fwding modes. Now it's forcing a user to set a 
fwding mode within a fwding mode to combine the functionality :/

The approach is to allow the fwding modes to expose their forwarding 
method so noisy can call them. Did you consider to expose the noisy 
functionality and allow the other forwarding modes to call that when the 
--noisy-* flags are set?

For example, a user sets fwding mode as normal 'fwd=macfwd' but then if 
the user adds the --noisy-* params, the macfwd'ing mode calls some 
functions exposed to add the noise, which seems a bit more intuitive.

Also, if someone adds a new fwding mode, they can just call the noisy 
functions and don't have update noisy fwding mode to add the new mode.

I'm not sure if it's better, just throwing it out there as an 
alternative idea.

On the downside, it would break backwards compatibility because 
previously those --noisy-* params would have had no effect with say 
macfwd mode, but now they will. So maybe that's enough to prohibit it.

In the past, I would have had all the params set and just changed 
fwdmode to enable/disable noisy vnf. That would behaviour would now be 
changed with this approach.

What do you think?

Few comments on the code below.

thanks,
Kevin.

> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---
> v2: Reverted changes to random memory lookup
> v3: Refactored entire patch
> ---
>   app/test-pmd/5tswap.c                 | 118 +----------------------
>   app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
>   app/test-pmd/macfwd.c                 |  33 +------
>   app/test-pmd/macfwd.h                 |  46 +++++++++
>   app/test-pmd/noisy_vnf.c              |  92 +++++++++++++++---
>   app/test-pmd/parameters.c             |  17 ++++
>   app/test-pmd/testpmd.c                |   5 +
>   app/test-pmd/testpmd.h                |   8 ++
>   doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>   9 files changed, 299 insertions(+), 159 deletions(-)
>   create mode 100644 app/test-pmd/5tswap.h
>   create mode 100644 app/test-pmd/macfwd.h
> 
> diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
> index ff8c2dcde5..8e8de2557a 100644
> --- a/app/test-pmd/5tswap.c
> +++ b/app/test-pmd/5tswap.c
> @@ -17,64 +17,8 @@
>   #include <rte_ip.h>
>   #include <rte_flow.h>
>   
> -#include "macswap_common.h"
>   #include "testpmd.h"
> -
> -
> -static inline void
> -swap_mac(struct rte_ether_hdr *eth_hdr)
> -{
> -	struct rte_ether_addr addr;
> -
> -	/* Swap dest and src mac addresses. */
> -	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> -	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> -	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> -}
> -
> -static inline void
> -swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> -{
> -	rte_be32_t addr;
> -
> -	/* Swap dest and src ipv4 addresses. */
> -	addr = ipv4_hdr->src_addr;
> -	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> -	ipv4_hdr->dst_addr = addr;
> -}
> -
> -static inline void
> -swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> -{
> -	uint8_t addr[16];
> -
> -	/* Swap dest and src ipv6 addresses. */
> -	memcpy(&addr, &ipv6_hdr->src_addr, 16);
> -	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> -	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> -}
> -
> -static inline void
> -swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> -{
> -	rte_be16_t port;
> -
> -	/* Swap dest and src tcp port. */
> -	port = tcp_hdr->src_port;
> -	tcp_hdr->src_port = tcp_hdr->dst_port;
> -	tcp_hdr->dst_port = port;
> -}
> -
> -static inline void
> -swap_udp(struct rte_udp_hdr *udp_hdr)
> -{
> -	rte_be16_t port;
> -
> -	/* Swap dest and src udp port */
> -	port = udp_hdr->src_port;
> -	udp_hdr->src_port = udp_hdr->dst_port;
> -	udp_hdr->dst_port = port;
> -}
> +#include "5tswap.h"
>   
>   /*
>    * 5 tuple swap forwarding mode: Swap the source and the destination of layers
> @@ -85,22 +29,7 @@ static bool
>   pkt_burst_5tuple_swap(struct fwd_stream *fs)
>   {
>   	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> -	struct rte_port  *txp;
> -	struct rte_mbuf *mb;
> -	uint16_t next_proto;
> -	uint64_t ol_flags;
> -	uint16_t proto;
>   	uint16_t nb_rx;
> -	int i;
> -	union {
> -		struct rte_ether_hdr *eth;
> -		struct rte_vlan_hdr *vlan;
> -		struct rte_ipv4_hdr *ipv4;
> -		struct rte_ipv6_hdr *ipv6;
> -		struct rte_tcp_hdr *tcp;
> -		struct rte_udp_hdr *udp;
> -		uint8_t *byte;
> -	} h;
>   
>   	/*
>   	 * Receive a burst of packets and forward them.
> @@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
>   	if (unlikely(nb_rx == 0))
>   		return false;
>   
> -	txp = &ports[fs->tx_port];
> -	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> -	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> -			txp->tx_vlan_id, txp->tx_vlan_id_outer);
> -	for (i = 0; i < nb_rx; i++) {
> -		if (likely(i < nb_rx - 1))
> -			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> -					void *));
> -		mb = pkts_burst[i];
> -		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> -		proto = h.eth->ether_type;
> -		swap_mac(h.eth);
> -		mb->l2_len = sizeof(struct rte_ether_hdr);
> -		h.eth++;
> -		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> -		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> -			proto = h.vlan->eth_proto;
> -			h.vlan++;
> -			mb->l2_len += sizeof(struct rte_vlan_hdr);
> -		}
> -		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> -			swap_ipv4(h.ipv4);
> -			next_proto = h.ipv4->next_proto_id;
> -			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> -			h.byte += mb->l3_len;
> -		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> -			swap_ipv6(h.ipv6);
> -			next_proto = h.ipv6->proto;
> -			h.ipv6++;
> -			mb->l3_len = sizeof(struct rte_ipv6_hdr);
> -		} else {
> -			mbuf_field_set(mb, ol_flags);
> -			continue;
> -		}
> -		if (next_proto == IPPROTO_UDP) {
> -			swap_udp(h.udp);
> -			mb->l4_len = sizeof(struct rte_udp_hdr);
> -		} else if (next_proto == IPPROTO_TCP) {
> -			swap_tcp(h.tcp);
> -			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> -		}
> -		mbuf_field_set(mb, ol_flags);
> -	}
> +	do_5tswap(pkts_burst, nb_rx, fs);
> +

this simplification is nice.

>   	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>   
>   	return true;
> diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
> new file mode 100644
> index 0000000000..48da9236dc
> --- /dev/null
> +++ b/app/test-pmd/5tswap.h
> @@ -0,0 +1,130 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef _5TSWAP_H_
> +#define _5TSWAP_H_
> +
> +#include "macswap_common.h"
> +
> +static inline void
> +swap_mac(struct rte_ether_hdr *eth_hdr)
> +{
> +	struct rte_ether_addr addr;
> +
> +	/* Swap dest and src mac addresses. */
> +	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> +	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> +	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> +}
> +
> +static inline void
> +swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> +{
> +	rte_be32_t addr;
> +
> +	/* Swap dest and src ipv4 addresses. */
> +	addr = ipv4_hdr->src_addr;
> +	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> +	ipv4_hdr->dst_addr = addr;
> +}
> +
> +static inline void
> +swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> +{
> +	uint8_t addr[16];
> +
> +	/* Swap dest and src ipv6 addresses. */
> +	memcpy(&addr, &ipv6_hdr->src_addr, 16);
> +	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> +	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> +}
> +
> +static inline void
> +swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> +{
> +	rte_be16_t port;
> +
> +	/* Swap dest and src tcp port. */
> +	port = tcp_hdr->src_port;
> +	tcp_hdr->src_port = tcp_hdr->dst_port;
> +	tcp_hdr->dst_port = port;
> +}
> +
> +static inline void
> +swap_udp(struct rte_udp_hdr *udp_hdr)
> +{
> +	rte_be16_t port;
> +
> +	/* Swap dest and src udp port */
> +	port = udp_hdr->src_port;
> +	udp_hdr->src_port = udp_hdr->dst_port;
> +	udp_hdr->dst_port = port;
> +}
> +
> +static inline void
> +do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> +		  struct fwd_stream *fs)
> +{
> +	struct rte_port  *txp;
> +	struct rte_mbuf *mb;
> +	uint16_t next_proto;
> +	uint64_t ol_flags;
> +	uint16_t proto;
> +	int i;
> +	union {
> +		struct rte_ether_hdr *eth;
> +		struct rte_vlan_hdr *vlan;
> +		struct rte_ipv4_hdr *ipv4;
> +		struct rte_ipv6_hdr *ipv6;
> +		struct rte_tcp_hdr *tcp;
> +		struct rte_udp_hdr *udp;
> +		uint8_t *byte;
> +	} h;
> +
> +	txp = &ports[fs->tx_port];
> +	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> +	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> +			txp->tx_vlan_id, txp->tx_vlan_id_outer);
> +	for (i = 0; i < nb_rx; i++) {
> +		if (likely(i < nb_rx - 1))
> +			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> +					void *));
> +		mb = pkts_burst[i];
> +		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> +		proto = h.eth->ether_type;
> +		swap_mac(h.eth);
> +		mb->l2_len = sizeof(struct rte_ether_hdr);
> +		h.eth++;
> +		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> +		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> +			proto = h.vlan->eth_proto;
> +			h.vlan++;
> +			mb->l2_len += sizeof(struct rte_vlan_hdr);
> +		}
> +		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> +			swap_ipv4(h.ipv4);
> +			next_proto = h.ipv4->next_proto_id;
> +			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> +			h.byte += mb->l3_len;
> +		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> +			swap_ipv6(h.ipv6);
> +			next_proto = h.ipv6->proto;
> +			h.ipv6++;
> +			mb->l3_len = sizeof(struct rte_ipv6_hdr);
> +		} else {
> +			mbuf_field_set(mb, ol_flags);
> +			continue;
> +		}
> +		if (next_proto == IPPROTO_UDP) {
> +			swap_udp(h.udp);
> +			mb->l4_len = sizeof(struct rte_udp_hdr);
> +		} else if (next_proto == IPPROTO_TCP) {
> +			swap_tcp(h.tcp);
> +			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> +		}
> +		mbuf_field_set(mb, ol_flags);
> +	}
> +}
> +
> +#endif /* _5TSWAP_H_ */
> diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
> index 7316d73315..d19ace7395 100644
> --- a/app/test-pmd/macfwd.c
> +++ b/app/test-pmd/macfwd.c
> @@ -35,6 +35,7 @@
>   #include <rte_flow.h>
>   
>   #include "testpmd.h"
> +#include "macfwd.h"
>   
>   /*
>    * Forwarding of packets in MAC mode.
> @@ -45,13 +46,7 @@ static bool
>   pkt_burst_mac_forward(struct fwd_stream *fs)
>   {
>   	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> -	struct rte_port  *txp;
> -	struct rte_mbuf  *mb;
> -	struct rte_ether_hdr *eth_hdr;
>   	uint16_t nb_rx;
> -	uint16_t i;
> -	uint64_t ol_flags = 0;
> -	uint64_t tx_offloads;
>   
>   	/*
>   	 * Receive a burst of packets and forward them.
> @@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
>   	if (unlikely(nb_rx == 0))
>   		return false;
>   
> -	txp = &ports[fs->tx_port];
> -	tx_offloads = txp->dev_conf.txmode.offloads;
> -	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> -		ol_flags = RTE_MBUF_F_TX_VLAN;
> -	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> -		ol_flags |= RTE_MBUF_F_TX_QINQ;
> -	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> -		ol_flags |= RTE_MBUF_F_TX_MACSEC;
> -	for (i = 0; i < nb_rx; i++) {
> -		if (likely(i < nb_rx - 1))
> -			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> -						       void *));
> -		mb = pkts_burst[i];
> -		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> -		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> -				&eth_hdr->dst_addr);
> -		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> -				&eth_hdr->src_addr);
> -		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> -		mb->ol_flags |= ol_flags;
> -		mb->l2_len = sizeof(struct rte_ether_hdr);
> -		mb->l3_len = sizeof(struct rte_ipv4_hdr);
> -		mb->vlan_tci = txp->tx_vlan_id;
> -		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> -	}
> +	do_macfwd(pkts_burst, nb_rx, fs);
>   
>   	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>   
> diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
> new file mode 100644
> index 0000000000..3f3e7189e1
> --- /dev/null
> +++ b/app/test-pmd/macfwd.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef _MACFWD_H_
> +#define _MACFWD_H_
> +
> +static inline void
> +do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> +		  struct fwd_stream *fs)

nit: indent/alignment is a little off here. There is some extra spaces. 
Same with other do_*()

> +{
> +	struct rte_ether_hdr *eth_hdr;
> +	uint64_t ol_flags = 0;
> +	uint64_t tx_offloads;
> +	struct rte_mbuf  *mb;
> +	struct rte_port *txp = &ports[fs->tx_port];
> +	uint16_t i;
> +
> +

can remove addition blank line

> +	tx_offloads = txp->dev_conf.txmode.offloads;
> +	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> +		ol_flags = RTE_MBUF_F_TX_VLAN;
> +	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> +		ol_flags |= RTE_MBUF_F_TX_QINQ;
> +	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> +		ol_flags |= RTE_MBUF_F_TX_MACSEC;
> +	for (i = 0; i < nb_rx; i++) {
> +		if (likely(i < nb_rx - 1))
> +			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> +						       void *));
> +		mb = pkts_burst[i];
> +		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> +		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> +				&eth_hdr->dst_addr);
> +		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> +				&eth_hdr->src_addr);
> +		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> +		mb->ol_flags |= ol_flags;
> +		mb->l2_len = sizeof(struct rte_ether_hdr);
> +		mb->l3_len = sizeof(struct rte_ipv4_hdr);
> +		mb->vlan_tci = txp->tx_vlan_id;
> +		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> +	}
> +}
> +
> +#endif /* _MACFWD_H_ */
> diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
> index 2bf90a983c..1d5a2e470a 100644
> --- a/app/test-pmd/noisy_vnf.c
> +++ b/app/test-pmd/noisy_vnf.c
> @@ -32,6 +32,18 @@
>   #include <rte_malloc.h>
>   
>   #include "testpmd.h"
> +#include "5tswap.h"
> +#include "macfwd.h"
> +#if defined(RTE_ARCH_X86)
> +#include "macswap_sse.h"
> +#elif defined(__ARM_NEON)
> +#include "macswap_neon.h"
> +#else
> +#include "macswap.h"
> +#endif
> +
> +#define NOISY_STRSIZE 256
> +#define NOISY_RING "noisy_ring_%d\n"
>   
>   struct noisy_config {
>   	struct rte_ring *f;
> @@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>   {
>   	uint16_t i, j;
>   
> -	if (!ncf->do_sim)
> -		return;
> -

Why is this removed? It's not checked before all calls to this function

>   	for (i = 0; i < nb_pkts; i++) {
>   		for (j = 0; j < noisy_lkup_num_writes; j++)
>   			do_write(ncf->vnf_mem);
> @@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>    *    out of the FIFO
>    * 4. Cases 2 and 3 combined
>    */
> -static bool
> -pkt_burst_noisy_vnf(struct fwd_stream *fs)
> +static uint16_t
> +noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
>   {
>   	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
>   	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
> -	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>   	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
>   	uint16_t nb_deqd = 0;
> -	uint16_t nb_rx = 0;
>   	uint16_t nb_tx = 0;
>   	uint16_t nb_enqd;
>   	unsigned int fifo_free;
> @@ -126,12 +133,12 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>   	bool needs_flush = false;
>   	uint64_t now;
>   
> -	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>   	if (unlikely(nb_rx == 0))
>   		goto flush;
>   
>   	if (!ncf->do_buffering) {
> -		sim_memory_lookups(ncf, nb_rx);
> +		if (ncf->do_sim)
> +			sim_memory_lookups(ncf, nb_rx);
>   		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>   		goto end;
>   	}
> @@ -169,11 +176,61 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>   		ncf->prev_time = rte_get_timer_cycles();
>   	}
>   end:
> +	return nb_tx;
> +}
> +
> +static bool
> +pkt_burst_io(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
>   	return nb_rx > 0 || nb_tx > 0;
>   }
>   
> -#define NOISY_STRSIZE 256
> -#define NOISY_RING "noisy_ring_%d\n"
> +static bool
> +pkt_burst_mac(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);

Similar to macfwd.c, you can add check for unlikely(nb_rx == 0) at this 
point in these fns.

> +	do_macfwd(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_burst_macswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx = 0;
> +	uint16_t nb_tx = 0;

nit: these are not assigned in the other functions

> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_brust_5tswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx = 0;
> +	uint16_t nb_tx = 0;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	do_5tswap(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
>   
>   static void
>   noisy_fwd_end(portid_t pi)
> @@ -226,6 +283,15 @@ noisy_fwd_begin(portid_t pi)
>   			 "--noisy-lkup-memory-size must be > 0\n");
>   	}
>   
> +	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_io;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
> +
>   	return 0;
>   }
>   
> @@ -233,6 +299,6 @@ struct fwd_engine noisy_vnf_engine = {
>   	.fwd_mode_name  = "noisy",
>   	.port_fwd_begin = noisy_fwd_begin,
>   	.port_fwd_end   = noisy_fwd_end,
> -	.stream_init    = common_fwd_stream_init,
> -	.packet_fwd     = pkt_burst_noisy_vnf,
> +	.stream_init	= common_fwd_stream_init,
> +	.packet_fwd     = pkt_burst_io,
>   };
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index 3b37809baf..129c55c0ad 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -196,6 +196,7 @@ usage(char* progname)
>   	printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
>   	printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
>   	printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
> +	printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
>   	printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
>   	       "valid only with --mp-alloc=anon\n");
>   	printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
> @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
>   		{ "noisy-lkup-num-writes",	1, 0, 0 },
>   		{ "noisy-lkup-num-reads",	1, 0, 0 },
>   		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
> +		{ "noisy-fwd-mode",             1, 0, 0 },
>   		{ "no-iova-contig",             0, 0, 0 },
>   		{ "rx-mq-mode",                 1, 0, 0 },
>   		{ "record-core-cycles",         0, 0, 0 },
> @@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
>   					rte_exit(EXIT_FAILURE,
>   						 "noisy-lkup-num-reads-writes must be >= 0\n");
>   			}
> +			if (!strcmp(lgopts[opt_idx].name,
> +				    "noisy-fwd-mode")) {
> +				if (!strcmp(optarg, "io"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_IO;
> +				else if (!strcmp(optarg, "mac"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_MAC;
> +				else if (!strcmp(optarg, "macswap"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
> +				else if (!strcmp(optarg, "5tswap"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
> +				else
> +					rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
> +						 " must b a valid fwd mode\n",

typo "be"

I would specify "..must be a valid noisy-fwd-mode value" to avoid 
confusion with the full set of general fwd modes and easier for user to 
search them in docs.

> +						 optarg);
> +			}
>   			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
>   				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
>   
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index 5cb6f92523..92784873ff 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
>    */
>   uint64_t noisy_lkup_num_reads_writes;
>   
> +/*
> + * Configurable forwarding mode in VNF simulation.
> + */
> +int noisy_fwd_mode;
> +
>   /*
>    * Receive Side Scaling (RSS) configuration.
>    */
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index bdfbfd36d3..f70397ad26 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -116,6 +116,13 @@ enum {
>   	QUEUE_JOB_TYPE_ACTION_QUERY,
>   };
>   
> +enum {
> +	NOISY_FWD_MODE_IO,
> +	NOISY_FWD_MODE_MAC,
> +	NOISY_FWD_MODE_MACSWAP,
> +	NOISY_FWD_MODE_5TSWAP
> +};
> +
>   /**
>    * The data structure associated with RX and TX packet burst statistics
>    * that are recorded for each forwarding stream.
> @@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
>   extern uint64_t noisy_lkup_num_writes;
>   extern uint64_t noisy_lkup_num_reads;
>   extern uint64_t noisy_lkup_num_reads_writes;
> +extern int noisy_fwd_mode;
>   
>   extern uint8_t dcb_config;
>   
> diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
> index 57b23241cf..fcca3e8921 100644
> --- a/doc/guides/testpmd_app_ug/run_app.rst
> +++ b/doc/guides/testpmd_app_ug/run_app.rst
> @@ -519,6 +519,15 @@ The command line options are:
>       Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
>       Only available with the noisy forwarding mode. The default value is 0.
>   
> +*   ``--noisy-fwd-mode=mode``
> +
> +    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
> +
> +       io (the default)
> +       mac
> +       macswap
> +       5tswap
> +
>   *   ``--no-iova-contig``
>   
>       Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] app/testpmd: expand noisy neighbour forward mode support
  2023-05-26 15:34 ` Kevin Traynor
@ 2023-05-26 17:32   ` Mike Pattrick
  2023-06-01 16:23     ` Kevin Traynor
  0 siblings, 1 reply; 18+ messages in thread
From: Mike Pattrick @ 2023-05-26 17:32 UTC (permalink / raw)
  To: Kevin Traynor; +Cc: Aman Singh, Yuying Zhang, dev, Ferruh Yigit, David Marchand

On Fri, May 26, 2023 at 11:34 AM Kevin Traynor <ktraynor@redhat.com> wrote:
>
> On 17/04/2023 19:55, Mike Pattrick wrote:
> > Previously the noisy neighbour vnf simulation would only operate in io
> > mode, forwarding packets as is. However, this limited the usefulness of
> > noisy neighbour simulation.
> >
> > This feature has now been expanded to supporting mac, macswap, and
> > 5tswap modes. To facilitate adding this support, some new header files
> > were added.
> >
>
> Hi Mike,
>
> I think it makes sense to allow these functionalities to be combined. It
> does seem like that noisy neighbour shouldn't have been added as a
> standalone fowarding option in the first place, as it's not mutually
> exclusive with the other fwding modes. Now it's forcing a user to set a
> fwding mode within a fwding mode to combine the functionality :/
>
> The approach is to allow the fwding modes to expose their forwarding
> method so noisy can call them. Did you consider to expose the noisy
> functionality and allow the other forwarding modes to call that when the
> --noisy-* flags are set?

Personally I like this approach more, and that was the strategy I took
with the previous version. However, that change didn't seem popular at
the time.

http://patches.dpdk.org/project/dpdk/patch/20230126045516.176917-1-mkp@redhat.com/#157095

> For example, a user sets fwding mode as normal 'fwd=macfwd' but then if
> the user adds the --noisy-* params, the macfwd'ing mode calls some
> functions exposed to add the noise, which seems a bit more intuitive.
>
> Also, if someone adds a new fwding mode, they can just call the noisy
> functions and don't have update noisy fwding mode to add the new mode.
>
> I'm not sure if it's better, just throwing it out there as an
> alternative idea.
>
> On the downside, it would break backwards compatibility because
> previously those --noisy-* params would have had no effect with say
> macfwd mode, but now they will. So maybe that's enough to prohibit it.
>
> In the past, I would have had all the params set and just changed
> fwdmode to enable/disable noisy vnf. That would behaviour would now be
> changed with this approach.
>
> What do you think?
>
> Few comments on the code below.
>
> thanks,
> Kevin.
>
> > Signed-off-by: Mike Pattrick <mkp@redhat.com>
> > ---
> > v2: Reverted changes to random memory lookup
> > v3: Refactored entire patch
> > ---
> >   app/test-pmd/5tswap.c                 | 118 +----------------------
> >   app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
> >   app/test-pmd/macfwd.c                 |  33 +------
> >   app/test-pmd/macfwd.h                 |  46 +++++++++
> >   app/test-pmd/noisy_vnf.c              |  92 +++++++++++++++---
> >   app/test-pmd/parameters.c             |  17 ++++
> >   app/test-pmd/testpmd.c                |   5 +
> >   app/test-pmd/testpmd.h                |   8 ++
> >   doc/guides/testpmd_app_ug/run_app.rst |   9 ++
> >   9 files changed, 299 insertions(+), 159 deletions(-)
> >   create mode 100644 app/test-pmd/5tswap.h
> >   create mode 100644 app/test-pmd/macfwd.h
> >
> > diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
> > index ff8c2dcde5..8e8de2557a 100644
> > --- a/app/test-pmd/5tswap.c
> > +++ b/app/test-pmd/5tswap.c
> > @@ -17,64 +17,8 @@
> >   #include <rte_ip.h>
> >   #include <rte_flow.h>
> >
> > -#include "macswap_common.h"
> >   #include "testpmd.h"
> > -
> > -
> > -static inline void
> > -swap_mac(struct rte_ether_hdr *eth_hdr)
> > -{
> > -     struct rte_ether_addr addr;
> > -
> > -     /* Swap dest and src mac addresses. */
> > -     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> > -     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> > -     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> > -}
> > -
> > -static inline void
> > -swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> > -{
> > -     rte_be32_t addr;
> > -
> > -     /* Swap dest and src ipv4 addresses. */
> > -     addr = ipv4_hdr->src_addr;
> > -     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> > -     ipv4_hdr->dst_addr = addr;
> > -}
> > -
> > -static inline void
> > -swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> > -{
> > -     uint8_t addr[16];
> > -
> > -     /* Swap dest and src ipv6 addresses. */
> > -     memcpy(&addr, &ipv6_hdr->src_addr, 16);
> > -     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> > -     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> > -}
> > -
> > -static inline void
> > -swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> > -{
> > -     rte_be16_t port;
> > -
> > -     /* Swap dest and src tcp port. */
> > -     port = tcp_hdr->src_port;
> > -     tcp_hdr->src_port = tcp_hdr->dst_port;
> > -     tcp_hdr->dst_port = port;
> > -}
> > -
> > -static inline void
> > -swap_udp(struct rte_udp_hdr *udp_hdr)
> > -{
> > -     rte_be16_t port;
> > -
> > -     /* Swap dest and src udp port */
> > -     port = udp_hdr->src_port;
> > -     udp_hdr->src_port = udp_hdr->dst_port;
> > -     udp_hdr->dst_port = port;
> > -}
> > +#include "5tswap.h"
> >
> >   /*
> >    * 5 tuple swap forwarding mode: Swap the source and the destination of layers
> > @@ -85,22 +29,7 @@ static bool
> >   pkt_burst_5tuple_swap(struct fwd_stream *fs)
> >   {
> >       struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> > -     struct rte_port  *txp;
> > -     struct rte_mbuf *mb;
> > -     uint16_t next_proto;
> > -     uint64_t ol_flags;
> > -     uint16_t proto;
> >       uint16_t nb_rx;
> > -     int i;
> > -     union {
> > -             struct rte_ether_hdr *eth;
> > -             struct rte_vlan_hdr *vlan;
> > -             struct rte_ipv4_hdr *ipv4;
> > -             struct rte_ipv6_hdr *ipv6;
> > -             struct rte_tcp_hdr *tcp;
> > -             struct rte_udp_hdr *udp;
> > -             uint8_t *byte;
> > -     } h;
> >
> >       /*
> >        * Receive a burst of packets and forward them.
> > @@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
> >       if (unlikely(nb_rx == 0))
> >               return false;
> >
> > -     txp = &ports[fs->tx_port];
> > -     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> > -     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> > -                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
> > -     for (i = 0; i < nb_rx; i++) {
> > -             if (likely(i < nb_rx - 1))
> > -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> > -                                     void *));
> > -             mb = pkts_burst[i];
> > -             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> > -             proto = h.eth->ether_type;
> > -             swap_mac(h.eth);
> > -             mb->l2_len = sizeof(struct rte_ether_hdr);
> > -             h.eth++;
> > -             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> > -                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> > -                     proto = h.vlan->eth_proto;
> > -                     h.vlan++;
> > -                     mb->l2_len += sizeof(struct rte_vlan_hdr);
> > -             }
> > -             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> > -                     swap_ipv4(h.ipv4);
> > -                     next_proto = h.ipv4->next_proto_id;
> > -                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> > -                     h.byte += mb->l3_len;
> > -             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> > -                     swap_ipv6(h.ipv6);
> > -                     next_proto = h.ipv6->proto;
> > -                     h.ipv6++;
> > -                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
> > -             } else {
> > -                     mbuf_field_set(mb, ol_flags);
> > -                     continue;
> > -             }
> > -             if (next_proto == IPPROTO_UDP) {
> > -                     swap_udp(h.udp);
> > -                     mb->l4_len = sizeof(struct rte_udp_hdr);
> > -             } else if (next_proto == IPPROTO_TCP) {
> > -                     swap_tcp(h.tcp);
> > -                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> > -             }
> > -             mbuf_field_set(mb, ol_flags);
> > -     }
> > +     do_5tswap(pkts_burst, nb_rx, fs);
> > +
>
> this simplification is nice.
>
> >       common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
> >
> >       return true;
> > diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
> > new file mode 100644
> > index 0000000000..48da9236dc
> > --- /dev/null
> > +++ b/app/test-pmd/5tswap.h
> > @@ -0,0 +1,130 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(c) 2018 Intel Corporation
> > + */
> > +
> > +#ifndef _5TSWAP_H_
> > +#define _5TSWAP_H_
> > +
> > +#include "macswap_common.h"
> > +
> > +static inline void
> > +swap_mac(struct rte_ether_hdr *eth_hdr)
> > +{
> > +     struct rte_ether_addr addr;
> > +
> > +     /* Swap dest and src mac addresses. */
> > +     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> > +     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> > +     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> > +}
> > +
> > +static inline void
> > +swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> > +{
> > +     rte_be32_t addr;
> > +
> > +     /* Swap dest and src ipv4 addresses. */
> > +     addr = ipv4_hdr->src_addr;
> > +     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> > +     ipv4_hdr->dst_addr = addr;
> > +}
> > +
> > +static inline void
> > +swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> > +{
> > +     uint8_t addr[16];
> > +
> > +     /* Swap dest and src ipv6 addresses. */
> > +     memcpy(&addr, &ipv6_hdr->src_addr, 16);
> > +     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> > +     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> > +}
> > +
> > +static inline void
> > +swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> > +{
> > +     rte_be16_t port;
> > +
> > +     /* Swap dest and src tcp port. */
> > +     port = tcp_hdr->src_port;
> > +     tcp_hdr->src_port = tcp_hdr->dst_port;
> > +     tcp_hdr->dst_port = port;
> > +}
> > +
> > +static inline void
> > +swap_udp(struct rte_udp_hdr *udp_hdr)
> > +{
> > +     rte_be16_t port;
> > +
> > +     /* Swap dest and src udp port */
> > +     port = udp_hdr->src_port;
> > +     udp_hdr->src_port = udp_hdr->dst_port;
> > +     udp_hdr->dst_port = port;
> > +}
> > +
> > +static inline void
> > +do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> > +               struct fwd_stream *fs)
> > +{
> > +     struct rte_port  *txp;
> > +     struct rte_mbuf *mb;
> > +     uint16_t next_proto;
> > +     uint64_t ol_flags;
> > +     uint16_t proto;
> > +     int i;
> > +     union {
> > +             struct rte_ether_hdr *eth;
> > +             struct rte_vlan_hdr *vlan;
> > +             struct rte_ipv4_hdr *ipv4;
> > +             struct rte_ipv6_hdr *ipv6;
> > +             struct rte_tcp_hdr *tcp;
> > +             struct rte_udp_hdr *udp;
> > +             uint8_t *byte;
> > +     } h;
> > +
> > +     txp = &ports[fs->tx_port];
> > +     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> > +     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> > +                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
> > +     for (i = 0; i < nb_rx; i++) {
> > +             if (likely(i < nb_rx - 1))
> > +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> > +                                     void *));
> > +             mb = pkts_burst[i];
> > +             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> > +             proto = h.eth->ether_type;
> > +             swap_mac(h.eth);
> > +             mb->l2_len = sizeof(struct rte_ether_hdr);
> > +             h.eth++;
> > +             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> > +                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> > +                     proto = h.vlan->eth_proto;
> > +                     h.vlan++;
> > +                     mb->l2_len += sizeof(struct rte_vlan_hdr);
> > +             }
> > +             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> > +                     swap_ipv4(h.ipv4);
> > +                     next_proto = h.ipv4->next_proto_id;
> > +                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> > +                     h.byte += mb->l3_len;
> > +             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> > +                     swap_ipv6(h.ipv6);
> > +                     next_proto = h.ipv6->proto;
> > +                     h.ipv6++;
> > +                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
> > +             } else {
> > +                     mbuf_field_set(mb, ol_flags);
> > +                     continue;
> > +             }
> > +             if (next_proto == IPPROTO_UDP) {
> > +                     swap_udp(h.udp);
> > +                     mb->l4_len = sizeof(struct rte_udp_hdr);
> > +             } else if (next_proto == IPPROTO_TCP) {
> > +                     swap_tcp(h.tcp);
> > +                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> > +             }
> > +             mbuf_field_set(mb, ol_flags);
> > +     }
> > +}
> > +
> > +#endif /* _5TSWAP_H_ */
> > diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
> > index 7316d73315..d19ace7395 100644
> > --- a/app/test-pmd/macfwd.c
> > +++ b/app/test-pmd/macfwd.c
> > @@ -35,6 +35,7 @@
> >   #include <rte_flow.h>
> >
> >   #include "testpmd.h"
> > +#include "macfwd.h"
> >
> >   /*
> >    * Forwarding of packets in MAC mode.
> > @@ -45,13 +46,7 @@ static bool
> >   pkt_burst_mac_forward(struct fwd_stream *fs)
> >   {
> >       struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> > -     struct rte_port  *txp;
> > -     struct rte_mbuf  *mb;
> > -     struct rte_ether_hdr *eth_hdr;
> >       uint16_t nb_rx;
> > -     uint16_t i;
> > -     uint64_t ol_flags = 0;
> > -     uint64_t tx_offloads;
> >
> >       /*
> >        * Receive a burst of packets and forward them.
> > @@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
> >       if (unlikely(nb_rx == 0))
> >               return false;
> >
> > -     txp = &ports[fs->tx_port];
> > -     tx_offloads = txp->dev_conf.txmode.offloads;
> > -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> > -             ol_flags = RTE_MBUF_F_TX_VLAN;
> > -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> > -             ol_flags |= RTE_MBUF_F_TX_QINQ;
> > -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> > -             ol_flags |= RTE_MBUF_F_TX_MACSEC;
> > -     for (i = 0; i < nb_rx; i++) {
> > -             if (likely(i < nb_rx - 1))
> > -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> > -                                                    void *));
> > -             mb = pkts_burst[i];
> > -             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> > -             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> > -                             &eth_hdr->dst_addr);
> > -             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> > -                             &eth_hdr->src_addr);
> > -             mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> > -             mb->ol_flags |= ol_flags;
> > -             mb->l2_len = sizeof(struct rte_ether_hdr);
> > -             mb->l3_len = sizeof(struct rte_ipv4_hdr);
> > -             mb->vlan_tci = txp->tx_vlan_id;
> > -             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> > -     }
> > +     do_macfwd(pkts_burst, nb_rx, fs);
> >
> >       common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
> >
> > diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
> > new file mode 100644
> > index 0000000000..3f3e7189e1
> > --- /dev/null
> > +++ b/app/test-pmd/macfwd.h
> > @@ -0,0 +1,46 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright(c) 2018 Intel Corporation
> > + */
> > +
> > +#ifndef _MACFWD_H_
> > +#define _MACFWD_H_
> > +
> > +static inline void
> > +do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> > +               struct fwd_stream *fs)
>
> nit: indent/alignment is a little off here. There is some extra spaces.
> Same with other do_*()
>
> > +{
> > +     struct rte_ether_hdr *eth_hdr;
> > +     uint64_t ol_flags = 0;
> > +     uint64_t tx_offloads;
> > +     struct rte_mbuf  *mb;
> > +     struct rte_port *txp = &ports[fs->tx_port];
> > +     uint16_t i;
> > +
> > +
>
> can remove addition blank line
>
> > +     tx_offloads = txp->dev_conf.txmode.offloads;
> > +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> > +             ol_flags = RTE_MBUF_F_TX_VLAN;
> > +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> > +             ol_flags |= RTE_MBUF_F_TX_QINQ;
> > +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> > +             ol_flags |= RTE_MBUF_F_TX_MACSEC;
> > +     for (i = 0; i < nb_rx; i++) {
> > +             if (likely(i < nb_rx - 1))
> > +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> > +                                                    void *));
> > +             mb = pkts_burst[i];
> > +             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> > +             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> > +                             &eth_hdr->dst_addr);
> > +             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> > +                             &eth_hdr->src_addr);
> > +             mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> > +             mb->ol_flags |= ol_flags;
> > +             mb->l2_len = sizeof(struct rte_ether_hdr);
> > +             mb->l3_len = sizeof(struct rte_ipv4_hdr);
> > +             mb->vlan_tci = txp->tx_vlan_id;
> > +             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> > +     }
> > +}
> > +
> > +#endif /* _MACFWD_H_ */
> > diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
> > index 2bf90a983c..1d5a2e470a 100644
> > --- a/app/test-pmd/noisy_vnf.c
> > +++ b/app/test-pmd/noisy_vnf.c
> > @@ -32,6 +32,18 @@
> >   #include <rte_malloc.h>
> >
> >   #include "testpmd.h"
> > +#include "5tswap.h"
> > +#include "macfwd.h"
> > +#if defined(RTE_ARCH_X86)
> > +#include "macswap_sse.h"
> > +#elif defined(__ARM_NEON)
> > +#include "macswap_neon.h"
> > +#else
> > +#include "macswap.h"
> > +#endif
> > +
> > +#define NOISY_STRSIZE 256
> > +#define NOISY_RING "noisy_ring_%d\n"
> >
> >   struct noisy_config {
> >       struct rte_ring *f;
> > @@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
> >   {
> >       uint16_t i, j;
> >
> > -     if (!ncf->do_sim)
> > -             return;
> > -
>
> Why is this removed? It's not checked before all calls to this function
>
> >       for (i = 0; i < nb_pkts; i++) {
> >               for (j = 0; j < noisy_lkup_num_writes; j++)
> >                       do_write(ncf->vnf_mem);
> > @@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
> >    *    out of the FIFO
> >    * 4. Cases 2 and 3 combined
> >    */
> > -static bool
> > -pkt_burst_noisy_vnf(struct fwd_stream *fs)
> > +static uint16_t
> > +noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
> >   {
> >       const uint64_t freq_khz = rte_get_timer_hz() / 1000;
> >       struct noisy_config *ncf = noisy_cfg[fs->rx_port];
> > -     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> >       struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
> >       uint16_t nb_deqd = 0;
> > -     uint16_t nb_rx = 0;
> >       uint16_t nb_tx = 0;
> >       uint16_t nb_enqd;
> >       unsigned int fifo_free;
> > @@ -126,12 +133,12 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
> >       bool needs_flush = false;
> >       uint64_t now;
> >
> > -     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> >       if (unlikely(nb_rx == 0))
> >               goto flush;
> >
> >       if (!ncf->do_buffering) {
> > -             sim_memory_lookups(ncf, nb_rx);
> > +             if (ncf->do_sim)
> > +                     sim_memory_lookups(ncf, nb_rx);
> >               nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
> >               goto end;
> >       }
> > @@ -169,11 +176,61 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
> >               ncf->prev_time = rte_get_timer_cycles();
> >       }
> >   end:
> > +     return nb_tx;
> > +}
> > +
> > +static bool
> > +pkt_burst_io(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx;
> > +     uint16_t nb_tx;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> >       return nb_rx > 0 || nb_tx > 0;
> >   }
> >
> > -#define NOISY_STRSIZE 256
> > -#define NOISY_RING "noisy_ring_%d\n"
> > +static bool
> > +pkt_burst_mac(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx;
> > +     uint16_t nb_tx;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>
> Similar to macfwd.c, you can add check for unlikely(nb_rx == 0) at this
> point in these fns.

That's true. I removed it because I'll have to call
noisy_eth_tx_burst() regardless, but we could avoid the middle call in
these locations.

I agree with the other suggestions.

Thanks,
M

>
> > +     do_macfwd(pkts_burst, nb_rx, fs);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> > +static bool
> > +pkt_burst_macswap(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx = 0;
> > +     uint16_t nb_tx = 0;
>
> nit: these are not assigned in the other functions
>
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> > +static bool
> > +pkt_brust_5tswap(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx = 0;
> > +     uint16_t nb_tx = 0;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     do_5tswap(pkts_burst, nb_rx, fs);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> >
> >   static void
> >   noisy_fwd_end(portid_t pi)
> > @@ -226,6 +283,15 @@ noisy_fwd_begin(portid_t pi)
> >                        "--noisy-lkup-memory-size must be > 0\n");
> >       }
> >
> > +     if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_io;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_mac;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
> > +             noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
> > +
> >       return 0;
> >   }
> >
> > @@ -233,6 +299,6 @@ struct fwd_engine noisy_vnf_engine = {
> >       .fwd_mode_name  = "noisy",
> >       .port_fwd_begin = noisy_fwd_begin,
> >       .port_fwd_end   = noisy_fwd_end,
> > -     .stream_init    = common_fwd_stream_init,
> > -     .packet_fwd     = pkt_burst_noisy_vnf,
> > +     .stream_init    = common_fwd_stream_init,
> > +     .packet_fwd     = pkt_burst_io,
> >   };
> > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> > index 3b37809baf..129c55c0ad 100644
> > --- a/app/test-pmd/parameters.c
> > +++ b/app/test-pmd/parameters.c
> > @@ -196,6 +196,7 @@ usage(char* progname)
> >       printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
> >       printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
> >       printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
> > +     printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
> >       printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
> >              "valid only with --mp-alloc=anon\n");
> >       printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
> > @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
> >               { "noisy-lkup-num-writes",      1, 0, 0 },
> >               { "noisy-lkup-num-reads",       1, 0, 0 },
> >               { "noisy-lkup-num-reads-writes", 1, 0, 0 },
> > +             { "noisy-fwd-mode",             1, 0, 0 },
> >               { "no-iova-contig",             0, 0, 0 },
> >               { "rx-mq-mode",                 1, 0, 0 },
> >               { "record-core-cycles",         0, 0, 0 },
> > @@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
> >                                       rte_exit(EXIT_FAILURE,
> >                                                "noisy-lkup-num-reads-writes must be >= 0\n");
> >                       }
> > +                     if (!strcmp(lgopts[opt_idx].name,
> > +                                 "noisy-fwd-mode")) {
> > +                             if (!strcmp(optarg, "io"))
> > +                                     noisy_fwd_mode = NOISY_FWD_MODE_IO;
> > +                             else if (!strcmp(optarg, "mac"))
> > +                                     noisy_fwd_mode = NOISY_FWD_MODE_MAC;
> > +                             else if (!strcmp(optarg, "macswap"))
> > +                                     noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
> > +                             else if (!strcmp(optarg, "5tswap"))
> > +                                     noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
> > +                             else
> > +                                     rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
> > +                                              " must b a valid fwd mode\n",
>
> typo "be"
>
> I would specify "..must be a valid noisy-fwd-mode value" to avoid
> confusion with the full set of general fwd modes and easier for user to
> search them in docs.
>
> > +                                              optarg);
> > +                     }
> >                       if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
> >                               mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
> >
> > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> > index 5cb6f92523..92784873ff 100644
> > --- a/app/test-pmd/testpmd.c
> > +++ b/app/test-pmd/testpmd.c
> > @@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
> >    */
> >   uint64_t noisy_lkup_num_reads_writes;
> >
> > +/*
> > + * Configurable forwarding mode in VNF simulation.
> > + */
> > +int noisy_fwd_mode;
> > +
> >   /*
> >    * Receive Side Scaling (RSS) configuration.
> >    */
> > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> > index bdfbfd36d3..f70397ad26 100644
> > --- a/app/test-pmd/testpmd.h
> > +++ b/app/test-pmd/testpmd.h
> > @@ -116,6 +116,13 @@ enum {
> >       QUEUE_JOB_TYPE_ACTION_QUERY,
> >   };
> >
> > +enum {
> > +     NOISY_FWD_MODE_IO,
> > +     NOISY_FWD_MODE_MAC,
> > +     NOISY_FWD_MODE_MACSWAP,
> > +     NOISY_FWD_MODE_5TSWAP
> > +};
> > +
> >   /**
> >    * The data structure associated with RX and TX packet burst statistics
> >    * that are recorded for each forwarding stream.
> > @@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
> >   extern uint64_t noisy_lkup_num_writes;
> >   extern uint64_t noisy_lkup_num_reads;
> >   extern uint64_t noisy_lkup_num_reads_writes;
> > +extern int noisy_fwd_mode;
> >
> >   extern uint8_t dcb_config;
> >
> > diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
> > index 57b23241cf..fcca3e8921 100644
> > --- a/doc/guides/testpmd_app_ug/run_app.rst
> > +++ b/doc/guides/testpmd_app_ug/run_app.rst
> > @@ -519,6 +519,15 @@ The command line options are:
> >       Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
> >       Only available with the noisy forwarding mode. The default value is 0.
> >
> > +*   ``--noisy-fwd-mode=mode``
> > +
> > +    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
> > +
> > +       io (the default)
> > +       mac
> > +       macswap
> > +       5tswap
> > +
> >   *   ``--no-iova-contig``
> >
> >       Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] app/testpmd: expand noisy neighbour forward mode support
  2023-05-26 17:32   ` Mike Pattrick
@ 2023-06-01 16:23     ` Kevin Traynor
  2023-06-06 14:17       ` Ferruh Yigit
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Traynor @ 2023-06-01 16:23 UTC (permalink / raw)
  To: Mike Pattrick; +Cc: Aman Singh, Yuying Zhang, dev, Ferruh Yigit, David Marchand

On 26/05/2023 18:32, Mike Pattrick wrote:
> On Fri, May 26, 2023 at 11:34 AM Kevin Traynor <ktraynor@redhat.com> wrote:
>>
>> On 17/04/2023 19:55, Mike Pattrick wrote:
>>> Previously the noisy neighbour vnf simulation would only operate in io
>>> mode, forwarding packets as is. However, this limited the usefulness of
>>> noisy neighbour simulation.
>>>
>>> This feature has now been expanded to supporting mac, macswap, and
>>> 5tswap modes. To facilitate adding this support, some new header files
>>> were added.
>>>
>>
>> Hi Mike,
>>
>> I think it makes sense to allow these functionalities to be combined. It
>> does seem like that noisy neighbour shouldn't have been added as a
>> standalone fowarding option in the first place, as it's not mutually
>> exclusive with the other fwding modes. Now it's forcing a user to set a
>> fwding mode within a fwding mode to combine the functionality :/
>>
>> The approach is to allow the fwding modes to expose their forwarding
>> method so noisy can call them. Did you consider to expose the noisy
>> functionality and allow the other forwarding modes to call that when the
>> --noisy-* flags are set?
> 
> Personally I like this approach more, and that was the strategy I took
> with the previous version. However, that change didn't seem popular at
> the time.
> 
> http://patches.dpdk.org/project/dpdk/patch/20230126045516.176917-1-mkp@redhat.com/#157095
> 

Ok, interesting, I hadn't realised that. It doesn't apply anymore since 
David has restructured the fowarding engines, but i applied to older 
code and took a look.

I had been thinking to an expose a function to do the noisy processing 
(if any) like a do_noise() and then to return the packets to the 
original fowarding engine for tx, similar to what is done the opposite 
way around in v3. I can understand Aman's concerns about tx of pkts 
moved from the fwding engines to noisy fwd engine.

I think we can summarize like this (will use macswp as example)
v3
- fwding engines expose their processing (e.g. do_macswp)
- user enables by setting --fwd=noisy and --noisy-fwd-mode=macswp
- noisy vnf does rx and tx
- noisy calls other fwding engine for other mode processing
- backwards compatible as existing noisy params have no effect when 
fwd!=noisy

v2
- noisy engine exposes a function for noise+tx
(e.g. noisy_eth_tx_burst())
- other fwd engines call this to add noise and tx
- user enables by setting --fwd=macswp and setting existing noisy params
- breaks backwards compatibility as previously noisy params would have 
no effect in macswp mode

It seems the ideal would be to have taken noisy as a feature, not a 
fwding engine but it's easy in hindsight. I'm not sure it's worth 
another big rework to try and add a do_noise() which may be a nice 
design but will break backwards compatability. So I'd probably vote for 
v3 design over v2.

What do others think ?

>> For example, a user sets fwding mode as normal 'fwd=macfwd' but then if
>> the user adds the --noisy-* params, the macfwd'ing mode calls some
>> functions exposed to add the noise, which seems a bit more intuitive.
>>
>> Also, if someone adds a new fwding mode, they can just call the noisy
>> functions and don't have update noisy fwding mode to add the new mode.
>>
>> I'm not sure if it's better, just throwing it out there as an
>> alternative idea.
>>
>> On the downside, it would break backwards compatibility because
>> previously those --noisy-* params would have had no effect with say
>> macfwd mode, but now they will. So maybe that's enough to prohibit it.
>>
>> In the past, I would have had all the params set and just changed
>> fwdmode to enable/disable noisy vnf. That would behaviour would now be
>> changed with this approach.
>>
>> What do you think?
>>
>> Few comments on the code below.
>>
>> thanks,
>> Kevin.
>>
>>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>>> ---
>>> v2: Reverted changes to random memory lookup
>>> v3: Refactored entire patch
>>> ---
>>>    app/test-pmd/5tswap.c                 | 118 +----------------------
>>>    app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
>>>    app/test-pmd/macfwd.c                 |  33 +------
>>>    app/test-pmd/macfwd.h                 |  46 +++++++++
>>>    app/test-pmd/noisy_vnf.c              |  92 +++++++++++++++---
>>>    app/test-pmd/parameters.c             |  17 ++++
>>>    app/test-pmd/testpmd.c                |   5 +
>>>    app/test-pmd/testpmd.h                |   8 ++
>>>    doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>>>    9 files changed, 299 insertions(+), 159 deletions(-)
>>>    create mode 100644 app/test-pmd/5tswap.h
>>>    create mode 100644 app/test-pmd/macfwd.h
>>>
>>> diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
>>> index ff8c2dcde5..8e8de2557a 100644
>>> --- a/app/test-pmd/5tswap.c
>>> +++ b/app/test-pmd/5tswap.c
>>> @@ -17,64 +17,8 @@
>>>    #include <rte_ip.h>
>>>    #include <rte_flow.h>
>>>
>>> -#include "macswap_common.h"
>>>    #include "testpmd.h"
>>> -
>>> -
>>> -static inline void
>>> -swap_mac(struct rte_ether_hdr *eth_hdr)
>>> -{
>>> -     struct rte_ether_addr addr;
>>> -
>>> -     /* Swap dest and src mac addresses. */
>>> -     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
>>> -     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
>>> -     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
>>> -}
>>> -
>>> -static inline void
>>> -swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
>>> -{
>>> -     rte_be32_t addr;
>>> -
>>> -     /* Swap dest and src ipv4 addresses. */
>>> -     addr = ipv4_hdr->src_addr;
>>> -     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
>>> -     ipv4_hdr->dst_addr = addr;
>>> -}
>>> -
>>> -static inline void
>>> -swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
>>> -{
>>> -     uint8_t addr[16];
>>> -
>>> -     /* Swap dest and src ipv6 addresses. */
>>> -     memcpy(&addr, &ipv6_hdr->src_addr, 16);
>>> -     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
>>> -     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
>>> -}
>>> -
>>> -static inline void
>>> -swap_tcp(struct rte_tcp_hdr *tcp_hdr)
>>> -{
>>> -     rte_be16_t port;
>>> -
>>> -     /* Swap dest and src tcp port. */
>>> -     port = tcp_hdr->src_port;
>>> -     tcp_hdr->src_port = tcp_hdr->dst_port;
>>> -     tcp_hdr->dst_port = port;
>>> -}
>>> -
>>> -static inline void
>>> -swap_udp(struct rte_udp_hdr *udp_hdr)
>>> -{
>>> -     rte_be16_t port;
>>> -
>>> -     /* Swap dest and src udp port */
>>> -     port = udp_hdr->src_port;
>>> -     udp_hdr->src_port = udp_hdr->dst_port;
>>> -     udp_hdr->dst_port = port;
>>> -}
>>> +#include "5tswap.h"
>>>
>>>    /*
>>>     * 5 tuple swap forwarding mode: Swap the source and the destination of layers
>>> @@ -85,22 +29,7 @@ static bool
>>>    pkt_burst_5tuple_swap(struct fwd_stream *fs)
>>>    {
>>>        struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>> -     struct rte_port  *txp;
>>> -     struct rte_mbuf *mb;
>>> -     uint16_t next_proto;
>>> -     uint64_t ol_flags;
>>> -     uint16_t proto;
>>>        uint16_t nb_rx;
>>> -     int i;
>>> -     union {
>>> -             struct rte_ether_hdr *eth;
>>> -             struct rte_vlan_hdr *vlan;
>>> -             struct rte_ipv4_hdr *ipv4;
>>> -             struct rte_ipv6_hdr *ipv6;
>>> -             struct rte_tcp_hdr *tcp;
>>> -             struct rte_udp_hdr *udp;
>>> -             uint8_t *byte;
>>> -     } h;
>>>
>>>        /*
>>>         * Receive a burst of packets and forward them.
>>> @@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
>>>        if (unlikely(nb_rx == 0))
>>>                return false;
>>>
>>> -     txp = &ports[fs->tx_port];
>>> -     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
>>> -     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
>>> -                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
>>> -     for (i = 0; i < nb_rx; i++) {
>>> -             if (likely(i < nb_rx - 1))
>>> -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
>>> -                                     void *));
>>> -             mb = pkts_burst[i];
>>> -             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>> -             proto = h.eth->ether_type;
>>> -             swap_mac(h.eth);
>>> -             mb->l2_len = sizeof(struct rte_ether_hdr);
>>> -             h.eth++;
>>> -             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
>>> -                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
>>> -                     proto = h.vlan->eth_proto;
>>> -                     h.vlan++;
>>> -                     mb->l2_len += sizeof(struct rte_vlan_hdr);
>>> -             }
>>> -             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
>>> -                     swap_ipv4(h.ipv4);
>>> -                     next_proto = h.ipv4->next_proto_id;
>>> -                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
>>> -                     h.byte += mb->l3_len;
>>> -             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
>>> -                     swap_ipv6(h.ipv6);
>>> -                     next_proto = h.ipv6->proto;
>>> -                     h.ipv6++;
>>> -                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
>>> -             } else {
>>> -                     mbuf_field_set(mb, ol_flags);
>>> -                     continue;
>>> -             }
>>> -             if (next_proto == IPPROTO_UDP) {
>>> -                     swap_udp(h.udp);
>>> -                     mb->l4_len = sizeof(struct rte_udp_hdr);
>>> -             } else if (next_proto == IPPROTO_TCP) {
>>> -                     swap_tcp(h.tcp);
>>> -                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
>>> -             }
>>> -             mbuf_field_set(mb, ol_flags);
>>> -     }
>>> +     do_5tswap(pkts_burst, nb_rx, fs);
>>> +
>>
>> this simplification is nice.
>>
>>>        common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>>>
>>>        return true;
>>> diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
>>> new file mode 100644
>>> index 0000000000..48da9236dc
>>> --- /dev/null
>>> +++ b/app/test-pmd/5tswap.h
>>> @@ -0,0 +1,130 @@
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(c) 2018 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _5TSWAP_H_
>>> +#define _5TSWAP_H_
>>> +
>>> +#include "macswap_common.h"
>>> +
>>> +static inline void
>>> +swap_mac(struct rte_ether_hdr *eth_hdr)
>>> +{
>>> +     struct rte_ether_addr addr;
>>> +
>>> +     /* Swap dest and src mac addresses. */
>>> +     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
>>> +     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
>>> +     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
>>> +}
>>> +
>>> +static inline void
>>> +swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
>>> +{
>>> +     rte_be32_t addr;
>>> +
>>> +     /* Swap dest and src ipv4 addresses. */
>>> +     addr = ipv4_hdr->src_addr;
>>> +     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
>>> +     ipv4_hdr->dst_addr = addr;
>>> +}
>>> +
>>> +static inline void
>>> +swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
>>> +{
>>> +     uint8_t addr[16];
>>> +
>>> +     /* Swap dest and src ipv6 addresses. */
>>> +     memcpy(&addr, &ipv6_hdr->src_addr, 16);
>>> +     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
>>> +     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
>>> +}
>>> +
>>> +static inline void
>>> +swap_tcp(struct rte_tcp_hdr *tcp_hdr)
>>> +{
>>> +     rte_be16_t port;
>>> +
>>> +     /* Swap dest and src tcp port. */
>>> +     port = tcp_hdr->src_port;
>>> +     tcp_hdr->src_port = tcp_hdr->dst_port;
>>> +     tcp_hdr->dst_port = port;
>>> +}
>>> +
>>> +static inline void
>>> +swap_udp(struct rte_udp_hdr *udp_hdr)
>>> +{
>>> +     rte_be16_t port;
>>> +
>>> +     /* Swap dest and src udp port */
>>> +     port = udp_hdr->src_port;
>>> +     udp_hdr->src_port = udp_hdr->dst_port;
>>> +     udp_hdr->dst_port = port;
>>> +}
>>> +
>>> +static inline void
>>> +do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
>>> +               struct fwd_stream *fs)
>>> +{
>>> +     struct rte_port  *txp;
>>> +     struct rte_mbuf *mb;
>>> +     uint16_t next_proto;
>>> +     uint64_t ol_flags;
>>> +     uint16_t proto;
>>> +     int i;
>>> +     union {
>>> +             struct rte_ether_hdr *eth;
>>> +             struct rte_vlan_hdr *vlan;
>>> +             struct rte_ipv4_hdr *ipv4;
>>> +             struct rte_ipv6_hdr *ipv6;
>>> +             struct rte_tcp_hdr *tcp;
>>> +             struct rte_udp_hdr *udp;
>>> +             uint8_t *byte;
>>> +     } h;
>>> +
>>> +     txp = &ports[fs->tx_port];
>>> +     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
>>> +     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
>>> +                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
>>> +     for (i = 0; i < nb_rx; i++) {
>>> +             if (likely(i < nb_rx - 1))
>>> +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
>>> +                                     void *));
>>> +             mb = pkts_burst[i];
>>> +             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>> +             proto = h.eth->ether_type;
>>> +             swap_mac(h.eth);
>>> +             mb->l2_len = sizeof(struct rte_ether_hdr);
>>> +             h.eth++;
>>> +             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
>>> +                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
>>> +                     proto = h.vlan->eth_proto;
>>> +                     h.vlan++;
>>> +                     mb->l2_len += sizeof(struct rte_vlan_hdr);
>>> +             }
>>> +             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
>>> +                     swap_ipv4(h.ipv4);
>>> +                     next_proto = h.ipv4->next_proto_id;
>>> +                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
>>> +                     h.byte += mb->l3_len;
>>> +             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
>>> +                     swap_ipv6(h.ipv6);
>>> +                     next_proto = h.ipv6->proto;
>>> +                     h.ipv6++;
>>> +                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
>>> +             } else {
>>> +                     mbuf_field_set(mb, ol_flags);
>>> +                     continue;
>>> +             }
>>> +             if (next_proto == IPPROTO_UDP) {
>>> +                     swap_udp(h.udp);
>>> +                     mb->l4_len = sizeof(struct rte_udp_hdr);
>>> +             } else if (next_proto == IPPROTO_TCP) {
>>> +                     swap_tcp(h.tcp);
>>> +                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
>>> +             }
>>> +             mbuf_field_set(mb, ol_flags);
>>> +     }
>>> +}
>>> +
>>> +#endif /* _5TSWAP_H_ */
>>> diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
>>> index 7316d73315..d19ace7395 100644
>>> --- a/app/test-pmd/macfwd.c
>>> +++ b/app/test-pmd/macfwd.c
>>> @@ -35,6 +35,7 @@
>>>    #include <rte_flow.h>
>>>
>>>    #include "testpmd.h"
>>> +#include "macfwd.h"
>>>
>>>    /*
>>>     * Forwarding of packets in MAC mode.
>>> @@ -45,13 +46,7 @@ static bool
>>>    pkt_burst_mac_forward(struct fwd_stream *fs)
>>>    {
>>>        struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>> -     struct rte_port  *txp;
>>> -     struct rte_mbuf  *mb;
>>> -     struct rte_ether_hdr *eth_hdr;
>>>        uint16_t nb_rx;
>>> -     uint16_t i;
>>> -     uint64_t ol_flags = 0;
>>> -     uint64_t tx_offloads;
>>>
>>>        /*
>>>         * Receive a burst of packets and forward them.
>>> @@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
>>>        if (unlikely(nb_rx == 0))
>>>                return false;
>>>
>>> -     txp = &ports[fs->tx_port];
>>> -     tx_offloads = txp->dev_conf.txmode.offloads;
>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
>>> -             ol_flags = RTE_MBUF_F_TX_VLAN;
>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
>>> -             ol_flags |= RTE_MBUF_F_TX_QINQ;
>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
>>> -             ol_flags |= RTE_MBUF_F_TX_MACSEC;
>>> -     for (i = 0; i < nb_rx; i++) {
>>> -             if (likely(i < nb_rx - 1))
>>> -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
>>> -                                                    void *));
>>> -             mb = pkts_burst[i];
>>> -             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>> -             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
>>> -                             &eth_hdr->dst_addr);
>>> -             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
>>> -                             &eth_hdr->src_addr);
>>> -             mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
>>> -             mb->ol_flags |= ol_flags;
>>> -             mb->l2_len = sizeof(struct rte_ether_hdr);
>>> -             mb->l3_len = sizeof(struct rte_ipv4_hdr);
>>> -             mb->vlan_tci = txp->tx_vlan_id;
>>> -             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
>>> -     }
>>> +     do_macfwd(pkts_burst, nb_rx, fs);
>>>
>>>        common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>>>
>>> diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
>>> new file mode 100644
>>> index 0000000000..3f3e7189e1
>>> --- /dev/null
>>> +++ b/app/test-pmd/macfwd.h
>>> @@ -0,0 +1,46 @@
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(c) 2018 Intel Corporation
>>> + */
>>> +
>>> +#ifndef _MACFWD_H_
>>> +#define _MACFWD_H_
>>> +
>>> +static inline void
>>> +do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
>>> +               struct fwd_stream *fs)
>>
>> nit: indent/alignment is a little off here. There is some extra spaces.
>> Same with other do_*()
>>
>>> +{
>>> +     struct rte_ether_hdr *eth_hdr;
>>> +     uint64_t ol_flags = 0;
>>> +     uint64_t tx_offloads;
>>> +     struct rte_mbuf  *mb;
>>> +     struct rte_port *txp = &ports[fs->tx_port];
>>> +     uint16_t i;
>>> +
>>> +
>>
>> can remove addition blank line
>>
>>> +     tx_offloads = txp->dev_conf.txmode.offloads;
>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
>>> +             ol_flags = RTE_MBUF_F_TX_VLAN;
>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
>>> +             ol_flags |= RTE_MBUF_F_TX_QINQ;
>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
>>> +             ol_flags |= RTE_MBUF_F_TX_MACSEC;
>>> +     for (i = 0; i < nb_rx; i++) {
>>> +             if (likely(i < nb_rx - 1))
>>> +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
>>> +                                                    void *));
>>> +             mb = pkts_burst[i];
>>> +             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>> +             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
>>> +                             &eth_hdr->dst_addr);
>>> +             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
>>> +                             &eth_hdr->src_addr);
>>> +             mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
>>> +             mb->ol_flags |= ol_flags;
>>> +             mb->l2_len = sizeof(struct rte_ether_hdr);
>>> +             mb->l3_len = sizeof(struct rte_ipv4_hdr);
>>> +             mb->vlan_tci = txp->tx_vlan_id;
>>> +             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
>>> +     }
>>> +}
>>> +
>>> +#endif /* _MACFWD_H_ */
>>> diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
>>> index 2bf90a983c..1d5a2e470a 100644
>>> --- a/app/test-pmd/noisy_vnf.c
>>> +++ b/app/test-pmd/noisy_vnf.c
>>> @@ -32,6 +32,18 @@
>>>    #include <rte_malloc.h>
>>>
>>>    #include "testpmd.h"
>>> +#include "5tswap.h"
>>> +#include "macfwd.h"
>>> +#if defined(RTE_ARCH_X86)
>>> +#include "macswap_sse.h"
>>> +#elif defined(__ARM_NEON)
>>> +#include "macswap_neon.h"
>>> +#else
>>> +#include "macswap.h"
>>> +#endif
>>> +
>>> +#define NOISY_STRSIZE 256
>>> +#define NOISY_RING "noisy_ring_%d\n"
>>>
>>>    struct noisy_config {
>>>        struct rte_ring *f;
>>> @@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>>>    {
>>>        uint16_t i, j;
>>>
>>> -     if (!ncf->do_sim)
>>> -             return;
>>> -
>>
>> Why is this removed? It's not checked before all calls to this function
>>
>>>        for (i = 0; i < nb_pkts; i++) {
>>>                for (j = 0; j < noisy_lkup_num_writes; j++)
>>>                        do_write(ncf->vnf_mem);
>>> @@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>>>     *    out of the FIFO
>>>     * 4. Cases 2 and 3 combined
>>>     */
>>> -static bool
>>> -pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>> +static uint16_t
>>> +noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
>>>    {
>>>        const uint64_t freq_khz = rte_get_timer_hz() / 1000;
>>>        struct noisy_config *ncf = noisy_cfg[fs->rx_port];
>>> -     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>>        struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
>>>        uint16_t nb_deqd = 0;
>>> -     uint16_t nb_rx = 0;
>>>        uint16_t nb_tx = 0;
>>>        uint16_t nb_enqd;
>>>        unsigned int fifo_free;
>>> @@ -126,12 +133,12 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>>        bool needs_flush = false;
>>>        uint64_t now;
>>>
>>> -     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>>        if (unlikely(nb_rx == 0))
>>>                goto flush;
>>>
>>>        if (!ncf->do_buffering) {
>>> -             sim_memory_lookups(ncf, nb_rx);
>>> +             if (ncf->do_sim)
>>> +                     sim_memory_lookups(ncf, nb_rx);
>>>                nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>>>                goto end;
>>>        }
>>> @@ -169,11 +176,61 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>>                ncf->prev_time = rte_get_timer_cycles();
>>>        }
>>>    end:
>>> +     return nb_tx;
>>> +}
>>> +
>>> +static bool
>>> +pkt_burst_io(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx;
>>> +     uint16_t nb_tx;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>>        return nb_rx > 0 || nb_tx > 0;
>>>    }
>>>
>>> -#define NOISY_STRSIZE 256
>>> -#define NOISY_RING "noisy_ring_%d\n"
>>> +static bool
>>> +pkt_burst_mac(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx;
>>> +     uint16_t nb_tx;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>
>> Similar to macfwd.c, you can add check for unlikely(nb_rx == 0) at this
>> point in these fns.
> 
> That's true. I removed it because I'll have to call
> noisy_eth_tx_burst() regardless, but we could avoid the middle call in
> these locations.
> 
> I agree with the other suggestions.
> 
> Thanks,
> M
> 
>>
>>> +     do_macfwd(pkts_burst, nb_rx, fs);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>> +static bool
>>> +pkt_burst_macswap(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx = 0;
>>> +     uint16_t nb_tx = 0;
>>
>> nit: these are not assigned in the other functions
>>
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>> +static bool
>>> +pkt_brust_5tswap(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx = 0;
>>> +     uint16_t nb_tx = 0;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     do_5tswap(pkts_burst, nb_rx, fs);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>>
>>>    static void
>>>    noisy_fwd_end(portid_t pi)
>>> @@ -226,6 +283,15 @@ noisy_fwd_begin(portid_t pi)
>>>                         "--noisy-lkup-memory-size must be > 0\n");
>>>        }
>>>
>>> +     if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_io;
>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_mac;
>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
>>> +             noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
>>> +
>>>        return 0;
>>>    }
>>>
>>> @@ -233,6 +299,6 @@ struct fwd_engine noisy_vnf_engine = {
>>>        .fwd_mode_name  = "noisy",
>>>        .port_fwd_begin = noisy_fwd_begin,
>>>        .port_fwd_end   = noisy_fwd_end,
>>> -     .stream_init    = common_fwd_stream_init,
>>> -     .packet_fwd     = pkt_burst_noisy_vnf,
>>> +     .stream_init    = common_fwd_stream_init,
>>> +     .packet_fwd     = pkt_burst_io,
>>>    };
>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>> index 3b37809baf..129c55c0ad 100644
>>> --- a/app/test-pmd/parameters.c
>>> +++ b/app/test-pmd/parameters.c
>>> @@ -196,6 +196,7 @@ usage(char* progname)
>>>        printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
>>>        printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
>>>        printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
>>> +     printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
>>>        printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
>>>               "valid only with --mp-alloc=anon\n");
>>>        printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
>>> @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
>>>                { "noisy-lkup-num-writes",      1, 0, 0 },
>>>                { "noisy-lkup-num-reads",       1, 0, 0 },
>>>                { "noisy-lkup-num-reads-writes", 1, 0, 0 },
>>> +             { "noisy-fwd-mode",             1, 0, 0 },
>>>                { "no-iova-contig",             0, 0, 0 },
>>>                { "rx-mq-mode",                 1, 0, 0 },
>>>                { "record-core-cycles",         0, 0, 0 },
>>> @@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
>>>                                        rte_exit(EXIT_FAILURE,
>>>                                                 "noisy-lkup-num-reads-writes must be >= 0\n");
>>>                        }
>>> +                     if (!strcmp(lgopts[opt_idx].name,
>>> +                                 "noisy-fwd-mode")) {
>>> +                             if (!strcmp(optarg, "io"))
>>> +                                     noisy_fwd_mode = NOISY_FWD_MODE_IO;
>>> +                             else if (!strcmp(optarg, "mac"))
>>> +                                     noisy_fwd_mode = NOISY_FWD_MODE_MAC;
>>> +                             else if (!strcmp(optarg, "macswap"))
>>> +                                     noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
>>> +                             else if (!strcmp(optarg, "5tswap"))
>>> +                                     noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
>>> +                             else
>>> +                                     rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
>>> +                                              " must b a valid fwd mode\n",
>>
>> typo "be"
>>
>> I would specify "..must be a valid noisy-fwd-mode value" to avoid
>> confusion with the full set of general fwd modes and easier for user to
>> search them in docs.
>>
>>> +                                              optarg);
>>> +                     }
>>>                        if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
>>>                                mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
>>>
>>> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
>>> index 5cb6f92523..92784873ff 100644
>>> --- a/app/test-pmd/testpmd.c
>>> +++ b/app/test-pmd/testpmd.c
>>> @@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
>>>     */
>>>    uint64_t noisy_lkup_num_reads_writes;
>>>
>>> +/*
>>> + * Configurable forwarding mode in VNF simulation.
>>> + */
>>> +int noisy_fwd_mode;
>>> +
>>>    /*
>>>     * Receive Side Scaling (RSS) configuration.
>>>     */
>>> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
>>> index bdfbfd36d3..f70397ad26 100644
>>> --- a/app/test-pmd/testpmd.h
>>> +++ b/app/test-pmd/testpmd.h
>>> @@ -116,6 +116,13 @@ enum {
>>>        QUEUE_JOB_TYPE_ACTION_QUERY,
>>>    };
>>>
>>> +enum {
>>> +     NOISY_FWD_MODE_IO,
>>> +     NOISY_FWD_MODE_MAC,
>>> +     NOISY_FWD_MODE_MACSWAP,
>>> +     NOISY_FWD_MODE_5TSWAP
>>> +};
>>> +
>>>    /**
>>>     * The data structure associated with RX and TX packet burst statistics
>>>     * that are recorded for each forwarding stream.
>>> @@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
>>>    extern uint64_t noisy_lkup_num_writes;
>>>    extern uint64_t noisy_lkup_num_reads;
>>>    extern uint64_t noisy_lkup_num_reads_writes;
>>> +extern int noisy_fwd_mode;
>>>
>>>    extern uint8_t dcb_config;
>>>
>>> diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
>>> index 57b23241cf..fcca3e8921 100644
>>> --- a/doc/guides/testpmd_app_ug/run_app.rst
>>> +++ b/doc/guides/testpmd_app_ug/run_app.rst
>>> @@ -519,6 +519,15 @@ The command line options are:
>>>        Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
>>>        Only available with the noisy forwarding mode. The default value is 0.
>>>
>>> +*   ``--noisy-fwd-mode=mode``
>>> +
>>> +    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
>>> +
>>> +       io (the default)
>>> +       mac
>>> +       macswap
>>> +       5tswap
>>> +
>>>    *   ``--no-iova-contig``
>>>
>>>        Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.
>>
> 


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v4] app/testpmd: expand noisy neighbour forward mode support
  2023-04-17 18:55 [PATCH v3] app/testpmd: expand noisy neighbour forward mode support Mike Pattrick
  2023-05-26 15:34 ` Kevin Traynor
@ 2023-06-02 18:29 ` Mike Pattrick
  2023-06-06 14:27   ` Ferruh Yigit
  2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
  1 sibling, 2 replies; 18+ messages in thread
From: Mike Pattrick @ 2023-06-02 18:29 UTC (permalink / raw)
  To: Aman Singh, Yuying Zhang, Ruifeng Wang, Bruce Richardson,
	Konstantin Ananyev
  Cc: ktraynor, dev, Mike Pattrick

Previously the noisy neighbour vnf simulation would only operate in io
mode, forwarding packets as is. However, this limited the usefulness of
noisy neighbour simulation.

This feature has now been expanded to supporting mac, macswap, and
5tswap modes. To facilitate adding this support, some new header files
were added.

Signed-off-by: Mike Pattrick <mkp@redhat.com>
 ---
 v2: Reverted changes to random memory lookup
 v3: Refactored entire patch
 v4: Implemented recommended formatting changes
---
 app/test-pmd/5tswap.c                 | 118 +----------------------
 app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
 app/test-pmd/macfwd.c                 |  33 +------
 app/test-pmd/macfwd.h                 |  45 +++++++++
 app/test-pmd/macswap.h                |   2 +-
 app/test-pmd/macswap_neon.h           |   2 +-
 app/test-pmd/macswap_sse.h            |   4 +-
 app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
 app/test-pmd/parameters.c             |  17 ++++
 app/test-pmd/testpmd.c                |   5 +
 app/test-pmd/testpmd.h                |   8 ++
 doc/guides/testpmd_app_ug/run_app.rst |   9 ++
 12 files changed, 313 insertions(+), 166 deletions(-)
 create mode 100644 app/test-pmd/5tswap.h
 create mode 100644 app/test-pmd/macfwd.h

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index ff8c2dcde5..8e8de2557a 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -17,64 +17,8 @@
 #include <rte_ip.h>
 #include <rte_flow.h>
 
-#include "macswap_common.h"
 #include "testpmd.h"
-
-
-static inline void
-swap_mac(struct rte_ether_hdr *eth_hdr)
-{
-	struct rte_ether_addr addr;
-
-	/* Swap dest and src mac addresses. */
-	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
-	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
-	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
-}
-
-static inline void
-swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
-{
-	rte_be32_t addr;
-
-	/* Swap dest and src ipv4 addresses. */
-	addr = ipv4_hdr->src_addr;
-	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
-	ipv4_hdr->dst_addr = addr;
-}
-
-static inline void
-swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
-{
-	uint8_t addr[16];
-
-	/* Swap dest and src ipv6 addresses. */
-	memcpy(&addr, &ipv6_hdr->src_addr, 16);
-	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
-	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
-}
-
-static inline void
-swap_tcp(struct rte_tcp_hdr *tcp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src tcp port. */
-	port = tcp_hdr->src_port;
-	tcp_hdr->src_port = tcp_hdr->dst_port;
-	tcp_hdr->dst_port = port;
-}
-
-static inline void
-swap_udp(struct rte_udp_hdr *udp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src udp port */
-	port = udp_hdr->src_port;
-	udp_hdr->src_port = udp_hdr->dst_port;
-	udp_hdr->dst_port = port;
-}
+#include "5tswap.h"
 
 /*
  * 5 tuple swap forwarding mode: Swap the source and the destination of layers
@@ -85,22 +29,7 @@ static bool
 pkt_burst_5tuple_swap(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf *mb;
-	uint16_t next_proto;
-	uint64_t ol_flags;
-	uint16_t proto;
 	uint16_t nb_rx;
-	int i;
-	union {
-		struct rte_ether_hdr *eth;
-		struct rte_vlan_hdr *vlan;
-		struct rte_ipv4_hdr *ipv4;
-		struct rte_ipv6_hdr *ipv6;
-		struct rte_tcp_hdr *tcp;
-		struct rte_udp_hdr *udp;
-		uint8_t *byte;
-	} h;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
-	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
-					void *));
-		mb = pkts_burst[i];
-		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		proto = h.eth->ether_type;
-		swap_mac(h.eth);
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		h.eth++;
-		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			proto = h.vlan->eth_proto;
-			h.vlan++;
-			mb->l2_len += sizeof(struct rte_vlan_hdr);
-		}
-		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
-			swap_ipv4(h.ipv4);
-			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
-			h.byte += mb->l3_len;
-		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
-			swap_ipv6(h.ipv6);
-			next_proto = h.ipv6->proto;
-			h.ipv6++;
-			mb->l3_len = sizeof(struct rte_ipv6_hdr);
-		} else {
-			mbuf_field_set(mb, ol_flags);
-			continue;
-		}
-		if (next_proto == IPPROTO_UDP) {
-			swap_udp(h.udp);
-			mb->l4_len = sizeof(struct rte_udp_hdr);
-		} else if (next_proto == IPPROTO_TCP) {
-			swap_tcp(h.tcp);
-			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
-		}
-		mbuf_field_set(mb, ol_flags);
-	}
+	do_5tswap(pkts_burst, nb_rx, fs);
+
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
 	return true;
diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
new file mode 100644
index 0000000000..974af1aacd
--- /dev/null
+++ b/app/test-pmd/5tswap.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _5TSWAP_H_
+#define _5TSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+swap_mac(struct rte_ether_hdr *eth_hdr)
+{
+	struct rte_ether_addr addr;
+
+	/* Swap dest and src mac addresses. */
+	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
+	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
+	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
+}
+
+static inline void
+swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
+{
+	rte_be32_t addr;
+
+	/* Swap dest and src ipv4 addresses. */
+	addr = ipv4_hdr->src_addr;
+	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
+	ipv4_hdr->dst_addr = addr;
+}
+
+static inline void
+swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
+{
+	uint8_t addr[16];
+
+	/* Swap dest and src ipv6 addresses. */
+	memcpy(&addr, &ipv6_hdr->src_addr, 16);
+	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
+	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
+}
+
+static inline void
+swap_tcp(struct rte_tcp_hdr *tcp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src tcp port. */
+	port = tcp_hdr->src_port;
+	tcp_hdr->src_port = tcp_hdr->dst_port;
+	tcp_hdr->dst_port = port;
+}
+
+static inline void
+swap_udp(struct rte_udp_hdr *udp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src udp port */
+	port = udp_hdr->src_port;
+	udp_hdr->src_port = udp_hdr->dst_port;
+	udp_hdr->dst_port = port;
+}
+
+static inline void
+do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_port  *txp;
+	struct rte_mbuf *mb;
+	uint16_t next_proto;
+	uint64_t ol_flags;
+	uint16_t proto;
+	int i;
+	union {
+		struct rte_ether_hdr *eth;
+		struct rte_vlan_hdr *vlan;
+		struct rte_ipv4_hdr *ipv4;
+		struct rte_ipv6_hdr *ipv6;
+		struct rte_tcp_hdr *tcp;
+		struct rte_udp_hdr *udp;
+		uint8_t *byte;
+	} h;
+
+	txp = &ports[fs->tx_port];
+	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
+		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
+						       void *));
+		mb = pkts_burst[i];
+		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		proto = h.eth->ether_type;
+		swap_mac(h.eth);
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		h.eth++;
+		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			proto = h.vlan->eth_proto;
+			h.vlan++;
+			mb->l2_len += sizeof(struct rte_vlan_hdr);
+		}
+		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
+			swap_ipv4(h.ipv4);
+			next_proto = h.ipv4->next_proto_id;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
+			h.byte += mb->l3_len;
+		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
+			swap_ipv6(h.ipv6);
+			next_proto = h.ipv6->proto;
+			h.ipv6++;
+			mb->l3_len = sizeof(struct rte_ipv6_hdr);
+		} else {
+			mbuf_field_set(mb, ol_flags);
+			continue;
+		}
+		if (next_proto == IPPROTO_UDP) {
+			swap_udp(h.udp);
+			mb->l4_len = sizeof(struct rte_udp_hdr);
+		} else if (next_proto == IPPROTO_TCP) {
+			swap_tcp(h.tcp);
+			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
+		}
+		mbuf_field_set(mb, ol_flags);
+	}
+}
+
+#endif /* _5TSWAP_H_ */
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index 7316d73315..d19ace7395 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -35,6 +35,7 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#include "macfwd.h"
 
 /*
  * Forwarding of packets in MAC mode.
@@ -45,13 +46,7 @@ static bool
 pkt_burst_mac_forward(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf  *mb;
-	struct rte_ether_hdr *eth_hdr;
 	uint16_t nb_rx;
-	uint16_t i;
-	uint64_t ol_flags = 0;
-	uint64_t tx_offloads;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	tx_offloads = txp->dev_conf.txmode.offloads;
-	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
-		ol_flags = RTE_MBUF_F_TX_VLAN;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_QINQ;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_MACSEC;
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
-						       void *));
-		mb = pkts_burst[i];
-		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
-				&eth_hdr->dst_addr);
-		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
-				&eth_hdr->src_addr);
-		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
-		mb->ol_flags |= ol_flags;
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		mb->l3_len = sizeof(struct rte_ipv4_hdr);
-		mb->vlan_tci = txp->tx_vlan_id;
-		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
-	}
+	do_macfwd(pkts_burst, nb_rx, fs);
 
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
new file mode 100644
index 0000000000..69d9dfc64f
--- /dev/null
+++ b/app/test-pmd/macfwd.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _MACFWD_H_
+#define _MACFWD_H_
+
+static inline void
+do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_ether_hdr *eth_hdr;
+	uint64_t ol_flags = 0;
+	uint64_t tx_offloads;
+	struct rte_mbuf  *mb;
+	struct rte_port *txp = &ports[fs->tx_port];
+	uint16_t i;
+
+	tx_offloads = txp->dev_conf.txmode.offloads;
+	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
+		ol_flags = RTE_MBUF_F_TX_VLAN;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_QINQ;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_MACSEC;
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+						       void *));
+		mb = pkts_burst[i];
+		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+				    &eth_hdr->dst_addr);
+		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+				    &eth_hdr->src_addr);
+		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
+		mb->ol_flags |= ol_flags;
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		mb->l3_len = sizeof(struct rte_ipv4_hdr);
+		mb->vlan_tci = txp->tx_vlan_id;
+		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+	}
+}
+
+#endif /* _MACFWD_H_ */
diff --git a/app/test-pmd/macswap.h b/app/test-pmd/macswap.h
index 29c252bb8f..7fea461e77 100644
--- a/app/test-pmd/macswap.h
+++ b/app/test-pmd/macswap.h
@@ -9,7 +9,7 @@
 
 static inline void
 do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
-		struct rte_port *txp)
+	   struct rte_port *txp)
 {
 	struct rte_ether_hdr *eth_hdr;
 	struct rte_mbuf *mb;
diff --git a/app/test-pmd/macswap_neon.h b/app/test-pmd/macswap_neon.h
index df6c260cd4..91d4cb7c2e 100644
--- a/app/test-pmd/macswap_neon.h
+++ b/app/test-pmd/macswap_neon.h
@@ -14,7 +14,7 @@
 
 static inline void
 do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
-		struct rte_port *txp)
+	   struct rte_port *txp)
 {
 	struct rte_ether_hdr *eth_hdr[4];
 	struct rte_mbuf *mb[4];
diff --git a/app/test-pmd/macswap_sse.h b/app/test-pmd/macswap_sse.h
index 223f87a539..e17cc07be0 100644
--- a/app/test-pmd/macswap_sse.h
+++ b/app/test-pmd/macswap_sse.h
@@ -9,7 +9,7 @@
 
 static inline void
 do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
-		struct rte_port *txp)
+	   struct rte_port *txp)
 {
 	struct rte_ether_hdr *eth_hdr[4];
 	struct rte_mbuf *mb[4];
@@ -29,7 +29,7 @@ do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
 
 	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
 	vlan_qinq_set(pkts, nb, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
+		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
 
 	i = 0;
 	r = nb;
diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
index 2bf90a983c..9b33930cab 100644
--- a/app/test-pmd/noisy_vnf.c
+++ b/app/test-pmd/noisy_vnf.c
@@ -32,6 +32,18 @@
 #include <rte_malloc.h>
 
 #include "testpmd.h"
+#include "5tswap.h"
+#include "macfwd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(__ARM_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
 
 struct noisy_config {
 	struct rte_ring *f;
@@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
 {
 	uint16_t i, j;
 
-	if (!ncf->do_sim)
-		return;
-
 	for (i = 0; i < nb_pkts; i++) {
 		for (j = 0; j < noisy_lkup_num_writes; j++)
 			do_write(ncf->vnf_mem);
@@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
  *    out of the FIFO
  * 4. Cases 2 and 3 combined
  */
-static bool
-pkt_burst_noisy_vnf(struct fwd_stream *fs)
+static uint16_t
+noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
 {
 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
 	uint16_t nb_deqd = 0;
-	uint16_t nb_rx = 0;
 	uint16_t nb_tx = 0;
 	uint16_t nb_enqd;
 	unsigned int fifo_free;
@@ -126,12 +133,16 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 	bool needs_flush = false;
 	uint64_t now;
 
-	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
-	if (unlikely(nb_rx == 0))
-		goto flush;
+	if (unlikely(nb_rx == 0)) {
+		if (!ncf->do_buffering)
+			goto end;
+		else
+			goto flush;
+	}
 
 	if (!ncf->do_buffering) {
-		sim_memory_lookups(ncf, nb_rx);
+		if (ncf->do_sim)
+			sim_memory_lookups(ncf, nb_rx);
 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 		goto end;
 	}
@@ -150,7 +161,8 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
 	}
 
-	sim_memory_lookups(ncf, nb_enqd);
+	if (ncf->do_sim)
+		sim_memory_lookups(ncf, nb_enqd);
 
 flush:
 	if (ncf->do_flush) {
@@ -169,11 +181,64 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 		ncf->prev_time = rte_get_timer_cycles();
 	}
 end:
+	return nb_tx;
+}
+
+static bool
+pkt_burst_io(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
 	return nb_rx > 0 || nb_tx > 0;
 }
 
-#define NOISY_STRSIZE 256
-#define NOISY_RING "noisy_ring_%d\n"
+static bool
+pkt_burst_mac(struct fwd_stream *fs)
+{
+	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macfwd(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_burst_macswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_brust_5tswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_5tswap(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
 
 static void
 noisy_fwd_end(portid_t pi)
@@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
 			 "--noisy-lkup-memory-size must be > 0\n");
 	}
 
+	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
+		noisy_vnf_engine.packet_fwd = pkt_burst_io;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
+		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
+
 	return 0;
 }
 
@@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
 	.fwd_mode_name  = "noisy",
 	.port_fwd_begin = noisy_fwd_begin,
 	.port_fwd_end   = noisy_fwd_end,
-	.stream_init    = common_fwd_stream_init,
-	.packet_fwd     = pkt_burst_noisy_vnf,
+	.stream_init	= common_fwd_stream_init,
+	.packet_fwd     = pkt_burst_io,
 };
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3b37809baf..551714cce4 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -196,6 +196,7 @@ usage(char* progname)
 	printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
 	printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
 	printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
+	printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
 	printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
 	       "valid only with --mp-alloc=anon\n");
 	printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
@@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
 		{ "noisy-lkup-num-writes",	1, 0, 0 },
 		{ "noisy-lkup-num-reads",	1, 0, 0 },
 		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
+		{ "noisy-fwd-mode",             1, 0, 0 },
 		{ "no-iova-contig",             0, 0, 0 },
 		{ "rx-mq-mode",                 1, 0, 0 },
 		{ "record-core-cycles",         0, 0, 0 },
@@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE,
 						 "noisy-lkup-num-reads-writes must be >= 0\n");
 			}
+			if (!strcmp(lgopts[opt_idx].name,
+				    "noisy-fwd-mode")) {
+				if (!strcmp(optarg, "io"))
+					noisy_fwd_mode = NOISY_FWD_MODE_IO;
+				else if (!strcmp(optarg, "mac"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MAC;
+				else if (!strcmp(optarg, "macswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
+				else if (!strcmp(optarg, "5tswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
+				else
+					rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
+						 " must be a valid noisy-fwd-mode value\n",
+						 optarg);
+			}
 			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
 				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
 
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5cb6f92523..92784873ff 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
  */
 uint64_t noisy_lkup_num_reads_writes;
 
+/*
+ * Configurable forwarding mode in VNF simulation.
+ */
+int noisy_fwd_mode;
+
 /*
  * Receive Side Scaling (RSS) configuration.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..f70397ad26 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -116,6 +116,13 @@ enum {
 	QUEUE_JOB_TYPE_ACTION_QUERY,
 };
 
+enum {
+	NOISY_FWD_MODE_IO,
+	NOISY_FWD_MODE_MAC,
+	NOISY_FWD_MODE_MACSWAP,
+	NOISY_FWD_MODE_5TSWAP
+};
+
 /**
  * The data structure associated with RX and TX packet burst statistics
  * that are recorded for each forwarding stream.
@@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
 extern uint64_t noisy_lkup_num_writes;
 extern uint64_t noisy_lkup_num_reads;
 extern uint64_t noisy_lkup_num_reads_writes;
+extern int noisy_fwd_mode;
 
 extern uint8_t dcb_config;
 
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index 57b23241cf..fcca3e8921 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -519,6 +519,15 @@ The command line options are:
     Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
     Only available with the noisy forwarding mode. The default value is 0.
 
+*   ``--noisy-fwd-mode=mode``
+
+    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
+
+       io (the default)
+       mac
+       macswap
+       5tswap
+
 *   ``--no-iova-contig``
 
     Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v3] app/testpmd: expand noisy neighbour forward mode support
  2023-06-01 16:23     ` Kevin Traynor
@ 2023-06-06 14:17       ` Ferruh Yigit
  0 siblings, 0 replies; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-06 14:17 UTC (permalink / raw)
  To: Kevin Traynor, Mike Pattrick
  Cc: Aman Singh, Yuying Zhang, dev, David Marchand

On 6/1/2023 5:23 PM, Kevin Traynor wrote:
> On 26/05/2023 18:32, Mike Pattrick wrote:
>> On Fri, May 26, 2023 at 11:34 AM Kevin Traynor <ktraynor@redhat.com>
>> wrote:
>>>
>>> On 17/04/2023 19:55, Mike Pattrick wrote:
>>>> Previously the noisy neighbour vnf simulation would only operate in io
>>>> mode, forwarding packets as is. However, this limited the usefulness of
>>>> noisy neighbour simulation.
>>>>
>>>> This feature has now been expanded to supporting mac, macswap, and
>>>> 5tswap modes. To facilitate adding this support, some new header files
>>>> were added.
>>>>
>>>
>>> Hi Mike,
>>>
>>> I think it makes sense to allow these functionalities to be combined. It
>>> does seem like that noisy neighbour shouldn't have been added as a
>>> standalone fowarding option in the first place, as it's not mutually
>>> exclusive with the other fwding modes. Now it's forcing a user to set a
>>> fwding mode within a fwding mode to combine the functionality :/
>>>
>>> The approach is to allow the fwding modes to expose their forwarding
>>> method so noisy can call them. Did you consider to expose the noisy
>>> functionality and allow the other forwarding modes to call that when the
>>> --noisy-* flags are set?
>>
>> Personally I like this approach more, and that was the strategy I took
>> with the previous version. However, that change didn't seem popular at
>> the time.
>>
>> http://patches.dpdk.org/project/dpdk/patch/20230126045516.176917-1-mkp@redhat.com/#157095
>>
> 
> Ok, interesting, I hadn't realised that. It doesn't apply anymore since
> David has restructured the fowarding engines, but i applied to older
> code and took a look.
> 
> I had been thinking to an expose a function to do the noisy processing
> (if any) like a do_noise() and then to return the packets to the
> original fowarding engine for tx, similar to what is done the opposite
> way around in v3. I can understand Aman's concerns about tx of pkts
> moved from the fwding engines to noisy fwd engine.
> 
> I think we can summarize like this (will use macswp as example)
> v3
> - fwding engines expose their processing (e.g. do_macswp)
> - user enables by setting --fwd=noisy and --noisy-fwd-mode=macswp
> - noisy vnf does rx and tx
> - noisy calls other fwding engine for other mode processing
> - backwards compatible as existing noisy params have no effect when
> fwd!=noisy
> 
> v2
> - noisy engine exposes a function for noise+tx
> (e.g. noisy_eth_tx_burst())
> - other fwd engines call this to add noise and tx
> - user enables by setting --fwd=macswp and setting existing noisy params
> - breaks backwards compatibility as previously noisy params would have
> no effect in macswp mode
> 
> It seems the ideal would be to have taken noisy as a feature, not a
> fwding engine but it's easy in hindsight. I'm not sure it's worth
> another big rework to try and add a do_noise() which may be a nice
> design but will break backwards compatability. So I'd probably vote for
> v3 design over v2.
> 
> What do others think ?
> 

Hi Kevin, Mike,

I think better to keep noisy neighbour forwarding mode separate.

testpmd forwarding modes are used a lot, and noisy neighbor impacts
forwarding, indeed that is the intension of the feature, right, but we
don't need this noise most of the times.
Other option can be embedding noisy neighbor into other forwarding
modes, but it will bring complexity to main usage of the other
forwarding modes.

Mike seems able to abstract the main function of the forwarding and use
it in both main forwarding function and noisy neighbour forwarding, this
looks good to me.


>>> For example, a user sets fwding mode as normal 'fwd=macfwd' but then if
>>> the user adds the --noisy-* params, the macfwd'ing mode calls some
>>> functions exposed to add the noise, which seems a bit more intuitive.
>>>
>>> Also, if someone adds a new fwding mode, they can just call the noisy
>>> functions and don't have update noisy fwding mode to add the new mode.
>>>
>>> I'm not sure if it's better, just throwing it out there as an
>>> alternative idea.
>>>
>>> On the downside, it would break backwards compatibility because
>>> previously those --noisy-* params would have had no effect with say
>>> macfwd mode, but now they will. So maybe that's enough to prohibit it.
>>>
>>> In the past, I would have had all the params set and just changed
>>> fwdmode to enable/disable noisy vnf. That would behaviour would now be
>>> changed with this approach.
>>>
>>> What do you think?
>>>
>>> Few comments on the code below.
>>>
>>> thanks,
>>> Kevin.
>>>
>>>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>>>> ---
>>>> v2: Reverted changes to random memory lookup
>>>> v3: Refactored entire patch
>>>> ---
>>>>    app/test-pmd/5tswap.c                 | 118 +----------------------
>>>>    app/test-pmd/5tswap.h                 | 130
>>>> ++++++++++++++++++++++++++
>>>>    app/test-pmd/macfwd.c                 |  33 +------
>>>>    app/test-pmd/macfwd.h                 |  46 +++++++++
>>>>    app/test-pmd/noisy_vnf.c              |  92 +++++++++++++++---
>>>>    app/test-pmd/parameters.c             |  17 ++++
>>>>    app/test-pmd/testpmd.c                |   5 +
>>>>    app/test-pmd/testpmd.h                |   8 ++
>>>>    doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>>>>    9 files changed, 299 insertions(+), 159 deletions(-)
>>>>    create mode 100644 app/test-pmd/5tswap.h
>>>>    create mode 100644 app/test-pmd/macfwd.h
>>>>
>>>> diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
>>>> index ff8c2dcde5..8e8de2557a 100644
>>>> --- a/app/test-pmd/5tswap.c
>>>> +++ b/app/test-pmd/5tswap.c
>>>> @@ -17,64 +17,8 @@
>>>>    #include <rte_ip.h>
>>>>    #include <rte_flow.h>
>>>>
>>>> -#include "macswap_common.h"
>>>>    #include "testpmd.h"
>>>> -
>>>> -
>>>> -static inline void
>>>> -swap_mac(struct rte_ether_hdr *eth_hdr)
>>>> -{
>>>> -     struct rte_ether_addr addr;
>>>> -
>>>> -     /* Swap dest and src mac addresses. */
>>>> -     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
>>>> -     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
>>>> -     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
>>>> -}
>>>> -
>>>> -static inline void
>>>> -swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
>>>> -{
>>>> -     rte_be32_t addr;
>>>> -
>>>> -     /* Swap dest and src ipv4 addresses. */
>>>> -     addr = ipv4_hdr->src_addr;
>>>> -     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
>>>> -     ipv4_hdr->dst_addr = addr;
>>>> -}
>>>> -
>>>> -static inline void
>>>> -swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
>>>> -{
>>>> -     uint8_t addr[16];
>>>> -
>>>> -     /* Swap dest and src ipv6 addresses. */
>>>> -     memcpy(&addr, &ipv6_hdr->src_addr, 16);
>>>> -     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
>>>> -     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
>>>> -}
>>>> -
>>>> -static inline void
>>>> -swap_tcp(struct rte_tcp_hdr *tcp_hdr)
>>>> -{
>>>> -     rte_be16_t port;
>>>> -
>>>> -     /* Swap dest and src tcp port. */
>>>> -     port = tcp_hdr->src_port;
>>>> -     tcp_hdr->src_port = tcp_hdr->dst_port;
>>>> -     tcp_hdr->dst_port = port;
>>>> -}
>>>> -
>>>> -static inline void
>>>> -swap_udp(struct rte_udp_hdr *udp_hdr)
>>>> -{
>>>> -     rte_be16_t port;
>>>> -
>>>> -     /* Swap dest and src udp port */
>>>> -     port = udp_hdr->src_port;
>>>> -     udp_hdr->src_port = udp_hdr->dst_port;
>>>> -     udp_hdr->dst_port = port;
>>>> -}
>>>> +#include "5tswap.h"
>>>>
>>>>    /*
>>>>     * 5 tuple swap forwarding mode: Swap the source and the
>>>> destination of layers
>>>> @@ -85,22 +29,7 @@ static bool
>>>>    pkt_burst_5tuple_swap(struct fwd_stream *fs)
>>>>    {
>>>>        struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>>> -     struct rte_port  *txp;
>>>> -     struct rte_mbuf *mb;
>>>> -     uint16_t next_proto;
>>>> -     uint64_t ol_flags;
>>>> -     uint16_t proto;
>>>>        uint16_t nb_rx;
>>>> -     int i;
>>>> -     union {
>>>> -             struct rte_ether_hdr *eth;
>>>> -             struct rte_vlan_hdr *vlan;
>>>> -             struct rte_ipv4_hdr *ipv4;
>>>> -             struct rte_ipv6_hdr *ipv6;
>>>> -             struct rte_tcp_hdr *tcp;
>>>> -             struct rte_udp_hdr *udp;
>>>> -             uint8_t *byte;
>>>> -     } h;
>>>>
>>>>        /*
>>>>         * Receive a burst of packets and forward them.
>>>> @@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
>>>>        if (unlikely(nb_rx == 0))
>>>>                return false;
>>>>
>>>> -     txp = &ports[fs->tx_port];
>>>> -     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
>>>> -     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
>>>> -                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
>>>> -     for (i = 0; i < nb_rx; i++) {
>>>> -             if (likely(i < nb_rx - 1))
>>>> -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
>>>> -                                     void *));
>>>> -             mb = pkts_burst[i];
>>>> -             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>>> -             proto = h.eth->ether_type;
>>>> -             swap_mac(h.eth);
>>>> -             mb->l2_len = sizeof(struct rte_ether_hdr);
>>>> -             h.eth++;
>>>> -             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
>>>> -                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
>>>> -                     proto = h.vlan->eth_proto;
>>>> -                     h.vlan++;
>>>> -                     mb->l2_len += sizeof(struct rte_vlan_hdr);
>>>> -             }
>>>> -             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
>>>> -                     swap_ipv4(h.ipv4);
>>>> -                     next_proto = h.ipv4->next_proto_id;
>>>> -                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
>>>> -                     h.byte += mb->l3_len;
>>>> -             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
>>>> -                     swap_ipv6(h.ipv6);
>>>> -                     next_proto = h.ipv6->proto;
>>>> -                     h.ipv6++;
>>>> -                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
>>>> -             } else {
>>>> -                     mbuf_field_set(mb, ol_flags);
>>>> -                     continue;
>>>> -             }
>>>> -             if (next_proto == IPPROTO_UDP) {
>>>> -                     swap_udp(h.udp);
>>>> -                     mb->l4_len = sizeof(struct rte_udp_hdr);
>>>> -             } else if (next_proto == IPPROTO_TCP) {
>>>> -                     swap_tcp(h.tcp);
>>>> -                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
>>>> -             }
>>>> -             mbuf_field_set(mb, ol_flags);
>>>> -     }
>>>> +     do_5tswap(pkts_burst, nb_rx, fs);
>>>> +
>>>
>>> this simplification is nice.
>>>
>>>>        common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>>>>
>>>>        return true;
>>>> diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
>>>> new file mode 100644
>>>> index 0000000000..48da9236dc
>>>> --- /dev/null
>>>> +++ b/app/test-pmd/5tswap.h
>>>> @@ -0,0 +1,130 @@
>>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>>> + * Copyright(c) 2018 Intel Corporation
>>>> + */
>>>> +
>>>> +#ifndef _5TSWAP_H_
>>>> +#define _5TSWAP_H_
>>>> +
>>>> +#include "macswap_common.h"
>>>> +
>>>> +static inline void
>>>> +swap_mac(struct rte_ether_hdr *eth_hdr)
>>>> +{
>>>> +     struct rte_ether_addr addr;
>>>> +
>>>> +     /* Swap dest and src mac addresses. */
>>>> +     rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
>>>> +     rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
>>>> +     rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
>>>> +}
>>>> +
>>>> +static inline void
>>>> +swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
>>>> +{
>>>> +     rte_be32_t addr;
>>>> +
>>>> +     /* Swap dest and src ipv4 addresses. */
>>>> +     addr = ipv4_hdr->src_addr;
>>>> +     ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
>>>> +     ipv4_hdr->dst_addr = addr;
>>>> +}
>>>> +
>>>> +static inline void
>>>> +swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
>>>> +{
>>>> +     uint8_t addr[16];
>>>> +
>>>> +     /* Swap dest and src ipv6 addresses. */
>>>> +     memcpy(&addr, &ipv6_hdr->src_addr, 16);
>>>> +     memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
>>>> +     memcpy(&ipv6_hdr->dst_addr, &addr, 16);
>>>> +}
>>>> +
>>>> +static inline void
>>>> +swap_tcp(struct rte_tcp_hdr *tcp_hdr)
>>>> +{
>>>> +     rte_be16_t port;
>>>> +
>>>> +     /* Swap dest and src tcp port. */
>>>> +     port = tcp_hdr->src_port;
>>>> +     tcp_hdr->src_port = tcp_hdr->dst_port;
>>>> +     tcp_hdr->dst_port = port;
>>>> +}
>>>> +
>>>> +static inline void
>>>> +swap_udp(struct rte_udp_hdr *udp_hdr)
>>>> +{
>>>> +     rte_be16_t port;
>>>> +
>>>> +     /* Swap dest and src udp port */
>>>> +     port = udp_hdr->src_port;
>>>> +     udp_hdr->src_port = udp_hdr->dst_port;
>>>> +     udp_hdr->dst_port = port;
>>>> +}
>>>> +
>>>> +static inline void
>>>> +do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
>>>> +               struct fwd_stream *fs)
>>>> +{
>>>> +     struct rte_port  *txp;
>>>> +     struct rte_mbuf *mb;
>>>> +     uint16_t next_proto;
>>>> +     uint64_t ol_flags;
>>>> +     uint16_t proto;
>>>> +     int i;
>>>> +     union {
>>>> +             struct rte_ether_hdr *eth;
>>>> +             struct rte_vlan_hdr *vlan;
>>>> +             struct rte_ipv4_hdr *ipv4;
>>>> +             struct rte_ipv6_hdr *ipv6;
>>>> +             struct rte_tcp_hdr *tcp;
>>>> +             struct rte_udp_hdr *udp;
>>>> +             uint8_t *byte;
>>>> +     } h;
>>>> +
>>>> +     txp = &ports[fs->tx_port];
>>>> +     ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
>>>> +     vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
>>>> +                     txp->tx_vlan_id, txp->tx_vlan_id_outer);
>>>> +     for (i = 0; i < nb_rx; i++) {
>>>> +             if (likely(i < nb_rx - 1))
>>>> +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
>>>> +                                     void *));
>>>> +             mb = pkts_burst[i];
>>>> +             h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>>> +             proto = h.eth->ether_type;
>>>> +             swap_mac(h.eth);
>>>> +             mb->l2_len = sizeof(struct rte_ether_hdr);
>>>> +             h.eth++;
>>>> +             while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
>>>> +                    proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
>>>> +                     proto = h.vlan->eth_proto;
>>>> +                     h.vlan++;
>>>> +                     mb->l2_len += sizeof(struct rte_vlan_hdr);
>>>> +             }
>>>> +             if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
>>>> +                     swap_ipv4(h.ipv4);
>>>> +                     next_proto = h.ipv4->next_proto_id;
>>>> +                     mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
>>>> +                     h.byte += mb->l3_len;
>>>> +             } else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
>>>> +                     swap_ipv6(h.ipv6);
>>>> +                     next_proto = h.ipv6->proto;
>>>> +                     h.ipv6++;
>>>> +                     mb->l3_len = sizeof(struct rte_ipv6_hdr);
>>>> +             } else {
>>>> +                     mbuf_field_set(mb, ol_flags);
>>>> +                     continue;
>>>> +             }
>>>> +             if (next_proto == IPPROTO_UDP) {
>>>> +                     swap_udp(h.udp);
>>>> +                     mb->l4_len = sizeof(struct rte_udp_hdr);
>>>> +             } else if (next_proto == IPPROTO_TCP) {
>>>> +                     swap_tcp(h.tcp);
>>>> +                     mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
>>>> +             }
>>>> +             mbuf_field_set(mb, ol_flags);
>>>> +     }
>>>> +}
>>>> +
>>>> +#endif /* _5TSWAP_H_ */
>>>> diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
>>>> index 7316d73315..d19ace7395 100644
>>>> --- a/app/test-pmd/macfwd.c
>>>> +++ b/app/test-pmd/macfwd.c
>>>> @@ -35,6 +35,7 @@
>>>>    #include <rte_flow.h>
>>>>
>>>>    #include "testpmd.h"
>>>> +#include "macfwd.h"
>>>>
>>>>    /*
>>>>     * Forwarding of packets in MAC mode.
>>>> @@ -45,13 +46,7 @@ static bool
>>>>    pkt_burst_mac_forward(struct fwd_stream *fs)
>>>>    {
>>>>        struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>>> -     struct rte_port  *txp;
>>>> -     struct rte_mbuf  *mb;
>>>> -     struct rte_ether_hdr *eth_hdr;
>>>>        uint16_t nb_rx;
>>>> -     uint16_t i;
>>>> -     uint64_t ol_flags = 0;
>>>> -     uint64_t tx_offloads;
>>>>
>>>>        /*
>>>>         * Receive a burst of packets and forward them.
>>>> @@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
>>>>        if (unlikely(nb_rx == 0))
>>>>                return false;
>>>>
>>>> -     txp = &ports[fs->tx_port];
>>>> -     tx_offloads = txp->dev_conf.txmode.offloads;
>>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
>>>> -             ol_flags = RTE_MBUF_F_TX_VLAN;
>>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
>>>> -             ol_flags |= RTE_MBUF_F_TX_QINQ;
>>>> -     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
>>>> -             ol_flags |= RTE_MBUF_F_TX_MACSEC;
>>>> -     for (i = 0; i < nb_rx; i++) {
>>>> -             if (likely(i < nb_rx - 1))
>>>> -                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
>>>> -                                                    void *));
>>>> -             mb = pkts_burst[i];
>>>> -             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>>> -             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
>>>> -                             &eth_hdr->dst_addr);
>>>> -             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
>>>> -                             &eth_hdr->src_addr);
>>>> -             mb->ol_flags &= RTE_MBUF_F_INDIRECT |
>>>> RTE_MBUF_F_EXTERNAL;
>>>> -             mb->ol_flags |= ol_flags;
>>>> -             mb->l2_len = sizeof(struct rte_ether_hdr);
>>>> -             mb->l3_len = sizeof(struct rte_ipv4_hdr);
>>>> -             mb->vlan_tci = txp->tx_vlan_id;
>>>> -             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
>>>> -     }
>>>> +     do_macfwd(pkts_burst, nb_rx, fs);
>>>>
>>>>        common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>>>>
>>>> diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
>>>> new file mode 100644
>>>> index 0000000000..3f3e7189e1
>>>> --- /dev/null
>>>> +++ b/app/test-pmd/macfwd.h
>>>> @@ -0,0 +1,46 @@
>>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>>> + * Copyright(c) 2018 Intel Corporation
>>>> + */
>>>> +
>>>> +#ifndef _MACFWD_H_
>>>> +#define _MACFWD_H_
>>>> +
>>>> +static inline void
>>>> +do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
>>>> +               struct fwd_stream *fs)
>>>
>>> nit: indent/alignment is a little off here. There is some extra spaces.
>>> Same with other do_*()
>>>
>>>> +{
>>>> +     struct rte_ether_hdr *eth_hdr;
>>>> +     uint64_t ol_flags = 0;
>>>> +     uint64_t tx_offloads;
>>>> +     struct rte_mbuf  *mb;
>>>> +     struct rte_port *txp = &ports[fs->tx_port];
>>>> +     uint16_t i;
>>>> +
>>>> +
>>>
>>> can remove addition blank line
>>>
>>>> +     tx_offloads = txp->dev_conf.txmode.offloads;
>>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
>>>> +             ol_flags = RTE_MBUF_F_TX_VLAN;
>>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
>>>> +             ol_flags |= RTE_MBUF_F_TX_QINQ;
>>>> +     if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
>>>> +             ol_flags |= RTE_MBUF_F_TX_MACSEC;
>>>> +     for (i = 0; i < nb_rx; i++) {
>>>> +             if (likely(i < nb_rx - 1))
>>>> +                     rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
>>>> +                                                    void *));
>>>> +             mb = pkts_burst[i];
>>>> +             eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
>>>> +             rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
>>>> +                             &eth_hdr->dst_addr);
>>>> +             rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
>>>> +                             &eth_hdr->src_addr);
>>>> +             mb->ol_flags &= RTE_MBUF_F_INDIRECT |
>>>> RTE_MBUF_F_EXTERNAL;
>>>> +             mb->ol_flags |= ol_flags;
>>>> +             mb->l2_len = sizeof(struct rte_ether_hdr);
>>>> +             mb->l3_len = sizeof(struct rte_ipv4_hdr);
>>>> +             mb->vlan_tci = txp->tx_vlan_id;
>>>> +             mb->vlan_tci_outer = txp->tx_vlan_id_outer;
>>>> +     }
>>>> +}
>>>> +
>>>> +#endif /* _MACFWD_H_ */
>>>> diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
>>>> index 2bf90a983c..1d5a2e470a 100644
>>>> --- a/app/test-pmd/noisy_vnf.c
>>>> +++ b/app/test-pmd/noisy_vnf.c
>>>> @@ -32,6 +32,18 @@
>>>>    #include <rte_malloc.h>
>>>>
>>>>    #include "testpmd.h"
>>>> +#include "5tswap.h"
>>>> +#include "macfwd.h"
>>>> +#if defined(RTE_ARCH_X86)
>>>> +#include "macswap_sse.h"
>>>> +#elif defined(__ARM_NEON)
>>>> +#include "macswap_neon.h"
>>>> +#else
>>>> +#include "macswap.h"
>>>> +#endif
>>>> +
>>>> +#define NOISY_STRSIZE 256
>>>> +#define NOISY_RING "noisy_ring_%d\n"
>>>>
>>>>    struct noisy_config {
>>>>        struct rte_ring *f;
>>>> @@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf,
>>>> uint16_t nb_pkts)
>>>>    {
>>>>        uint16_t i, j;
>>>>
>>>> -     if (!ncf->do_sim)
>>>> -             return;
>>>> -
>>>
>>> Why is this removed? It's not checked before all calls to this function
>>>
>>>>        for (i = 0; i < nb_pkts; i++) {
>>>>                for (j = 0; j < noisy_lkup_num_writes; j++)
>>>>                        do_write(ncf->vnf_mem);
>>>> @@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf,
>>>> uint16_t nb_pkts)
>>>>     *    out of the FIFO
>>>>     * 4. Cases 2 and 3 combined
>>>>     */
>>>> -static bool
>>>> -pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>>> +static uint16_t
>>>> +noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct
>>>> rte_mbuf **pkts_burst)
>>>>    {
>>>>        const uint64_t freq_khz = rte_get_timer_hz() / 1000;
>>>>        struct noisy_config *ncf = noisy_cfg[fs->rx_port];
>>>> -     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>>>        struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
>>>>        uint16_t nb_deqd = 0;
>>>> -     uint16_t nb_rx = 0;
>>>>        uint16_t nb_tx = 0;
>>>>        uint16_t nb_enqd;
>>>>        unsigned int fifo_free;
>>>> @@ -126,12 +133,12 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>>>        bool needs_flush = false;
>>>>        uint64_t now;
>>>>
>>>> -     nb_rx = common_fwd_stream_receive(fs, pkts_burst,
>>>> nb_pkt_per_burst);
>>>>        if (unlikely(nb_rx == 0))
>>>>                goto flush;
>>>>
>>>>        if (!ncf->do_buffering) {
>>>> -             sim_memory_lookups(ncf, nb_rx);
>>>> +             if (ncf->do_sim)
>>>> +                     sim_memory_lookups(ncf, nb_rx);
>>>>                nb_tx = common_fwd_stream_transmit(fs, pkts_burst,
>>>> nb_rx);
>>>>                goto end;
>>>>        }
>>>> @@ -169,11 +176,61 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>>>>                ncf->prev_time = rte_get_timer_cycles();
>>>>        }
>>>>    end:
>>>> +     return nb_tx;
>>>> +}
>>>> +
>>>> +static bool
>>>> +pkt_burst_io(struct fwd_stream *fs)
>>>> +{
>>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>>> +     uint16_t nb_rx;
>>>> +     uint16_t nb_tx;
>>>> +
>>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst,
>>>> nb_pkt_per_burst);
>>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>>> +
>>>>        return nb_rx > 0 || nb_tx > 0;
>>>>    }
>>>>
>>>> -#define NOISY_STRSIZE 256
>>>> -#define NOISY_RING "noisy_ring_%d\n"
>>>> +static bool
>>>> +pkt_burst_mac(struct fwd_stream *fs)
>>>> +{
>>>> +     struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>>> +     uint16_t nb_rx;
>>>> +     uint16_t nb_tx;
>>>> +
>>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst,
>>>> nb_pkt_per_burst);
>>>
>>> Similar to macfwd.c, you can add check for unlikely(nb_rx == 0) at this
>>> point in these fns.
>>
>> That's true. I removed it because I'll have to call
>> noisy_eth_tx_burst() regardless, but we could avoid the middle call in
>> these locations.
>>
>> I agree with the other suggestions.
>>
>> Thanks,
>> M
>>
>>>
>>>> +     do_macfwd(pkts_burst, nb_rx, fs);
>>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>>> +
>>>> +     return nb_rx > 0 || nb_tx > 0;
>>>> +}
>>>> +static bool
>>>> +pkt_burst_macswap(struct fwd_stream *fs)
>>>> +{
>>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>>> +     uint16_t nb_rx = 0;
>>>> +     uint16_t nb_tx = 0;
>>>
>>> nit: these are not assigned in the other functions
>>>
>>>> +
>>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst,
>>>> nb_pkt_per_burst);
>>>> +     do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
>>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>>> +
>>>> +     return nb_rx > 0 || nb_tx > 0;
>>>> +}
>>>> +static bool
>>>> +pkt_brust_5tswap(struct fwd_stream *fs)
>>>> +{
>>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>>> +     uint16_t nb_rx = 0;
>>>> +     uint16_t nb_tx = 0;
>>>> +
>>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst,
>>>> nb_pkt_per_burst);
>>>> +     do_5tswap(pkts_burst, nb_rx, fs);
>>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>>> +
>>>> +     return nb_rx > 0 || nb_tx > 0;
>>>> +}
>>>>
>>>>    static void
>>>>    noisy_fwd_end(portid_t pi)
>>>> @@ -226,6 +283,15 @@ noisy_fwd_begin(portid_t pi)
>>>>                         "--noisy-lkup-memory-size must be > 0\n");
>>>>        }
>>>>
>>>> +     if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
>>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_io;
>>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
>>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_mac;
>>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
>>>> +             noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
>>>> +     else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
>>>> +             noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
>>>> +
>>>>        return 0;
>>>>    }
>>>>
>>>> @@ -233,6 +299,6 @@ struct fwd_engine noisy_vnf_engine = {
>>>>        .fwd_mode_name  = "noisy",
>>>>        .port_fwd_begin = noisy_fwd_begin,
>>>>        .port_fwd_end   = noisy_fwd_end,
>>>> -     .stream_init    = common_fwd_stream_init,
>>>> -     .packet_fwd     = pkt_burst_noisy_vnf,
>>>> +     .stream_init    = common_fwd_stream_init,
>>>> +     .packet_fwd     = pkt_burst_io,
>>>>    };
>>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>>> index 3b37809baf..129c55c0ad 100644
>>>> --- a/app/test-pmd/parameters.c
>>>> +++ b/app/test-pmd/parameters.c
>>>> @@ -196,6 +196,7 @@ usage(char* progname)
>>>>        printf("  --noisy-lkup-num-writes=N: do N random writes per
>>>> packet\n");
>>>>        printf("  --noisy-lkup-num-reads=N: do N random reads per
>>>> packet\n");
>>>>        printf("  --noisy-lkup-num-reads-writes=N: do N random reads
>>>> and writes per packet\n");
>>>> +     printf("  --noisy-fwd-mode=mode: set the fwd mode\n");
>>>>        printf("  --no-iova-contig: mempool memory can be IOVA non
>>>> contiguous. "
>>>>               "valid only with --mp-alloc=anon\n");
>>>>        printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode
>>>> can be "
>>>> @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
>>>>                { "noisy-lkup-num-writes",      1, 0, 0 },
>>>>                { "noisy-lkup-num-reads",       1, 0, 0 },
>>>>                { "noisy-lkup-num-reads-writes", 1, 0, 0 },
>>>> +             { "noisy-fwd-mode",             1, 0, 0 },
>>>>                { "no-iova-contig",             0, 0, 0 },
>>>>                { "rx-mq-mode",                 1, 0, 0 },
>>>>                { "record-core-cycles",         0, 0, 0 },
>>>> @@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
>>>>                                        rte_exit(EXIT_FAILURE,
>>>>                                                
>>>> "noisy-lkup-num-reads-writes must be >= 0\n");
>>>>                        }
>>>> +                     if (!strcmp(lgopts[opt_idx].name,
>>>> +                                 "noisy-fwd-mode")) {
>>>> +                             if (!strcmp(optarg, "io"))
>>>> +                                     noisy_fwd_mode =
>>>> NOISY_FWD_MODE_IO;
>>>> +                             else if (!strcmp(optarg, "mac"))
>>>> +                                     noisy_fwd_mode =
>>>> NOISY_FWD_MODE_MAC;
>>>> +                             else if (!strcmp(optarg, "macswap"))
>>>> +                                     noisy_fwd_mode =
>>>> NOISY_FWD_MODE_MACSWAP;
>>>> +                             else if (!strcmp(optarg, "5tswap"))
>>>> +                                     noisy_fwd_mode =
>>>> NOISY_FWD_MODE_5TSWAP;
>>>> +                             else
>>>> +                                     rte_exit(EXIT_FAILURE,
>>>> "noisy-fwd-mode %s invalid -"
>>>> +                                              " must b a valid fwd
>>>> mode\n",
>>>
>>> typo "be"
>>>
>>> I would specify "..must be a valid noisy-fwd-mode value" to avoid
>>> confusion with the full set of general fwd modes and easier for user to
>>> search them in docs.
>>>
>>>> +                                              optarg);
>>>> +                     }
>>>>                        if (!strcmp(lgopts[opt_idx].name,
>>>> "no-iova-contig"))
>>>>                                mempool_flags =
>>>> RTE_MEMPOOL_F_NO_IOVA_CONTIG;
>>>>
>>>> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
>>>> index 5cb6f92523..92784873ff 100644
>>>> --- a/app/test-pmd/testpmd.c
>>>> +++ b/app/test-pmd/testpmd.c
>>>> @@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
>>>>     */
>>>>    uint64_t noisy_lkup_num_reads_writes;
>>>>
>>>> +/*
>>>> + * Configurable forwarding mode in VNF simulation.
>>>> + */
>>>> +int noisy_fwd_mode;
>>>> +
>>>>    /*
>>>>     * Receive Side Scaling (RSS) configuration.
>>>>     */
>>>> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
>>>> index bdfbfd36d3..f70397ad26 100644
>>>> --- a/app/test-pmd/testpmd.h
>>>> +++ b/app/test-pmd/testpmd.h
>>>> @@ -116,6 +116,13 @@ enum {
>>>>        QUEUE_JOB_TYPE_ACTION_QUERY,
>>>>    };
>>>>
>>>> +enum {
>>>> +     NOISY_FWD_MODE_IO,
>>>> +     NOISY_FWD_MODE_MAC,
>>>> +     NOISY_FWD_MODE_MACSWAP,
>>>> +     NOISY_FWD_MODE_5TSWAP
>>>> +};
>>>> +
>>>>    /**
>>>>     * The data structure associated with RX and TX packet burst
>>>> statistics
>>>>     * that are recorded for each forwarding stream.
>>>> @@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
>>>>    extern uint64_t noisy_lkup_num_writes;
>>>>    extern uint64_t noisy_lkup_num_reads;
>>>>    extern uint64_t noisy_lkup_num_reads_writes;
>>>> +extern int noisy_fwd_mode;
>>>>
>>>>    extern uint8_t dcb_config;
>>>>
>>>> diff --git a/doc/guides/testpmd_app_ug/run_app.rst
>>>> b/doc/guides/testpmd_app_ug/run_app.rst
>>>> index 57b23241cf..fcca3e8921 100644
>>>> --- a/doc/guides/testpmd_app_ug/run_app.rst
>>>> +++ b/doc/guides/testpmd_app_ug/run_app.rst
>>>> @@ -519,6 +519,15 @@ The command line options are:
>>>>        Set the number of r/w accesses to be done in noisy neighbor
>>>> simulation memory buffer to N.
>>>>        Only available with the noisy forwarding mode. The default
>>>> value is 0.
>>>>
>>>> +*   ``--noisy-fwd-mode=mode``
>>>> +
>>>> +    Set the noisy vnf forwarding mode where ``mode`` is one of the
>>>> following::
>>>> +
>>>> +       io (the default)
>>>> +       mac
>>>> +       macswap
>>>> +       5tswap
>>>> +
>>>>    *   ``--no-iova-contig``
>>>>
>>>>        Enable to create mempool which is not IOVA contiguous. Valid
>>>> only with --mp-alloc=anon.
>>>
>>
> 


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v4] app/testpmd: expand noisy neighbour forward mode support
  2023-06-02 18:29 ` [PATCH v4] " Mike Pattrick
@ 2023-06-06 14:27   ` Ferruh Yigit
  2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
  1 sibling, 0 replies; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-06 14:27 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang, Ruifeng Wang,
	Bruce Richardson, Konstantin Ananyev
  Cc: ktraynor, dev

On 6/2/2023 7:29 PM, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>  ---
>  v2: Reverted changes to random memory lookup
>  v3: Refactored entire patch
>  v4: Implemented recommended formatting changes
> ---
>  app/test-pmd/5tswap.c                 | 118 +----------------------
>  app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
>  app/test-pmd/macfwd.c                 |  33 +------
>  app/test-pmd/macfwd.h                 |  45 +++++++++
>  app/test-pmd/macswap.h                |   2 +-
>  app/test-pmd/macswap_neon.h           |   2 +-
>  app/test-pmd/macswap_sse.h            |   4 +-
>  app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
>  app/test-pmd/parameters.c             |  17 ++++
>  app/test-pmd/testpmd.c                |   5 +
>  app/test-pmd/testpmd.h                |   8 ++
>  doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>  12 files changed, 313 insertions(+), 166 deletions(-)
>  create mode 100644 app/test-pmd/5tswap.h
>  create mode 100644 app/test-pmd/macfwd.h
> 
> diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
> index ff8c2dcde5..8e8de2557a 100644
> --- a/app/test-pmd/5tswap.c
> +++ b/app/test-pmd/5tswap.c
> @@ -17,64 +17,8 @@
>  #include <rte_ip.h>
>  #include <rte_flow.h>
>  
> -#include "macswap_common.h"
>  #include "testpmd.h"
> -
> -
> -static inline void
> -swap_mac(struct rte_ether_hdr *eth_hdr)
> -{
> -	struct rte_ether_addr addr;
> -
> -	/* Swap dest and src mac addresses. */
> -	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> -	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> -	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> -}
> -
> -static inline void
> -swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> -{
> -	rte_be32_t addr;
> -
> -	/* Swap dest and src ipv4 addresses. */
> -	addr = ipv4_hdr->src_addr;
> -	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> -	ipv4_hdr->dst_addr = addr;
> -}
> -
> -static inline void
> -swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> -{
> -	uint8_t addr[16];
> -
> -	/* Swap dest and src ipv6 addresses. */
> -	memcpy(&addr, &ipv6_hdr->src_addr, 16);
> -	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> -	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> -}
> -
> -static inline void
> -swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> -{
> -	rte_be16_t port;
> -
> -	/* Swap dest and src tcp port. */
> -	port = tcp_hdr->src_port;
> -	tcp_hdr->src_port = tcp_hdr->dst_port;
> -	tcp_hdr->dst_port = port;
> -}
> -
> -static inline void
> -swap_udp(struct rte_udp_hdr *udp_hdr)
> -{
> -	rte_be16_t port;
> -
> -	/* Swap dest and src udp port */
> -	port = udp_hdr->src_port;
> -	udp_hdr->src_port = udp_hdr->dst_port;
> -	udp_hdr->dst_port = port;
> -}
> +#include "5tswap.h"
>  
>  /*
>   * 5 tuple swap forwarding mode: Swap the source and the destination of layers
> @@ -85,22 +29,7 @@ static bool
>  pkt_burst_5tuple_swap(struct fwd_stream *fs)
>  {
>  	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> -	struct rte_port  *txp;
> -	struct rte_mbuf *mb;
> -	uint16_t next_proto;
> -	uint64_t ol_flags;
> -	uint16_t proto;
>  	uint16_t nb_rx;
> -	int i;
> -	union {
> -		struct rte_ether_hdr *eth;
> -		struct rte_vlan_hdr *vlan;
> -		struct rte_ipv4_hdr *ipv4;
> -		struct rte_ipv6_hdr *ipv6;
> -		struct rte_tcp_hdr *tcp;
> -		struct rte_udp_hdr *udp;
> -		uint8_t *byte;
> -	} h;
>  
>  	/*
>  	 * Receive a burst of packets and forward them.
> @@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
>  	if (unlikely(nb_rx == 0))
>  		return false;
>  
> -	txp = &ports[fs->tx_port];
> -	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> -	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> -			txp->tx_vlan_id, txp->tx_vlan_id_outer);
> -	for (i = 0; i < nb_rx; i++) {
> -		if (likely(i < nb_rx - 1))
> -			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> -					void *));
> -		mb = pkts_burst[i];
> -		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> -		proto = h.eth->ether_type;
> -		swap_mac(h.eth);
> -		mb->l2_len = sizeof(struct rte_ether_hdr);
> -		h.eth++;
> -		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> -		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> -			proto = h.vlan->eth_proto;
> -			h.vlan++;
> -			mb->l2_len += sizeof(struct rte_vlan_hdr);
> -		}
> -		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> -			swap_ipv4(h.ipv4);
> -			next_proto = h.ipv4->next_proto_id;
> -			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> -			h.byte += mb->l3_len;
> -		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> -			swap_ipv6(h.ipv6);
> -			next_proto = h.ipv6->proto;
> -			h.ipv6++;
> -			mb->l3_len = sizeof(struct rte_ipv6_hdr);
> -		} else {
> -			mbuf_field_set(mb, ol_flags);
> -			continue;
> -		}
> -		if (next_proto == IPPROTO_UDP) {
> -			swap_udp(h.udp);
> -			mb->l4_len = sizeof(struct rte_udp_hdr);
> -		} else if (next_proto == IPPROTO_TCP) {
> -			swap_tcp(h.tcp);
> -			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> -		}
> -		mbuf_field_set(mb, ol_flags);
> -	}
> +	do_5tswap(pkts_burst, nb_rx, fs);
> +
>  	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>  
>  	return true;
> diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
> new file mode 100644
> index 0000000000..974af1aacd
> --- /dev/null
> +++ b/app/test-pmd/5tswap.h
> @@ -0,0 +1,130 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
>

I guess intention is to keep original file copyright owner, but it is
not Intel, can you please check again?

> + */
> +
> +#ifndef _5TSWAP_H_
> +#define _5TSWAP_H_
> +
> +#include "macswap_common.h"
> +
> +static inline void
> +swap_mac(struct rte_ether_hdr *eth_hdr)
> +{
> +	struct rte_ether_addr addr;
> +
> +	/* Swap dest and src mac addresses. */
> +	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
> +	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
> +	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
> +}
> +
> +static inline void
> +swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
> +{
> +	rte_be32_t addr;
> +
> +	/* Swap dest and src ipv4 addresses. */
> +	addr = ipv4_hdr->src_addr;
> +	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
> +	ipv4_hdr->dst_addr = addr;
> +}
> +
> +static inline void
> +swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
> +{
> +	uint8_t addr[16];
> +
> +	/* Swap dest and src ipv6 addresses. */
> +	memcpy(&addr, &ipv6_hdr->src_addr, 16);
> +	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
> +	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
> +}
> +
> +static inline void
> +swap_tcp(struct rte_tcp_hdr *tcp_hdr)
> +{
> +	rte_be16_t port;
> +
> +	/* Swap dest and src tcp port. */
> +	port = tcp_hdr->src_port;
> +	tcp_hdr->src_port = tcp_hdr->dst_port;
> +	tcp_hdr->dst_port = port;
> +}
> +
> +static inline void
> +swap_udp(struct rte_udp_hdr *udp_hdr)
> +{
> +	rte_be16_t port;
> +
> +	/* Swap dest and src udp port */
> +	port = udp_hdr->src_port;
> +	udp_hdr->src_port = udp_hdr->dst_port;
> +	udp_hdr->dst_port = port;
> +}
> +
> +static inline void
> +do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> +	  struct fwd_stream *fs)
> +{
> +	struct rte_port  *txp;
> +	struct rte_mbuf *mb;
> +	uint16_t next_proto;
> +	uint64_t ol_flags;
> +	uint16_t proto;
> +	int i;
> +	union {
> +		struct rte_ether_hdr *eth;
> +		struct rte_vlan_hdr *vlan;
> +		struct rte_ipv4_hdr *ipv4;
> +		struct rte_ipv6_hdr *ipv6;
> +		struct rte_tcp_hdr *tcp;
> +		struct rte_udp_hdr *udp;
> +		uint8_t *byte;
> +	} h;
> +
> +	txp = &ports[fs->tx_port];
> +	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
> +	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
> +		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
> +	for (i = 0; i < nb_rx; i++) {
> +		if (likely(i < nb_rx - 1))
> +			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
> +						       void *));
> +		mb = pkts_burst[i];
> +		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> +		proto = h.eth->ether_type;
> +		swap_mac(h.eth);
> +		mb->l2_len = sizeof(struct rte_ether_hdr);
> +		h.eth++;
> +		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> +		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> +			proto = h.vlan->eth_proto;
> +			h.vlan++;
> +			mb->l2_len += sizeof(struct rte_vlan_hdr);
> +		}
> +		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
> +			swap_ipv4(h.ipv4);
> +			next_proto = h.ipv4->next_proto_id;
> +			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
> +			h.byte += mb->l3_len;
> +		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
> +			swap_ipv6(h.ipv6);
> +			next_proto = h.ipv6->proto;
> +			h.ipv6++;
> +			mb->l3_len = sizeof(struct rte_ipv6_hdr);
> +		} else {
> +			mbuf_field_set(mb, ol_flags);
> +			continue;
> +		}
> +		if (next_proto == IPPROTO_UDP) {
> +			swap_udp(h.udp);
> +			mb->l4_len = sizeof(struct rte_udp_hdr);
> +		} else if (next_proto == IPPROTO_TCP) {
> +			swap_tcp(h.tcp);
> +			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
> +		}
> +		mbuf_field_set(mb, ol_flags);
> +	}
> +}
> +
> +#endif /* _5TSWAP_H_ */
> diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
> index 7316d73315..d19ace7395 100644
> --- a/app/test-pmd/macfwd.c
> +++ b/app/test-pmd/macfwd.c
> @@ -35,6 +35,7 @@
>  #include <rte_flow.h>
>  
>  #include "testpmd.h"
> +#include "macfwd.h"
>  
>  /*
>   * Forwarding of packets in MAC mode.
> @@ -45,13 +46,7 @@ static bool
>  pkt_burst_mac_forward(struct fwd_stream *fs)
>  {
>  	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> -	struct rte_port  *txp;
> -	struct rte_mbuf  *mb;
> -	struct rte_ether_hdr *eth_hdr;
>  	uint16_t nb_rx;
> -	uint16_t i;
> -	uint64_t ol_flags = 0;
> -	uint64_t tx_offloads;
>  
>  	/*
>  	 * Receive a burst of packets and forward them.
> @@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
>  	if (unlikely(nb_rx == 0))
>  		return false;
>  
> -	txp = &ports[fs->tx_port];
> -	tx_offloads = txp->dev_conf.txmode.offloads;
> -	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> -		ol_flags = RTE_MBUF_F_TX_VLAN;
> -	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> -		ol_flags |= RTE_MBUF_F_TX_QINQ;
> -	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> -		ol_flags |= RTE_MBUF_F_TX_MACSEC;
> -	for (i = 0; i < nb_rx; i++) {
> -		if (likely(i < nb_rx - 1))
> -			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> -						       void *));
> -		mb = pkts_burst[i];
> -		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> -		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> -				&eth_hdr->dst_addr);
> -		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> -				&eth_hdr->src_addr);
> -		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> -		mb->ol_flags |= ol_flags;
> -		mb->l2_len = sizeof(struct rte_ether_hdr);
> -		mb->l3_len = sizeof(struct rte_ipv4_hdr);
> -		mb->vlan_tci = txp->tx_vlan_id;
> -		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> -	}
> +	do_macfwd(pkts_burst, nb_rx, fs);
>  
>  	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>  
> diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
> new file mode 100644
> index 0000000000..69d9dfc64f
> --- /dev/null
> +++ b/app/test-pmd/macfwd.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef _MACFWD_H_
> +#define _MACFWD_H_
> +
> +static inline void
> +do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
> +	  struct fwd_stream *fs)
> +{
> +	struct rte_ether_hdr *eth_hdr;
> +	uint64_t ol_flags = 0;
> +	uint64_t tx_offloads;
> +	struct rte_mbuf  *mb;
> +	struct rte_port *txp = &ports[fs->tx_port];
> +	uint16_t i;
> +
> +	tx_offloads = txp->dev_conf.txmode.offloads;
> +	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
> +		ol_flags = RTE_MBUF_F_TX_VLAN;
> +	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
> +		ol_flags |= RTE_MBUF_F_TX_QINQ;
> +	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
> +		ol_flags |= RTE_MBUF_F_TX_MACSEC;
> +	for (i = 0; i < nb_rx; i++) {
> +		if (likely(i < nb_rx - 1))
> +			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
> +						       void *));
> +		mb = pkts_burst[i];
> +		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
> +		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
> +				    &eth_hdr->dst_addr);
> +		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
> +				    &eth_hdr->src_addr);
> +		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
> +		mb->ol_flags |= ol_flags;
> +		mb->l2_len = sizeof(struct rte_ether_hdr);
> +		mb->l3_len = sizeof(struct rte_ipv4_hdr);
> +		mb->vlan_tci = txp->tx_vlan_id;
> +		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
> +	}
> +}
> +
> +#endif /* _MACFWD_H_ */
> diff --git a/app/test-pmd/macswap.h b/app/test-pmd/macswap.h
> index 29c252bb8f..7fea461e77 100644
> --- a/app/test-pmd/macswap.h
> +++ b/app/test-pmd/macswap.h
> @@ -9,7 +9,7 @@
>  
>  static inline void
>  do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
> -		struct rte_port *txp)
> +	   struct rte_port *txp)
>  {
>  	struct rte_ether_hdr *eth_hdr;
>  	struct rte_mbuf *mb;
> diff --git a/app/test-pmd/macswap_neon.h b/app/test-pmd/macswap_neon.h
> index df6c260cd4..91d4cb7c2e 100644
> --- a/app/test-pmd/macswap_neon.h
> +++ b/app/test-pmd/macswap_neon.h
> @@ -14,7 +14,7 @@
>  
>  static inline void
>  do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
> -		struct rte_port *txp)
> +	   struct rte_port *txp)
>  {
>  	struct rte_ether_hdr *eth_hdr[4];
>  	struct rte_mbuf *mb[4];
> diff --git a/app/test-pmd/macswap_sse.h b/app/test-pmd/macswap_sse.h
> index 223f87a539..e17cc07be0 100644
> --- a/app/test-pmd/macswap_sse.h
> +++ b/app/test-pmd/macswap_sse.h
> @@ -9,7 +9,7 @@
>  
>  static inline void
>  do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
> -		struct rte_port *txp)
> +	   struct rte_port *txp)
>  {
>  	struct rte_ether_hdr *eth_hdr[4];
>  	struct rte_mbuf *mb[4];
> @@ -29,7 +29,7 @@ do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
>  
>  	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
>  	vlan_qinq_set(pkts, nb, ol_flags,
> -			txp->tx_vlan_id, txp->tx_vlan_id_outer);
> +		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
>  
>  	i = 0;
>  	r = nb;

Can you please remove these syntax changes, they are not just noise for
this patch?
And indeed original syntax looks correct, DPDK coding convention doesn't
allign parameters to the paranthesis, but uses tabs for next line.

> diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
> index 2bf90a983c..9b33930cab 100644
> --- a/app/test-pmd/noisy_vnf.c
> +++ b/app/test-pmd/noisy_vnf.c
> @@ -32,6 +32,18 @@
>  #include <rte_malloc.h>
>  
>  #include "testpmd.h"
> +#include "5tswap.h"
> +#include "macfwd.h"
> +#if defined(RTE_ARCH_X86)
> +#include "macswap_sse.h"
> +#elif defined(__ARM_NEON)
> +#include "macswap_neon.h"
> +#else
> +#include "macswap.h"
> +#endif
> +
> +#define NOISY_STRSIZE 256
> +#define NOISY_RING "noisy_ring_%d\n"
>  
>  struct noisy_config {
>  	struct rte_ring *f;
> @@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>  {
>  	uint16_t i, j;
>  
> -	if (!ncf->do_sim)
> -		return;
> -
>  	for (i = 0; i < nb_pkts; i++) {
>  		for (j = 0; j < noisy_lkup_num_writes; j++)
>  			do_write(ncf->vnf_mem);
> @@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
>   *    out of the FIFO
>   * 4. Cases 2 and 3 combined
>   */
> -static bool
> -pkt_burst_noisy_vnf(struct fwd_stream *fs)
> +static uint16_t
> +noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
>  {
>  	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
>  	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
> -	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>  	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
>  	uint16_t nb_deqd = 0;
> -	uint16_t nb_rx = 0;
>  	uint16_t nb_tx = 0;
>  	uint16_t nb_enqd;
>  	unsigned int fifo_free;
> @@ -126,12 +133,16 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>  	bool needs_flush = false;
>  	uint64_t now;
>  
> -	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> -	if (unlikely(nb_rx == 0))
> -		goto flush;
> +	if (unlikely(nb_rx == 0)) {
> +		if (!ncf->do_buffering)
> +			goto end;
> +		else
> +			goto flush;
> +	}
>  
>  	if (!ncf->do_buffering) {
> -		sim_memory_lookups(ncf, nb_rx);
> +		if (ncf->do_sim)
> +			sim_memory_lookups(ncf, nb_rx);
>  		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
>  		goto end;
>  	}
> @@ -150,7 +161,8 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>  			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
>  	}
>  
> -	sim_memory_lookups(ncf, nb_enqd);
> +	if (ncf->do_sim)
> +		sim_memory_lookups(ncf, nb_enqd);
>  
>  flush:
>  	if (ncf->do_flush) {
> @@ -169,11 +181,64 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
>  		ncf->prev_time = rte_get_timer_cycles();
>  	}
>  end:
> +	return nb_tx;
> +}
> +
> +static bool
> +pkt_burst_io(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
>  	return nb_rx > 0 || nb_tx > 0;
>  }
>  
> -#define NOISY_STRSIZE 256
> -#define NOISY_RING "noisy_ring_%d\n"
> +static bool
> +pkt_burst_mac(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_macfwd(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_burst_macswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_brust_5tswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_5tswap(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
>  
>  static void
>  noisy_fwd_end(portid_t pi)
> @@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
>  			 "--noisy-lkup-memory-size must be > 0\n");
>  	}
>  
> +	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_io;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
> +
>  	return 0;
>  }
>  
> @@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
>  	.fwd_mode_name  = "noisy",
>  	.port_fwd_begin = noisy_fwd_begin,
>  	.port_fwd_end   = noisy_fwd_end,
> -	.stream_init    = common_fwd_stream_init,
> -	.packet_fwd     = pkt_burst_noisy_vnf,
> +	.stream_init	= common_fwd_stream_init,
> +	.packet_fwd     = pkt_burst_io,
>  };
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index 3b37809baf..551714cce4 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -196,6 +196,7 @@ usage(char* progname)
>  	printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
>  	printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
>  	printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
> +	printf("  --noisy-fwd-mode=mode: set the fwd mode\n");

'--noisy-fwd-mode' looks more major config option comparing the other
'--noisy-lkup-*' ones, if so can you please move '--noisy-fwd-mode' up
to the top of the '--noisy-*' group?


Also what do you think to list possible values here, to help users, like
'io (default), mac, macswap, 5tswap'.

>  	printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
>  	       "valid only with --mp-alloc=anon\n");
>  	printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
> @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
>  		{ "noisy-lkup-num-writes",	1, 0, 0 },
>  		{ "noisy-lkup-num-reads",	1, 0, 0 },
>  		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
> +		{ "noisy-fwd-mode",             1, 0, 0 },
>  		{ "no-iova-contig",             0, 0, 0 },
>  		{ "rx-mq-mode",                 1, 0, 0 },
>  		{ "record-core-cycles",         0, 0, 0 },
> @@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
>  					rte_exit(EXIT_FAILURE,
>  						 "noisy-lkup-num-reads-writes must be >= 0\n");
>  			}
> +			if (!strcmp(lgopts[opt_idx].name,
> +				    "noisy-fwd-mode")) {
> +				if (!strcmp(optarg, "io"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_IO;
> +				else if (!strcmp(optarg, "mac"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_MAC;
> +				else if (!strcmp(optarg, "macswap"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
> +				else if (!strcmp(optarg, "5tswap"))
> +					noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
> +				else
> +					rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
> +						 " must be a valid noisy-fwd-mode value\n",
> +						 optarg);
> +			}
>  			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
>  				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
>  
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index 5cb6f92523..92784873ff 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
>   */
>  uint64_t noisy_lkup_num_reads_writes;
>  
> +/*
> + * Configurable forwarding mode in VNF simulation.

Kind of obvious from variable name but can you extend the comment to
give more detail that this is related to the noisy forwarding mode?

> + */
> +int noisy_fwd_mode;
> +

Why not define named enum and use it here, instead of 'int'?

>  /*
>   * Receive Side Scaling (RSS) configuration.
>   */
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index bdfbfd36d3..f70397ad26 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -116,6 +116,13 @@ enum {
>  	QUEUE_JOB_TYPE_ACTION_QUERY,
>  };
>  
> +enum {
> +	NOISY_FWD_MODE_IO,
> +	NOISY_FWD_MODE_MAC,
> +	NOISY_FWD_MODE_MACSWAP,
> +	NOISY_FWD_MODE_5TSWAP
> +};
> +
>  /**
>   * The data structure associated with RX and TX packet burst statistics
>   * that are recorded for each forwarding stream.
> @@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
>  extern uint64_t noisy_lkup_num_writes;
>  extern uint64_t noisy_lkup_num_reads;
>  extern uint64_t noisy_lkup_num_reads_writes;
> +extern int noisy_fwd_mode;
>  
>  extern uint8_t dcb_config;
>  
> diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
> index 57b23241cf..fcca3e8921 100644
> --- a/doc/guides/testpmd_app_ug/run_app.rst
> +++ b/doc/guides/testpmd_app_ug/run_app.rst
> @@ -519,6 +519,15 @@ The command line options are:
>      Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
>      Only available with the noisy forwarding mode. The default value is 0.
>  
> +*   ``--noisy-fwd-mode=mode``
> +
> +    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
> +
> +       io (the default)
> +       mac
> +       macswap
> +       5tswap
> +
>  *   ``--no-iova-contig``
>  
>      Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v5] app/testpmd: expand noisy neighbour forward mode support
  2023-06-02 18:29 ` [PATCH v4] " Mike Pattrick
  2023-06-06 14:27   ` Ferruh Yigit
@ 2023-06-06 21:12   ` Mike Pattrick
  2023-06-06 21:37     ` Ferruh Yigit
                       ` (2 more replies)
  1 sibling, 3 replies; 18+ messages in thread
From: Mike Pattrick @ 2023-06-06 21:12 UTC (permalink / raw)
  To: Aman Singh, Yuying Zhang; +Cc: ktraynor, dev, Mike Pattrick

Previously the noisy neighbour vnf simulation would only operate in io
mode, forwarding packets as is. However, this limited the usefulness of
noisy neighbour simulation.

This feature has now been expanded to supporting mac, macswap, and
5tswap modes. To facilitate adding this support, some new header files
were added.

Signed-off-by: Mike Pattrick <mkp@redhat.com>
 ---
 v2: Reverted changes to random memory lookup
 v3: Refactored entire patch
 v4: Implemented recommended formatting changes
 v5: Corrected copyright statement and formatting changes
---
 app/test-pmd/5tswap.c                 | 118 +----------------------
 app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
 app/test-pmd/macfwd.c                 |  33 +------
 app/test-pmd/macfwd.h                 |  45 +++++++++
 app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
 app/test-pmd/parameters.c             |  17 ++++
 app/test-pmd/testpmd.c                |   5 +
 app/test-pmd/testpmd.h                |   8 ++
 doc/guides/testpmd_app_ug/run_app.rst |   9 ++
 9 files changed, 309 insertions(+), 162 deletions(-)
 create mode 100644 app/test-pmd/5tswap.h
 create mode 100644 app/test-pmd/macfwd.h

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index ff8c2dcde5..8e8de2557a 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -17,64 +17,8 @@
 #include <rte_ip.h>
 #include <rte_flow.h>
 
-#include "macswap_common.h"
 #include "testpmd.h"
-
-
-static inline void
-swap_mac(struct rte_ether_hdr *eth_hdr)
-{
-	struct rte_ether_addr addr;
-
-	/* Swap dest and src mac addresses. */
-	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
-	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
-	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
-}
-
-static inline void
-swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
-{
-	rte_be32_t addr;
-
-	/* Swap dest and src ipv4 addresses. */
-	addr = ipv4_hdr->src_addr;
-	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
-	ipv4_hdr->dst_addr = addr;
-}
-
-static inline void
-swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
-{
-	uint8_t addr[16];
-
-	/* Swap dest and src ipv6 addresses. */
-	memcpy(&addr, &ipv6_hdr->src_addr, 16);
-	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
-	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
-}
-
-static inline void
-swap_tcp(struct rte_tcp_hdr *tcp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src tcp port. */
-	port = tcp_hdr->src_port;
-	tcp_hdr->src_port = tcp_hdr->dst_port;
-	tcp_hdr->dst_port = port;
-}
-
-static inline void
-swap_udp(struct rte_udp_hdr *udp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src udp port */
-	port = udp_hdr->src_port;
-	udp_hdr->src_port = udp_hdr->dst_port;
-	udp_hdr->dst_port = port;
-}
+#include "5tswap.h"
 
 /*
  * 5 tuple swap forwarding mode: Swap the source and the destination of layers
@@ -85,22 +29,7 @@ static bool
 pkt_burst_5tuple_swap(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf *mb;
-	uint16_t next_proto;
-	uint64_t ol_flags;
-	uint16_t proto;
 	uint16_t nb_rx;
-	int i;
-	union {
-		struct rte_ether_hdr *eth;
-		struct rte_vlan_hdr *vlan;
-		struct rte_ipv4_hdr *ipv4;
-		struct rte_ipv6_hdr *ipv6;
-		struct rte_tcp_hdr *tcp;
-		struct rte_udp_hdr *udp;
-		uint8_t *byte;
-	} h;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
-	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
-					void *));
-		mb = pkts_burst[i];
-		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		proto = h.eth->ether_type;
-		swap_mac(h.eth);
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		h.eth++;
-		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			proto = h.vlan->eth_proto;
-			h.vlan++;
-			mb->l2_len += sizeof(struct rte_vlan_hdr);
-		}
-		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
-			swap_ipv4(h.ipv4);
-			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
-			h.byte += mb->l3_len;
-		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
-			swap_ipv6(h.ipv6);
-			next_proto = h.ipv6->proto;
-			h.ipv6++;
-			mb->l3_len = sizeof(struct rte_ipv6_hdr);
-		} else {
-			mbuf_field_set(mb, ol_flags);
-			continue;
-		}
-		if (next_proto == IPPROTO_UDP) {
-			swap_udp(h.udp);
-			mb->l4_len = sizeof(struct rte_udp_hdr);
-		} else if (next_proto == IPPROTO_TCP) {
-			swap_tcp(h.tcp);
-			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
-		}
-		mbuf_field_set(mb, ol_flags);
-	}
+	do_5tswap(pkts_burst, nb_rx, fs);
+
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
 	return true;
diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
new file mode 100644
index 0000000000..345c08b4d0
--- /dev/null
+++ b/app/test-pmd/5tswap.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
+ */
+
+#ifndef _5TSWAP_H_
+#define _5TSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+swap_mac(struct rte_ether_hdr *eth_hdr)
+{
+	struct rte_ether_addr addr;
+
+	/* Swap dest and src mac addresses. */
+	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
+	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
+	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
+}
+
+static inline void
+swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
+{
+	rte_be32_t addr;
+
+	/* Swap dest and src ipv4 addresses. */
+	addr = ipv4_hdr->src_addr;
+	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
+	ipv4_hdr->dst_addr = addr;
+}
+
+static inline void
+swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
+{
+	uint8_t addr[16];
+
+	/* Swap dest and src ipv6 addresses. */
+	memcpy(&addr, &ipv6_hdr->src_addr, 16);
+	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
+	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
+}
+
+static inline void
+swap_tcp(struct rte_tcp_hdr *tcp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src tcp port. */
+	port = tcp_hdr->src_port;
+	tcp_hdr->src_port = tcp_hdr->dst_port;
+	tcp_hdr->dst_port = port;
+}
+
+static inline void
+swap_udp(struct rte_udp_hdr *udp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src udp port */
+	port = udp_hdr->src_port;
+	udp_hdr->src_port = udp_hdr->dst_port;
+	udp_hdr->dst_port = port;
+}
+
+static inline void
+do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_port  *txp;
+	struct rte_mbuf *mb;
+	uint16_t next_proto;
+	uint64_t ol_flags;
+	uint16_t proto;
+	int i;
+	union {
+		struct rte_ether_hdr *eth;
+		struct rte_vlan_hdr *vlan;
+		struct rte_ipv4_hdr *ipv4;
+		struct rte_ipv6_hdr *ipv6;
+		struct rte_tcp_hdr *tcp;
+		struct rte_udp_hdr *udp;
+		uint8_t *byte;
+	} h;
+
+	txp = &ports[fs->tx_port];
+	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
+		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
+						       void *));
+		mb = pkts_burst[i];
+		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		proto = h.eth->ether_type;
+		swap_mac(h.eth);
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		h.eth++;
+		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			proto = h.vlan->eth_proto;
+			h.vlan++;
+			mb->l2_len += sizeof(struct rte_vlan_hdr);
+		}
+		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
+			swap_ipv4(h.ipv4);
+			next_proto = h.ipv4->next_proto_id;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
+			h.byte += mb->l3_len;
+		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
+			swap_ipv6(h.ipv6);
+			next_proto = h.ipv6->proto;
+			h.ipv6++;
+			mb->l3_len = sizeof(struct rte_ipv6_hdr);
+		} else {
+			mbuf_field_set(mb, ol_flags);
+			continue;
+		}
+		if (next_proto == IPPROTO_UDP) {
+			swap_udp(h.udp);
+			mb->l4_len = sizeof(struct rte_udp_hdr);
+		} else if (next_proto == IPPROTO_TCP) {
+			swap_tcp(h.tcp);
+			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
+		}
+		mbuf_field_set(mb, ol_flags);
+	}
+}
+
+#endif /* _5TSWAP_H_ */
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index 7316d73315..d19ace7395 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -35,6 +35,7 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#include "macfwd.h"
 
 /*
  * Forwarding of packets in MAC mode.
@@ -45,13 +46,7 @@ static bool
 pkt_burst_mac_forward(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf  *mb;
-	struct rte_ether_hdr *eth_hdr;
 	uint16_t nb_rx;
-	uint16_t i;
-	uint64_t ol_flags = 0;
-	uint64_t tx_offloads;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	tx_offloads = txp->dev_conf.txmode.offloads;
-	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
-		ol_flags = RTE_MBUF_F_TX_VLAN;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_QINQ;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_MACSEC;
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
-						       void *));
-		mb = pkts_burst[i];
-		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
-				&eth_hdr->dst_addr);
-		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
-				&eth_hdr->src_addr);
-		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
-		mb->ol_flags |= ol_flags;
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		mb->l3_len = sizeof(struct rte_ipv4_hdr);
-		mb->vlan_tci = txp->tx_vlan_id;
-		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
-	}
+	do_macfwd(pkts_burst, nb_rx, fs);
 
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
new file mode 100644
index 0000000000..ae2346e589
--- /dev/null
+++ b/app/test-pmd/macfwd.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _MACFWD_H_
+#define _MACFWD_H_
+
+static inline void
+do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_ether_hdr *eth_hdr;
+	uint64_t ol_flags = 0;
+	uint64_t tx_offloads;
+	struct rte_mbuf  *mb;
+	struct rte_port *txp = &ports[fs->tx_port];
+	uint16_t i;
+
+	tx_offloads = txp->dev_conf.txmode.offloads;
+	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
+		ol_flags = RTE_MBUF_F_TX_VLAN;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_QINQ;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_MACSEC;
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+						       void *));
+		mb = pkts_burst[i];
+		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+				    &eth_hdr->dst_addr);
+		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+				    &eth_hdr->src_addr);
+		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
+		mb->ol_flags |= ol_flags;
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		mb->l3_len = sizeof(struct rte_ipv4_hdr);
+		mb->vlan_tci = txp->tx_vlan_id;
+		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+	}
+}
+
+#endif /* _MACFWD_H_ */
diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
index 2bf90a983c..9b33930cab 100644
--- a/app/test-pmd/noisy_vnf.c
+++ b/app/test-pmd/noisy_vnf.c
@@ -32,6 +32,18 @@
 #include <rte_malloc.h>
 
 #include "testpmd.h"
+#include "5tswap.h"
+#include "macfwd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(__ARM_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
 
 struct noisy_config {
 	struct rte_ring *f;
@@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
 {
 	uint16_t i, j;
 
-	if (!ncf->do_sim)
-		return;
-
 	for (i = 0; i < nb_pkts; i++) {
 		for (j = 0; j < noisy_lkup_num_writes; j++)
 			do_write(ncf->vnf_mem);
@@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
  *    out of the FIFO
  * 4. Cases 2 and 3 combined
  */
-static bool
-pkt_burst_noisy_vnf(struct fwd_stream *fs)
+static uint16_t
+noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
 {
 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
 	uint16_t nb_deqd = 0;
-	uint16_t nb_rx = 0;
 	uint16_t nb_tx = 0;
 	uint16_t nb_enqd;
 	unsigned int fifo_free;
@@ -126,12 +133,16 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 	bool needs_flush = false;
 	uint64_t now;
 
-	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
-	if (unlikely(nb_rx == 0))
-		goto flush;
+	if (unlikely(nb_rx == 0)) {
+		if (!ncf->do_buffering)
+			goto end;
+		else
+			goto flush;
+	}
 
 	if (!ncf->do_buffering) {
-		sim_memory_lookups(ncf, nb_rx);
+		if (ncf->do_sim)
+			sim_memory_lookups(ncf, nb_rx);
 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 		goto end;
 	}
@@ -150,7 +161,8 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
 	}
 
-	sim_memory_lookups(ncf, nb_enqd);
+	if (ncf->do_sim)
+		sim_memory_lookups(ncf, nb_enqd);
 
 flush:
 	if (ncf->do_flush) {
@@ -169,11 +181,64 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 		ncf->prev_time = rte_get_timer_cycles();
 	}
 end:
+	return nb_tx;
+}
+
+static bool
+pkt_burst_io(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
 	return nb_rx > 0 || nb_tx > 0;
 }
 
-#define NOISY_STRSIZE 256
-#define NOISY_RING "noisy_ring_%d\n"
+static bool
+pkt_burst_mac(struct fwd_stream *fs)
+{
+	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macfwd(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_burst_macswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_brust_5tswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_5tswap(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
 
 static void
 noisy_fwd_end(portid_t pi)
@@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
 			 "--noisy-lkup-memory-size must be > 0\n");
 	}
 
+	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
+		noisy_vnf_engine.packet_fwd = pkt_burst_io;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
+		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
+
 	return 0;
 }
 
@@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
 	.fwd_mode_name  = "noisy",
 	.port_fwd_begin = noisy_fwd_begin,
 	.port_fwd_end   = noisy_fwd_end,
-	.stream_init    = common_fwd_stream_init,
-	.packet_fwd     = pkt_burst_noisy_vnf,
+	.stream_init	= common_fwd_stream_init,
+	.packet_fwd     = pkt_burst_io,
 };
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3b37809baf..d29c65fef4 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -190,6 +190,7 @@ usage(char* progname)
 	       "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
 	       "    xmem: use anonymous memory to create and populate mempool\n"
 	       "    xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
+	printf("  --noisy-fwd-mode=<io|mac|macswap|5tswap>: set the sub-fwd mode, defaults to io\n");
 	printf("  --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
 	printf("  --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
 	printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
@@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
 		{ "noisy-lkup-num-writes",	1, 0, 0 },
 		{ "noisy-lkup-num-reads",	1, 0, 0 },
 		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
+		{ "noisy-fwd-mode",             1, 0, 0 },
 		{ "no-iova-contig",             0, 0, 0 },
 		{ "rx-mq-mode",                 1, 0, 0 },
 		{ "record-core-cycles",         0, 0, 0 },
@@ -1444,6 +1446,21 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE,
 						 "noisy-lkup-num-reads-writes must be >= 0\n");
 			}
+			if (!strcmp(lgopts[opt_idx].name,
+				    "noisy-fwd-mode")) {
+				if (!strcmp(optarg, "io"))
+					noisy_fwd_mode = NOISY_FWD_MODE_IO;
+				else if (!strcmp(optarg, "mac"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MAC;
+				else if (!strcmp(optarg, "macswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_MACSWAP;
+				else if (!strcmp(optarg, "5tswap"))
+					noisy_fwd_mode = NOISY_FWD_MODE_5TSWAP;
+				else
+					rte_exit(EXIT_FAILURE, "noisy-fwd-mode %s invalid -"
+						 " must be a valid noisy-fwd-mode value\n",
+						 optarg);
+			}
 			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
 				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
 
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5cb6f92523..ef6e3592ea 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -364,6 +364,11 @@ uint64_t noisy_lkup_num_reads;
  */
 uint64_t noisy_lkup_num_reads_writes;
 
+/*
+ * Configurable sub-forwarding mode for the noisy_vnf forwarding mode.
+ */
+enum noisy_fwd_mode noisy_fwd_mode;
+
 /*
  * Receive Side Scaling (RSS) configuration.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..5256e5c199 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -116,6 +116,13 @@ enum {
 	QUEUE_JOB_TYPE_ACTION_QUERY,
 };
 
+enum noisy_fwd_mode {
+	NOISY_FWD_MODE_IO,
+	NOISY_FWD_MODE_MAC,
+	NOISY_FWD_MODE_MACSWAP,
+	NOISY_FWD_MODE_5TSWAP
+};
+
 /**
  * The data structure associated with RX and TX packet burst statistics
  * that are recorded for each forwarding stream.
@@ -561,6 +568,7 @@ extern uint64_t noisy_lkup_mem_sz;
 extern uint64_t noisy_lkup_num_writes;
 extern uint64_t noisy_lkup_num_reads;
 extern uint64_t noisy_lkup_num_reads_writes;
+extern enum noisy_fwd_mode noisy_fwd_mode;
 
 extern uint8_t dcb_config;
 
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index 57b23241cf..fcca3e8921 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -519,6 +519,15 @@ The command line options are:
     Set the number of r/w accesses to be done in noisy neighbor simulation memory buffer to N.
     Only available with the noisy forwarding mode. The default value is 0.
 
+*   ``--noisy-fwd-mode=mode``
+
+    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
+
+       io (the default)
+       mac
+       macswap
+       5tswap
+
 *   ``--no-iova-contig``
 
     Enable to create mempool which is not IOVA contiguous. Valid only with --mp-alloc=anon.
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5] app/testpmd: expand noisy neighbour forward mode support
  2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
@ 2023-06-06 21:37     ` Ferruh Yigit
  2023-06-06 21:42       ` Ferruh Yigit
  2023-06-06 22:23     ` Ferruh Yigit
  2023-06-08  9:59     ` [PATCH v6] " Mike Pattrick
  2 siblings, 1 reply; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-06 21:37 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: ktraynor, dev

On 6/6/2023 10:12 PM, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>  ---
>  v2: Reverted changes to random memory lookup
>  v3: Refactored entire patch
>  v4: Implemented recommended formatting changes
>  v5: Corrected copyright statement and formatting changes
>

Hi Mike,

There are some comments in v4 seems missed, can you please check the
comments?


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5] app/testpmd: expand noisy neighbour forward mode support
  2023-06-06 21:37     ` Ferruh Yigit
@ 2023-06-06 21:42       ` Ferruh Yigit
  0 siblings, 0 replies; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-06 21:42 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: ktraynor, dev

On 6/6/2023 10:37 PM, Ferruh Yigit wrote:
> On 6/6/2023 10:12 PM, Mike Pattrick wrote:
>> Previously the noisy neighbour vnf simulation would only operate in io
>> mode, forwarding packets as is. However, this limited the usefulness of
>> noisy neighbour simulation.
>>
>> This feature has now been expanded to supporting mac, macswap, and
>> 5tswap modes. To facilitate adding this support, some new header files
>> were added.
>>
>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>>  ---
>>  v2: Reverted changes to random memory lookup
>>  v3: Refactored entire patch
>>  v4: Implemented recommended formatting changes
>>  v5: Corrected copyright statement and formatting changes
>>
> 
> Hi Mike,
> 
> There are some comments in v4 seems missed, can you please check the
> comments?
> 

My bad, v5 looks good, I was looking to wrong places, let me
review/check this version.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5] app/testpmd: expand noisy neighbour forward mode support
  2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
  2023-06-06 21:37     ` Ferruh Yigit
@ 2023-06-06 22:23     ` Ferruh Yigit
  2023-06-07 15:42       ` Mike Pattrick
  2023-06-08  9:59     ` [PATCH v6] " Mike Pattrick
  2 siblings, 1 reply; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-06 22:23 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: ktraynor, dev

On 6/6/2023 10:12 PM, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>  ---
>  v2: Reverted changes to random memory lookup
>  v3: Refactored entire patch
>  v4: Implemented recommended formatting changes
>  v5: Corrected copyright statement and formatting changes

<...>

> @@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
>  			 "--noisy-lkup-memory-size must be > 0\n");
>  	}
>  
> +	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_io;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
> +	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
> +		noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
> +

When noisy forward mode is set, it is not possbile to see what mode is
set, what about keeping '.fwd_mode_name' longer,
like "noisy -        ", and update it based on selected mode?

This way "show config fwd" command displays selected noisy mode.

>  	return 0;
>  }
>  
> @@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
>  	.fwd_mode_name  = "noisy",
>  	.port_fwd_begin = noisy_fwd_begin,
>  	.port_fwd_end   = noisy_fwd_end,
> -	.stream_init    = common_fwd_stream_init,
> -	.packet_fwd     = pkt_burst_noisy_vnf,
> +	.stream_init	= common_fwd_stream_init,
> +	.packet_fwd     = pkt_burst_io,
>  };
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index 3b37809baf..d29c65fef4 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -190,6 +190,7 @@ usage(char* progname)
>  	       "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
>  	       "    xmem: use anonymous memory to create and populate mempool\n"
>  	       "    xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
> +	printf("  --noisy-fwd-mode=<io|mac|macswap|5tswap>: set the sub-fwd mode, defaults to io\n");

Main forwarding parameter is '--forward-mode=N', and while testing I
searched for 'forward' in the testpmd help output but not able to find
this command, because of shortened 'fwd'.

What do you think to have full '--noisy-forward-mode' to be more
consistent with existing '--forward-mode=N'?


>  	printf("  --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
>  	printf("  --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
>  	printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
> @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
>  		{ "noisy-lkup-num-writes",	1, 0, 0 },
>  		{ "noisy-lkup-num-reads",	1, 0, 0 },
>  		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
> +		{ "noisy-fwd-mode",             1, 0, 0 },

If there will be a new version can you please move it to the top of the
noisy-* block, as done in the help string?
And this is same for all new code, from 'extern' to global variable to
.rst documentation update.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v5] app/testpmd: expand noisy neighbour forward mode support
  2023-06-06 22:23     ` Ferruh Yigit
@ 2023-06-07 15:42       ` Mike Pattrick
  0 siblings, 0 replies; 18+ messages in thread
From: Mike Pattrick @ 2023-06-07 15:42 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: Aman Singh, Yuying Zhang, ktraynor, dev

On Tue, Jun 6, 2023 at 6:23 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/6/2023 10:12 PM, Mike Pattrick wrote:
> > Previously the noisy neighbour vnf simulation would only operate in io
> > mode, forwarding packets as is. However, this limited the usefulness of
> > noisy neighbour simulation.
> >
> > This feature has now been expanded to supporting mac, macswap, and
> > 5tswap modes. To facilitate adding this support, some new header files
> > were added.
> >
> > Signed-off-by: Mike Pattrick <mkp@redhat.com>
> >  ---
> >  v2: Reverted changes to random memory lookup
> >  v3: Refactored entire patch
> >  v4: Implemented recommended formatting changes
> >  v5: Corrected copyright statement and formatting changes
>
> <...>
>
> > @@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
> >                        "--noisy-lkup-memory-size must be > 0\n");
> >       }
> >
> > +     if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_io;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_mac;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
> > +             noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
> > +     else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
> > +             noisy_vnf_engine.packet_fwd = pkt_brust_5tswap;
> > +
>
> When noisy forward mode is set, it is not possbile to see what mode is
> set, what about keeping '.fwd_mode_name' longer,
> like "noisy -        ", and update it based on selected mode?
>
> This way "show config fwd" command displays selected noisy mode.
>
> >       return 0;
> >  }
> >
> > @@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
> >       .fwd_mode_name  = "noisy",
> >       .port_fwd_begin = noisy_fwd_begin,
> >       .port_fwd_end   = noisy_fwd_end,
> > -     .stream_init    = common_fwd_stream_init,
> > -     .packet_fwd     = pkt_burst_noisy_vnf,
> > +     .stream_init    = common_fwd_stream_init,
> > +     .packet_fwd     = pkt_burst_io,
> >  };
> > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> > index 3b37809baf..d29c65fef4 100644
> > --- a/app/test-pmd/parameters.c
> > +++ b/app/test-pmd/parameters.c
> > @@ -190,6 +190,7 @@ usage(char* progname)
> >              "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
> >              "    xmem: use anonymous memory to create and populate mempool\n"
> >              "    xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
> > +     printf("  --noisy-fwd-mode=<io|mac|macswap|5tswap>: set the sub-fwd mode, defaults to io\n");
>
> Main forwarding parameter is '--forward-mode=N', and while testing I
> searched for 'forward' in the testpmd help output but not able to find
> this command, because of shortened 'fwd'.
>
> What do you think to have full '--noisy-forward-mode' to be more
> consistent with existing '--forward-mode=N'?
>
>
> >       printf("  --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
> >       printf("  --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
> >       printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
> > @@ -704,6 +705,7 @@ launch_args_parse(int argc, char** argv)
> >               { "noisy-lkup-num-writes",      1, 0, 0 },
> >               { "noisy-lkup-num-reads",       1, 0, 0 },
> >               { "noisy-lkup-num-reads-writes", 1, 0, 0 },
> > +             { "noisy-fwd-mode",             1, 0, 0 },
>
> If there will be a new version can you please move it to the top of the
> noisy-* block, as done in the help string?
> And this is same for all new code, from 'extern' to global variable to
> .rst documentation update.

You've made some good suggestions here, I'll send you a new version.


Thanks for the review,
M

>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v6] app/testpmd: expand noisy neighbour forward mode support
  2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
  2023-06-06 21:37     ` Ferruh Yigit
  2023-06-06 22:23     ` Ferruh Yigit
@ 2023-06-08  9:59     ` Mike Pattrick
  2023-06-08 10:25       ` Ferruh Yigit
  2023-06-08 13:31       ` [PATCH v7] " Mike Pattrick
  2 siblings, 2 replies; 18+ messages in thread
From: Mike Pattrick @ 2023-06-08  9:59 UTC (permalink / raw)
  To: Aman Singh, Yuying Zhang; +Cc: ktraynor, dev, Mike Pattrick

Previously the noisy neighbour vnf simulation would only operate in io
mode, forwarding packets as is. However, this limited the usefulness of
noisy neighbour simulation.

This feature has now been expanded to supporting mac, macswap, and
5tswap modes. To facilitate adding this support, some new header files
were added.

Signed-off-by: Mike Pattrick <mkp@redhat.com>
 ---
 v2: Reverted changes to random memory lookup
 v3: Refactored entire patch
 v4: Implemented recommended formatting changes
 v5: Corrected copyright statement and formatting changes
 v6: Reordered some variables, preserved noisy subtype for display
---
 app/test-pmd/5tswap.c                 | 118 +----------------------
 app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
 app/test-pmd/config.c                 |  18 +++-
 app/test-pmd/macfwd.c                 |  33 +------
 app/test-pmd/macfwd.h                 |  45 +++++++++
 app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
 app/test-pmd/parameters.c             |  15 +++
 app/test-pmd/testpmd.c                |  14 +++
 app/test-pmd/testpmd.h                |  10 ++
 doc/guides/testpmd_app_ug/run_app.rst |   9 ++
 10 files changed, 334 insertions(+), 164 deletions(-)
 create mode 100644 app/test-pmd/5tswap.h
 create mode 100644 app/test-pmd/macfwd.h

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index ff8c2dcde5..8e8de2557a 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -17,64 +17,8 @@
 #include <rte_ip.h>
 #include <rte_flow.h>
 
-#include "macswap_common.h"
 #include "testpmd.h"
-
-
-static inline void
-swap_mac(struct rte_ether_hdr *eth_hdr)
-{
-	struct rte_ether_addr addr;
-
-	/* Swap dest and src mac addresses. */
-	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
-	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
-	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
-}
-
-static inline void
-swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
-{
-	rte_be32_t addr;
-
-	/* Swap dest and src ipv4 addresses. */
-	addr = ipv4_hdr->src_addr;
-	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
-	ipv4_hdr->dst_addr = addr;
-}
-
-static inline void
-swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
-{
-	uint8_t addr[16];
-
-	/* Swap dest and src ipv6 addresses. */
-	memcpy(&addr, &ipv6_hdr->src_addr, 16);
-	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
-	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
-}
-
-static inline void
-swap_tcp(struct rte_tcp_hdr *tcp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src tcp port. */
-	port = tcp_hdr->src_port;
-	tcp_hdr->src_port = tcp_hdr->dst_port;
-	tcp_hdr->dst_port = port;
-}
-
-static inline void
-swap_udp(struct rte_udp_hdr *udp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src udp port */
-	port = udp_hdr->src_port;
-	udp_hdr->src_port = udp_hdr->dst_port;
-	udp_hdr->dst_port = port;
-}
+#include "5tswap.h"
 
 /*
  * 5 tuple swap forwarding mode: Swap the source and the destination of layers
@@ -85,22 +29,7 @@ static bool
 pkt_burst_5tuple_swap(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf *mb;
-	uint16_t next_proto;
-	uint64_t ol_flags;
-	uint16_t proto;
 	uint16_t nb_rx;
-	int i;
-	union {
-		struct rte_ether_hdr *eth;
-		struct rte_vlan_hdr *vlan;
-		struct rte_ipv4_hdr *ipv4;
-		struct rte_ipv6_hdr *ipv6;
-		struct rte_tcp_hdr *tcp;
-		struct rte_udp_hdr *udp;
-		uint8_t *byte;
-	} h;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
-	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
-					void *));
-		mb = pkts_burst[i];
-		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		proto = h.eth->ether_type;
-		swap_mac(h.eth);
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		h.eth++;
-		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			proto = h.vlan->eth_proto;
-			h.vlan++;
-			mb->l2_len += sizeof(struct rte_vlan_hdr);
-		}
-		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
-			swap_ipv4(h.ipv4);
-			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
-			h.byte += mb->l3_len;
-		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
-			swap_ipv6(h.ipv6);
-			next_proto = h.ipv6->proto;
-			h.ipv6++;
-			mb->l3_len = sizeof(struct rte_ipv6_hdr);
-		} else {
-			mbuf_field_set(mb, ol_flags);
-			continue;
-		}
-		if (next_proto == IPPROTO_UDP) {
-			swap_udp(h.udp);
-			mb->l4_len = sizeof(struct rte_udp_hdr);
-		} else if (next_proto == IPPROTO_TCP) {
-			swap_tcp(h.tcp);
-			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
-		}
-		mbuf_field_set(mb, ol_flags);
-	}
+	do_5tswap(pkts_burst, nb_rx, fs);
+
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
 	return true;
diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
new file mode 100644
index 0000000000..345c08b4d0
--- /dev/null
+++ b/app/test-pmd/5tswap.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
+ */
+
+#ifndef _5TSWAP_H_
+#define _5TSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+swap_mac(struct rte_ether_hdr *eth_hdr)
+{
+	struct rte_ether_addr addr;
+
+	/* Swap dest and src mac addresses. */
+	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
+	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
+	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
+}
+
+static inline void
+swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
+{
+	rte_be32_t addr;
+
+	/* Swap dest and src ipv4 addresses. */
+	addr = ipv4_hdr->src_addr;
+	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
+	ipv4_hdr->dst_addr = addr;
+}
+
+static inline void
+swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
+{
+	uint8_t addr[16];
+
+	/* Swap dest and src ipv6 addresses. */
+	memcpy(&addr, &ipv6_hdr->src_addr, 16);
+	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
+	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
+}
+
+static inline void
+swap_tcp(struct rte_tcp_hdr *tcp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src tcp port. */
+	port = tcp_hdr->src_port;
+	tcp_hdr->src_port = tcp_hdr->dst_port;
+	tcp_hdr->dst_port = port;
+}
+
+static inline void
+swap_udp(struct rte_udp_hdr *udp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src udp port */
+	port = udp_hdr->src_port;
+	udp_hdr->src_port = udp_hdr->dst_port;
+	udp_hdr->dst_port = port;
+}
+
+static inline void
+do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_port  *txp;
+	struct rte_mbuf *mb;
+	uint16_t next_proto;
+	uint64_t ol_flags;
+	uint16_t proto;
+	int i;
+	union {
+		struct rte_ether_hdr *eth;
+		struct rte_vlan_hdr *vlan;
+		struct rte_ipv4_hdr *ipv4;
+		struct rte_ipv6_hdr *ipv6;
+		struct rte_tcp_hdr *tcp;
+		struct rte_udp_hdr *udp;
+		uint8_t *byte;
+	} h;
+
+	txp = &ports[fs->tx_port];
+	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
+		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
+						       void *));
+		mb = pkts_burst[i];
+		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		proto = h.eth->ether_type;
+		swap_mac(h.eth);
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		h.eth++;
+		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			proto = h.vlan->eth_proto;
+			h.vlan++;
+			mb->l2_len += sizeof(struct rte_vlan_hdr);
+		}
+		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
+			swap_ipv4(h.ipv4);
+			next_proto = h.ipv4->next_proto_id;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
+			h.byte += mb->l3_len;
+		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
+			swap_ipv6(h.ipv6);
+			next_proto = h.ipv6->proto;
+			h.ipv6++;
+			mb->l3_len = sizeof(struct rte_ipv6_hdr);
+		} else {
+			mbuf_field_set(mb, ol_flags);
+			continue;
+		}
+		if (next_proto == IPPROTO_UDP) {
+			swap_udp(h.udp);
+			mb->l4_len = sizeof(struct rte_udp_hdr);
+		} else if (next_proto == IPPROTO_TCP) {
+			swap_tcp(h.tcp);
+			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
+		}
+		mbuf_field_set(mb, ol_flags);
+	}
+}
+
+#endif /* _5TSWAP_H_ */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 096c218c12..a3e2c2ac15 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -4052,9 +4052,16 @@ rxtx_config_display(void)
 {
 	portid_t pid;
 	queueid_t qid;
+	char buf[32];
+
+	if (cur_fwd_eng == &noisy_vnf_engine)
+		snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
+	else
+		buf[0] = '\0';
 
-	printf("  %s packet forwarding%s packets/burst=%d\n",
+	printf("  %s%s packet forwarding%s packets/burst=%d\n",
 	       cur_fwd_eng->fwd_mode_name,
+	       buf,
 	       retry_enabled == 0 ? "" : " with retry",
 	       nb_pkt_per_burst);
 
@@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
 	struct fwd_stream *fs;
 	lcoreid_t  lc_id;
 	streamid_t sm_id;
+	char buf[32];
+
+	if (cfg->fwd_eng == &noisy_vnf_engine)
+		snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
+	else
+		buf[0] = '\0';
 
-	printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
+	printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
 		"NUMA support %s, MP allocation mode: %s\n",
 		cfg->fwd_eng->fwd_mode_name,
+		buf,
 		retry_enabled == 0 ? "" : " with retry",
 		cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
 		numa_support == 1 ? "enabled" : "disabled",
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index 7316d73315..d19ace7395 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -35,6 +35,7 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#include "macfwd.h"
 
 /*
  * Forwarding of packets in MAC mode.
@@ -45,13 +46,7 @@ static bool
 pkt_burst_mac_forward(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf  *mb;
-	struct rte_ether_hdr *eth_hdr;
 	uint16_t nb_rx;
-	uint16_t i;
-	uint64_t ol_flags = 0;
-	uint64_t tx_offloads;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	tx_offloads = txp->dev_conf.txmode.offloads;
-	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
-		ol_flags = RTE_MBUF_F_TX_VLAN;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_QINQ;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_MACSEC;
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
-						       void *));
-		mb = pkts_burst[i];
-		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
-				&eth_hdr->dst_addr);
-		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
-				&eth_hdr->src_addr);
-		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
-		mb->ol_flags |= ol_flags;
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		mb->l3_len = sizeof(struct rte_ipv4_hdr);
-		mb->vlan_tci = txp->tx_vlan_id;
-		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
-	}
+	do_macfwd(pkts_burst, nb_rx, fs);
 
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
new file mode 100644
index 0000000000..ae2346e589
--- /dev/null
+++ b/app/test-pmd/macfwd.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _MACFWD_H_
+#define _MACFWD_H_
+
+static inline void
+do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_ether_hdr *eth_hdr;
+	uint64_t ol_flags = 0;
+	uint64_t tx_offloads;
+	struct rte_mbuf  *mb;
+	struct rte_port *txp = &ports[fs->tx_port];
+	uint16_t i;
+
+	tx_offloads = txp->dev_conf.txmode.offloads;
+	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
+		ol_flags = RTE_MBUF_F_TX_VLAN;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_QINQ;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_MACSEC;
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+						       void *));
+		mb = pkts_burst[i];
+		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+				    &eth_hdr->dst_addr);
+		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+				    &eth_hdr->src_addr);
+		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
+		mb->ol_flags |= ol_flags;
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		mb->l3_len = sizeof(struct rte_ipv4_hdr);
+		mb->vlan_tci = txp->tx_vlan_id;
+		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+	}
+}
+
+#endif /* _MACFWD_H_ */
diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
index 2bf90a983c..619660358d 100644
--- a/app/test-pmd/noisy_vnf.c
+++ b/app/test-pmd/noisy_vnf.c
@@ -32,6 +32,18 @@
 #include <rte_malloc.h>
 
 #include "testpmd.h"
+#include "5tswap.h"
+#include "macfwd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(__ARM_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
 
 struct noisy_config {
 	struct rte_ring *f;
@@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
 {
 	uint16_t i, j;
 
-	if (!ncf->do_sim)
-		return;
-
 	for (i = 0; i < nb_pkts; i++) {
 		for (j = 0; j < noisy_lkup_num_writes; j++)
 			do_write(ncf->vnf_mem);
@@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
  *    out of the FIFO
  * 4. Cases 2 and 3 combined
  */
-static bool
-pkt_burst_noisy_vnf(struct fwd_stream *fs)
+static uint16_t
+noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
 {
 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
 	uint16_t nb_deqd = 0;
-	uint16_t nb_rx = 0;
 	uint16_t nb_tx = 0;
 	uint16_t nb_enqd;
 	unsigned int fifo_free;
@@ -126,12 +133,16 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 	bool needs_flush = false;
 	uint64_t now;
 
-	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
-	if (unlikely(nb_rx == 0))
-		goto flush;
+	if (unlikely(nb_rx == 0)) {
+		if (!ncf->do_buffering)
+			goto end;
+		else
+			goto flush;
+	}
 
 	if (!ncf->do_buffering) {
-		sim_memory_lookups(ncf, nb_rx);
+		if (ncf->do_sim)
+			sim_memory_lookups(ncf, nb_rx);
 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 		goto end;
 	}
@@ -150,7 +161,8 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
 	}
 
-	sim_memory_lookups(ncf, nb_enqd);
+	if (ncf->do_sim)
+		sim_memory_lookups(ncf, nb_enqd);
 
 flush:
 	if (ncf->do_flush) {
@@ -169,11 +181,64 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 		ncf->prev_time = rte_get_timer_cycles();
 	}
 end:
+	return nb_tx;
+}
+
+static bool
+pkt_burst_io(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
 	return nb_rx > 0 || nb_tx > 0;
 }
 
-#define NOISY_STRSIZE 256
-#define NOISY_RING "noisy_ring_%d\n"
+static bool
+pkt_burst_mac(struct fwd_stream *fs)
+{
+	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macfwd(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_burst_macswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+static bool
+pkt_burst_5tswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_5tswap(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
 
 static void
 noisy_fwd_end(portid_t pi)
@@ -226,6 +291,15 @@ noisy_fwd_begin(portid_t pi)
 			 "--noisy-lkup-memory-size must be > 0\n");
 	}
 
+	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
+		noisy_vnf_engine.packet_fwd = pkt_burst_io;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
+		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_5tswap;
+
 	return 0;
 }
 
@@ -233,6 +307,6 @@ struct fwd_engine noisy_vnf_engine = {
 	.fwd_mode_name  = "noisy",
 	.port_fwd_begin = noisy_fwd_begin,
 	.port_fwd_end   = noisy_fwd_end,
-	.stream_init    = common_fwd_stream_init,
-	.packet_fwd     = pkt_burst_noisy_vnf,
+	.stream_init	= common_fwd_stream_init,
+	.packet_fwd     = pkt_burst_io,
 };
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3b37809baf..b676f2c6ae 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -190,6 +190,7 @@ usage(char* progname)
 	       "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
 	       "    xmem: use anonymous memory to create and populate mempool\n"
 	       "    xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
+	printf("  --noisy-forward-mode=<io|mac|macswap|5tswap>: set the sub-fwd mode, defaults to io\n");
 	printf("  --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
 	printf("  --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
 	printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
@@ -698,6 +699,7 @@ launch_args_parse(int argc, char** argv)
 		{ "mp-alloc",			1, 0, 0 },
 		{ "tx-ip",			1, 0, 0 },
 		{ "tx-udp",			1, 0, 0 },
+		{ "noisy-forward-mode",		1, 0, 0 },
 		{ "noisy-tx-sw-buffer-size",	1, 0, 0 },
 		{ "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
 		{ "noisy-lkup-memory",		1, 0, 0 },
@@ -1444,6 +1446,19 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE,
 						 "noisy-lkup-num-reads-writes must be >= 0\n");
 			}
+			if (!strcmp(lgopts[opt_idx].name,
+				    "noisy-forward-mode")) {
+				int i;
+				for (i = 0; i < NOISY_FWD_MODE_MAX; i++)
+					if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
+						noisy_fwd_mode = i;
+						break;
+					}
+				if (i == NOISY_FWD_MODE_MAX)
+					rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
+						 " must be a valid noisy-forward-mode value\n",
+						 optarg);
+			}
 			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
 				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
 
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5cb6f92523..c6ad9b18bf 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -330,6 +330,20 @@ int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
  */
 int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
 
+/*
+ * Configurable sub-forwarding mode for the noisy_vnf forwarding mode.
+ */
+enum noisy_fwd_mode noisy_fwd_mode;
+
+/* String version of enum noisy_fwd_mode */
+const char * const noisy_fwd_mode_desc[] = {
+	[NOISY_FWD_MODE_IO] = "io",
+	[NOISY_FWD_MODE_MAC] = "mac",
+	[NOISY_FWD_MODE_MACSWAP] = "macswap",
+	[NOISY_FWD_MODE_5TSWAP] = "5tswap",
+	[NOISY_FWD_MODE_MAX] = NULL,
+};
+
 /*
  * Configurable value of buffered packets before sending.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..734c2c99a1 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -116,6 +116,14 @@ enum {
 	QUEUE_JOB_TYPE_ACTION_QUERY,
 };
 
+enum noisy_fwd_mode {
+	NOISY_FWD_MODE_IO,
+	NOISY_FWD_MODE_MAC,
+	NOISY_FWD_MODE_MACSWAP,
+	NOISY_FWD_MODE_5TSWAP,
+	NOISY_FWD_MODE_MAX,
+};
+
 /**
  * The data structure associated with RX and TX packet burst statistics
  * that are recorded for each forwarding stream.
@@ -555,6 +563,8 @@ extern int8_t rx_drop_en;
 extern int16_t tx_free_thresh;
 extern int16_t tx_rs_thresh;
 
+extern enum noisy_fwd_mode noisy_fwd_mode;
+extern const char * const noisy_fwd_mode_desc[];
 extern uint16_t noisy_tx_sw_bufsz;
 extern uint16_t noisy_tx_sw_buf_flush_time;
 extern uint64_t noisy_lkup_mem_sz;
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index 57b23241cf..8319a30968 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -487,6 +487,15 @@ The command line options are:
     * xmemhuge: create and populate mempool using externally and anonymously
       allocated hugepage area
 
+*   ``--noisy-forward-mode=mode``
+
+    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
+
+       io (the default)
+       mac
+       macswap
+       5tswap
+
 *   ``--noisy-tx-sw-buffer-size``
 
     Set the number of maximum elements  of the FIFO queue to be created
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6] app/testpmd: expand noisy neighbour forward mode support
  2023-06-08  9:59     ` [PATCH v6] " Mike Pattrick
@ 2023-06-08 10:25       ` Ferruh Yigit
  2023-06-08 10:43         ` Mike Pattrick
  2023-06-08 13:31       ` [PATCH v7] " Mike Pattrick
  1 sibling, 1 reply; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-08 10:25 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: ktraynor, dev

On 6/8/2023 10:59 AM, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>  ---
>  v2: Reverted changes to random memory lookup
>  v3: Refactored entire patch
>  v4: Implemented recommended formatting changes
>  v5: Corrected copyright statement and formatting changes
>  v6: Reordered some variables, preserved noisy subtype for display
> ---
>  app/test-pmd/5tswap.c                 | 118 +----------------------
>  app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
>  app/test-pmd/config.c                 |  18 +++-
>  app/test-pmd/macfwd.c                 |  33 +------
>  app/test-pmd/macfwd.h                 |  45 +++++++++
>  app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
>  app/test-pmd/parameters.c             |  15 +++
>  app/test-pmd/testpmd.c                |  14 +++
>  app/test-pmd/testpmd.h                |  10 ++
>  doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>  10 files changed, 334 insertions(+), 164 deletions(-)
>  create mode 100644 app/test-pmd/5tswap.h
>  create mode 100644 app/test-pmd/macfwd.h
> 

<...>

> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 096c218c12..a3e2c2ac15 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -4052,9 +4052,16 @@ rxtx_config_display(void)
>  {
>  	portid_t pid;
>  	queueid_t qid;
> +	char buf[32];
> +
> +	if (cur_fwd_eng == &noisy_vnf_engine)
> +		snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
> +	else
> +		buf[0] = '\0';
>  
> -	printf("  %s packet forwarding%s packets/burst=%d\n",
> +	printf("  %s%s packet forwarding%s packets/burst=%d\n",
>  	       cur_fwd_eng->fwd_mode_name,
> +	       buf,
>  	       retry_enabled == 0 ? "" : " with retry",
>  	       nb_pkt_per_burst);
>  
> @@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
>  	struct fwd_stream *fs;
>  	lcoreid_t  lc_id;
>  	streamid_t sm_id;
> +	char buf[32];
> +
> +	if (cfg->fwd_eng == &noisy_vnf_engine)
> +		snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
> +	else
> +		buf[0] = '\0';
>  
> -	printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
> +	printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
>  		"NUMA support %s, MP allocation mode: %s\n",
>  		cfg->fwd_eng->fwd_mode_name,
> +		buf,
>  		retry_enabled == 0 ? "" : " with retry",
>  		cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
>  		numa_support == 1 ? "enabled" : "disabled",


This works but I wonder if we can keep the display functions generic (as
much as possible), without forwarding enginee specific checks.

What about the idea to update '.fwd_mode_name' in 'noisy_fwd_begin()'?
That way generic display code can stay as it is.

<...>

> +static bool
> +pkt_burst_mac(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_macfwd(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_burst_macswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
> +static bool
> +pkt_burst_5tswap(struct fwd_stream *fs)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx;
> +	uint16_t nb_tx;
> +
> +	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> +	if (likely(nb_rx != 0))
> +		do_5tswap(pkts_burst, nb_rx, fs);
> +	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> +
> +	return nb_rx > 0 || nb_tx > 0;
> +}
>  

Empty lines are missing between functions.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6] app/testpmd: expand noisy neighbour forward mode support
  2023-06-08 10:25       ` Ferruh Yigit
@ 2023-06-08 10:43         ` Mike Pattrick
  2023-06-08 11:42           ` Ferruh Yigit
  0 siblings, 1 reply; 18+ messages in thread
From: Mike Pattrick @ 2023-06-08 10:43 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: Aman Singh, Yuying Zhang, ktraynor, dev

On Thu, Jun 8, 2023 at 6:25 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/8/2023 10:59 AM, Mike Pattrick wrote:
> > Previously the noisy neighbour vnf simulation would only operate in io
> > mode, forwarding packets as is. However, this limited the usefulness of
> > noisy neighbour simulation.
> >
> > This feature has now been expanded to supporting mac, macswap, and
> > 5tswap modes. To facilitate adding this support, some new header files
> > were added.
> >
> > Signed-off-by: Mike Pattrick <mkp@redhat.com>
> >  ---
> >  v2: Reverted changes to random memory lookup
> >  v3: Refactored entire patch
> >  v4: Implemented recommended formatting changes
> >  v5: Corrected copyright statement and formatting changes
> >  v6: Reordered some variables, preserved noisy subtype for display
> > ---
> >  app/test-pmd/5tswap.c                 | 118 +----------------------
> >  app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
> >  app/test-pmd/config.c                 |  18 +++-
> >  app/test-pmd/macfwd.c                 |  33 +------
> >  app/test-pmd/macfwd.h                 |  45 +++++++++
> >  app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
> >  app/test-pmd/parameters.c             |  15 +++
> >  app/test-pmd/testpmd.c                |  14 +++
> >  app/test-pmd/testpmd.h                |  10 ++
> >  doc/guides/testpmd_app_ug/run_app.rst |   9 ++
> >  10 files changed, 334 insertions(+), 164 deletions(-)
> >  create mode 100644 app/test-pmd/5tswap.h
> >  create mode 100644 app/test-pmd/macfwd.h
> >
>
> <...>
>
> > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> > index 096c218c12..a3e2c2ac15 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -4052,9 +4052,16 @@ rxtx_config_display(void)
> >  {
> >       portid_t pid;
> >       queueid_t qid;
> > +     char buf[32];
> > +
> > +     if (cur_fwd_eng == &noisy_vnf_engine)
> > +             snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
> > +     else
> > +             buf[0] = '\0';
> >
> > -     printf("  %s packet forwarding%s packets/burst=%d\n",
> > +     printf("  %s%s packet forwarding%s packets/burst=%d\n",
> >              cur_fwd_eng->fwd_mode_name,
> > +            buf,
> >              retry_enabled == 0 ? "" : " with retry",
> >              nb_pkt_per_burst);
> >
> > @@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
> >       struct fwd_stream *fs;
> >       lcoreid_t  lc_id;
> >       streamid_t sm_id;
> > +     char buf[32];
> > +
> > +     if (cfg->fwd_eng == &noisy_vnf_engine)
> > +             snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
> > +     else
> > +             buf[0] = '\0';
> >
> > -     printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
> > +     printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
> >               "NUMA support %s, MP allocation mode: %s\n",
> >               cfg->fwd_eng->fwd_mode_name,
> > +             buf,
> >               retry_enabled == 0 ? "" : " with retry",
> >               cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
> >               numa_support == 1 ? "enabled" : "disabled",
>
>
> This works but I wonder if we can keep the display functions generic (as
> much as possible), without forwarding enginee specific checks.
>
> What about the idea to update '.fwd_mode_name' in 'noisy_fwd_begin()'?
> That way generic display code can stay as it is.

I worried that this would interfere with set_pkt_forwarding_mode()
among other functions. The .fwd_mode_name seems to play double duty as
view and model.

I was also thinking about adding another member to struct fwd_engine
to display subtype / internal status. But I couldn't think of a
compelling use case in the other modules. So I leaned towards this
implementation.

Which do you prefer?

>
> <...>
>
> > +static bool
> > +pkt_burst_mac(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx;
> > +     uint16_t nb_tx;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     if (likely(nb_rx != 0))
> > +             do_macfwd(pkts_burst, nb_rx, fs);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> > +static bool
> > +pkt_burst_macswap(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx;
> > +     uint16_t nb_tx;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     if (likely(nb_rx != 0))
> > +             do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> > +static bool
> > +pkt_burst_5tswap(struct fwd_stream *fs)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx;
> > +     uint16_t nb_tx;
> > +
> > +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
> > +     if (likely(nb_rx != 0))
> > +             do_5tswap(pkts_burst, nb_rx, fs);
> > +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
> > +
> > +     return nb_rx > 0 || nb_tx > 0;
> > +}
> >
>
> Empty lines are missing between functions.
>
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6] app/testpmd: expand noisy neighbour forward mode support
  2023-06-08 10:43         ` Mike Pattrick
@ 2023-06-08 11:42           ` Ferruh Yigit
  0 siblings, 0 replies; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-08 11:42 UTC (permalink / raw)
  To: Mike Pattrick; +Cc: Aman Singh, Yuying Zhang, ktraynor, dev

On 6/8/2023 11:43 AM, Mike Pattrick wrote:
> On Thu, Jun 8, 2023 at 6:25 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 6/8/2023 10:59 AM, Mike Pattrick wrote:
>>> Previously the noisy neighbour vnf simulation would only operate in io
>>> mode, forwarding packets as is. However, this limited the usefulness of
>>> noisy neighbour simulation.
>>>
>>> This feature has now been expanded to supporting mac, macswap, and
>>> 5tswap modes. To facilitate adding this support, some new header files
>>> were added.
>>>
>>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>>>  ---
>>>  v2: Reverted changes to random memory lookup
>>>  v3: Refactored entire patch
>>>  v4: Implemented recommended formatting changes
>>>  v5: Corrected copyright statement and formatting changes
>>>  v6: Reordered some variables, preserved noisy subtype for display
>>> ---
>>>  app/test-pmd/5tswap.c                 | 118 +----------------------
>>>  app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
>>>  app/test-pmd/config.c                 |  18 +++-
>>>  app/test-pmd/macfwd.c                 |  33 +------
>>>  app/test-pmd/macfwd.h                 |  45 +++++++++
>>>  app/test-pmd/noisy_vnf.c              | 106 +++++++++++++++++----
>>>  app/test-pmd/parameters.c             |  15 +++
>>>  app/test-pmd/testpmd.c                |  14 +++
>>>  app/test-pmd/testpmd.h                |  10 ++
>>>  doc/guides/testpmd_app_ug/run_app.rst |   9 ++
>>>  10 files changed, 334 insertions(+), 164 deletions(-)
>>>  create mode 100644 app/test-pmd/5tswap.h
>>>  create mode 100644 app/test-pmd/macfwd.h
>>>
>>
>> <...>
>>
>>> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
>>> index 096c218c12..a3e2c2ac15 100644
>>> --- a/app/test-pmd/config.c
>>> +++ b/app/test-pmd/config.c
>>> @@ -4052,9 +4052,16 @@ rxtx_config_display(void)
>>>  {
>>>       portid_t pid;
>>>       queueid_t qid;
>>> +     char buf[32];
>>> +
>>> +     if (cur_fwd_eng == &noisy_vnf_engine)
>>> +             snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
>>> +     else
>>> +             buf[0] = '\0';
>>>
>>> -     printf("  %s packet forwarding%s packets/burst=%d\n",
>>> +     printf("  %s%s packet forwarding%s packets/burst=%d\n",
>>>              cur_fwd_eng->fwd_mode_name,
>>> +            buf,
>>>              retry_enabled == 0 ? "" : " with retry",
>>>              nb_pkt_per_burst);
>>>
>>> @@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
>>>       struct fwd_stream *fs;
>>>       lcoreid_t  lc_id;
>>>       streamid_t sm_id;
>>> +     char buf[32];
>>> +
>>> +     if (cfg->fwd_eng == &noisy_vnf_engine)
>>> +             snprintf(buf, sizeof(buf), " (%s)", noisy_fwd_mode_desc[noisy_fwd_mode]);
>>> +     else
>>> +             buf[0] = '\0';
>>>
>>> -     printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
>>> +     printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
>>>               "NUMA support %s, MP allocation mode: %s\n",
>>>               cfg->fwd_eng->fwd_mode_name,
>>> +             buf,
>>>               retry_enabled == 0 ? "" : " with retry",
>>>               cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
>>>               numa_support == 1 ? "enabled" : "disabled",
>>
>>
>> This works but I wonder if we can keep the display functions generic (as
>> much as possible), without forwarding enginee specific checks.
>>
>> What about the idea to update '.fwd_mode_name' in 'noisy_fwd_begin()'?
>> That way generic display code can stay as it is.
> 
> I worried that this would interfere with set_pkt_forwarding_mode()
> among other functions. The .fwd_mode_name seems to play double duty as
> view and model.
> 

You are right.

> I was also thinking about adding another member to struct fwd_engine
> to display subtype / internal status. But I couldn't think of a
> compelling use case in the other modules. So I leaned towards this
> implementation.
> 
> Which do you prefer?
> 

I think adding a new field is more proper, although I don't expect to
have subtype for other forwarding modes, perhaps adding something like
"internal status" may be useful later.

>>
>> <...>
>>
>>> +static bool
>>> +pkt_burst_mac(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx;
>>> +     uint16_t nb_tx;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     if (likely(nb_rx != 0))
>>> +             do_macfwd(pkts_burst, nb_rx, fs);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>> +static bool
>>> +pkt_burst_macswap(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx;
>>> +     uint16_t nb_tx;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     if (likely(nb_rx != 0))
>>> +             do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>> +static bool
>>> +pkt_burst_5tswap(struct fwd_stream *fs)
>>> +{
>>> +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>>> +     uint16_t nb_rx;
>>> +     uint16_t nb_tx;
>>> +
>>> +     nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
>>> +     if (likely(nb_rx != 0))
>>> +             do_5tswap(pkts_burst, nb_rx, fs);
>>> +     nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
>>> +
>>> +     return nb_rx > 0 || nb_tx > 0;
>>> +}
>>>
>>
>> Empty lines are missing between functions.
>>
>>
> 


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v7] app/testpmd: expand noisy neighbour forward mode support
  2023-06-08  9:59     ` [PATCH v6] " Mike Pattrick
  2023-06-08 10:25       ` Ferruh Yigit
@ 2023-06-08 13:31       ` Mike Pattrick
  2023-06-08 14:32         ` Ferruh Yigit
  1 sibling, 1 reply; 18+ messages in thread
From: Mike Pattrick @ 2023-06-08 13:31 UTC (permalink / raw)
  To: Aman Singh, Yuying Zhang; +Cc: ktraynor, dev, Mike Pattrick

Previously the noisy neighbour vnf simulation would only operate in io
mode, forwarding packets as is. However, this limited the usefulness of
noisy neighbour simulation.

This feature has now been expanded to supporting mac, macswap, and
5tswap modes. To facilitate adding this support, some new header files
were added.

Signed-off-by: Mike Pattrick <mkp@redhat.com>
 ---
 v2: Reverted changes to random memory lookup
 v3: Refactored entire patch
 v4: Implemented recommended formatting changes
 v5: Corrected copyright statement and formatting changes
 v6: Reordered some variables, preserved noisy subtype for display
 v7: Made fwd engine status generic across all modules
---
 app/test-pmd/5tswap.c                 | 118 +----------------------
 app/test-pmd/5tswap.h                 | 130 ++++++++++++++++++++++++++
 app/test-pmd/config.c                 |  18 +++-
 app/test-pmd/macfwd.c                 |  33 +------
 app/test-pmd/macfwd.h                 |  45 +++++++++
 app/test-pmd/noisy_vnf.c              | 113 ++++++++++++++++++----
 app/test-pmd/parameters.c             |  15 +++
 app/test-pmd/testpmd.c                |  14 +++
 app/test-pmd/testpmd.h                |  11 +++
 doc/guides/testpmd_app_ug/run_app.rst |   9 ++
 10 files changed, 342 insertions(+), 164 deletions(-)
 create mode 100644 app/test-pmd/5tswap.h
 create mode 100644 app/test-pmd/macfwd.h

diff --git a/app/test-pmd/5tswap.c b/app/test-pmd/5tswap.c
index ff8c2dcde5..8e8de2557a 100644
--- a/app/test-pmd/5tswap.c
+++ b/app/test-pmd/5tswap.c
@@ -17,64 +17,8 @@
 #include <rte_ip.h>
 #include <rte_flow.h>
 
-#include "macswap_common.h"
 #include "testpmd.h"
-
-
-static inline void
-swap_mac(struct rte_ether_hdr *eth_hdr)
-{
-	struct rte_ether_addr addr;
-
-	/* Swap dest and src mac addresses. */
-	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
-	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
-	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
-}
-
-static inline void
-swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
-{
-	rte_be32_t addr;
-
-	/* Swap dest and src ipv4 addresses. */
-	addr = ipv4_hdr->src_addr;
-	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
-	ipv4_hdr->dst_addr = addr;
-}
-
-static inline void
-swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
-{
-	uint8_t addr[16];
-
-	/* Swap dest and src ipv6 addresses. */
-	memcpy(&addr, &ipv6_hdr->src_addr, 16);
-	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
-	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
-}
-
-static inline void
-swap_tcp(struct rte_tcp_hdr *tcp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src tcp port. */
-	port = tcp_hdr->src_port;
-	tcp_hdr->src_port = tcp_hdr->dst_port;
-	tcp_hdr->dst_port = port;
-}
-
-static inline void
-swap_udp(struct rte_udp_hdr *udp_hdr)
-{
-	rte_be16_t port;
-
-	/* Swap dest and src udp port */
-	port = udp_hdr->src_port;
-	udp_hdr->src_port = udp_hdr->dst_port;
-	udp_hdr->dst_port = port;
-}
+#include "5tswap.h"
 
 /*
  * 5 tuple swap forwarding mode: Swap the source and the destination of layers
@@ -85,22 +29,7 @@ static bool
 pkt_burst_5tuple_swap(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf *mb;
-	uint16_t next_proto;
-	uint64_t ol_flags;
-	uint16_t proto;
 	uint16_t nb_rx;
-	int i;
-	union {
-		struct rte_ether_hdr *eth;
-		struct rte_vlan_hdr *vlan;
-		struct rte_ipv4_hdr *ipv4;
-		struct rte_ipv6_hdr *ipv6;
-		struct rte_tcp_hdr *tcp;
-		struct rte_udp_hdr *udp;
-		uint8_t *byte;
-	} h;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -109,49 +38,8 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
-	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
-			txp->tx_vlan_id, txp->tx_vlan_id_outer);
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
-					void *));
-		mb = pkts_burst[i];
-		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		proto = h.eth->ether_type;
-		swap_mac(h.eth);
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		h.eth++;
-		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			proto = h.vlan->eth_proto;
-			h.vlan++;
-			mb->l2_len += sizeof(struct rte_vlan_hdr);
-		}
-		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
-			swap_ipv4(h.ipv4);
-			next_proto = h.ipv4->next_proto_id;
-			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
-			h.byte += mb->l3_len;
-		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
-			swap_ipv6(h.ipv6);
-			next_proto = h.ipv6->proto;
-			h.ipv6++;
-			mb->l3_len = sizeof(struct rte_ipv6_hdr);
-		} else {
-			mbuf_field_set(mb, ol_flags);
-			continue;
-		}
-		if (next_proto == IPPROTO_UDP) {
-			swap_udp(h.udp);
-			mb->l4_len = sizeof(struct rte_udp_hdr);
-		} else if (next_proto == IPPROTO_TCP) {
-			swap_tcp(h.tcp);
-			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
-		}
-		mbuf_field_set(mb, ol_flags);
-	}
+	do_5tswap(pkts_burst, nb_rx, fs);
+
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
 	return true;
diff --git a/app/test-pmd/5tswap.h b/app/test-pmd/5tswap.h
new file mode 100644
index 0000000000..345c08b4d0
--- /dev/null
+++ b/app/test-pmd/5tswap.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
+ */
+
+#ifndef _5TSWAP_H_
+#define _5TSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+swap_mac(struct rte_ether_hdr *eth_hdr)
+{
+	struct rte_ether_addr addr;
+
+	/* Swap dest and src mac addresses. */
+	rte_ether_addr_copy(&eth_hdr->dst_addr, &addr);
+	rte_ether_addr_copy(&eth_hdr->src_addr, &eth_hdr->dst_addr);
+	rte_ether_addr_copy(&addr, &eth_hdr->src_addr);
+}
+
+static inline void
+swap_ipv4(struct rte_ipv4_hdr *ipv4_hdr)
+{
+	rte_be32_t addr;
+
+	/* Swap dest and src ipv4 addresses. */
+	addr = ipv4_hdr->src_addr;
+	ipv4_hdr->src_addr = ipv4_hdr->dst_addr;
+	ipv4_hdr->dst_addr = addr;
+}
+
+static inline void
+swap_ipv6(struct rte_ipv6_hdr *ipv6_hdr)
+{
+	uint8_t addr[16];
+
+	/* Swap dest and src ipv6 addresses. */
+	memcpy(&addr, &ipv6_hdr->src_addr, 16);
+	memcpy(&ipv6_hdr->src_addr, &ipv6_hdr->dst_addr, 16);
+	memcpy(&ipv6_hdr->dst_addr, &addr, 16);
+}
+
+static inline void
+swap_tcp(struct rte_tcp_hdr *tcp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src tcp port. */
+	port = tcp_hdr->src_port;
+	tcp_hdr->src_port = tcp_hdr->dst_port;
+	tcp_hdr->dst_port = port;
+}
+
+static inline void
+swap_udp(struct rte_udp_hdr *udp_hdr)
+{
+	rte_be16_t port;
+
+	/* Swap dest and src udp port */
+	port = udp_hdr->src_port;
+	udp_hdr->src_port = udp_hdr->dst_port;
+	udp_hdr->dst_port = port;
+}
+
+static inline void
+do_5tswap(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_port  *txp;
+	struct rte_mbuf *mb;
+	uint16_t next_proto;
+	uint64_t ol_flags;
+	uint16_t proto;
+	int i;
+	union {
+		struct rte_ether_hdr *eth;
+		struct rte_vlan_hdr *vlan;
+		struct rte_ipv4_hdr *ipv4;
+		struct rte_ipv6_hdr *ipv6;
+		struct rte_tcp_hdr *tcp;
+		struct rte_udp_hdr *udp;
+		uint8_t *byte;
+	} h;
+
+	txp = &ports[fs->tx_port];
+	ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+	vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
+		      txp->tx_vlan_id, txp->tx_vlan_id_outer);
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i+1],
+						       void *));
+		mb = pkts_burst[i];
+		h.eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		proto = h.eth->ether_type;
+		swap_mac(h.eth);
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		h.eth++;
+		while (proto == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		       proto == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			proto = h.vlan->eth_proto;
+			h.vlan++;
+			mb->l2_len += sizeof(struct rte_vlan_hdr);
+		}
+		if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV4)) {
+			swap_ipv4(h.ipv4);
+			next_proto = h.ipv4->next_proto_id;
+			mb->l3_len = rte_ipv4_hdr_len(h.ipv4);
+			h.byte += mb->l3_len;
+		} else if (proto == RTE_BE16(RTE_ETHER_TYPE_IPV6)) {
+			swap_ipv6(h.ipv6);
+			next_proto = h.ipv6->proto;
+			h.ipv6++;
+			mb->l3_len = sizeof(struct rte_ipv6_hdr);
+		} else {
+			mbuf_field_set(mb, ol_flags);
+			continue;
+		}
+		if (next_proto == IPPROTO_UDP) {
+			swap_udp(h.udp);
+			mb->l4_len = sizeof(struct rte_udp_hdr);
+		} else if (next_proto == IPPROTO_TCP) {
+			swap_tcp(h.tcp);
+			mb->l4_len = (h.tcp->data_off & 0xf0) >> 2;
+		}
+		mbuf_field_set(mb, ol_flags);
+	}
+}
+
+#endif /* _5TSWAP_H_ */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 096c218c12..d55212bbad 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -4052,9 +4052,16 @@ rxtx_config_display(void)
 {
 	portid_t pid;
 	queueid_t qid;
+	char buf[32];
+
+	if (cur_fwd_eng->status)
+		snprintf(buf, sizeof(buf), " (%s)", cur_fwd_eng->status);
+	else
+		buf[0] = '\0';
 
-	printf("  %s packet forwarding%s packets/burst=%d\n",
+	printf("  %s%s packet forwarding%s packets/burst=%d\n",
 	       cur_fwd_eng->fwd_mode_name,
+	       buf,
 	       retry_enabled == 0 ? "" : " with retry",
 	       nb_pkt_per_burst);
 
@@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
 	struct fwd_stream *fs;
 	lcoreid_t  lc_id;
 	streamid_t sm_id;
+	char buf[32];
+
+	if (cfg->fwd_eng->status)
+		snprintf(buf, sizeof(buf), " (%s)", cfg->fwd_eng->status);
+	else
+		buf[0] = '\0';
 
-	printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
+	printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
 		"NUMA support %s, MP allocation mode: %s\n",
 		cfg->fwd_eng->fwd_mode_name,
+		buf,
 		retry_enabled == 0 ? "" : " with retry",
 		cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
 		numa_support == 1 ? "enabled" : "disabled",
diff --git a/app/test-pmd/macfwd.c b/app/test-pmd/macfwd.c
index 7316d73315..d19ace7395 100644
--- a/app/test-pmd/macfwd.c
+++ b/app/test-pmd/macfwd.c
@@ -35,6 +35,7 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#include "macfwd.h"
 
 /*
  * Forwarding of packets in MAC mode.
@@ -45,13 +46,7 @@ static bool
 pkt_burst_mac_forward(struct fwd_stream *fs)
 {
 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
-	struct rte_port  *txp;
-	struct rte_mbuf  *mb;
-	struct rte_ether_hdr *eth_hdr;
 	uint16_t nb_rx;
-	uint16_t i;
-	uint64_t ol_flags = 0;
-	uint64_t tx_offloads;
 
 	/*
 	 * Receive a burst of packets and forward them.
@@ -60,31 +55,7 @@ pkt_burst_mac_forward(struct fwd_stream *fs)
 	if (unlikely(nb_rx == 0))
 		return false;
 
-	txp = &ports[fs->tx_port];
-	tx_offloads = txp->dev_conf.txmode.offloads;
-	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
-		ol_flags = RTE_MBUF_F_TX_VLAN;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_QINQ;
-	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
-		ol_flags |= RTE_MBUF_F_TX_MACSEC;
-	for (i = 0; i < nb_rx; i++) {
-		if (likely(i < nb_rx - 1))
-			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
-						       void *));
-		mb = pkts_burst[i];
-		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
-		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
-				&eth_hdr->dst_addr);
-		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
-				&eth_hdr->src_addr);
-		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
-		mb->ol_flags |= ol_flags;
-		mb->l2_len = sizeof(struct rte_ether_hdr);
-		mb->l3_len = sizeof(struct rte_ipv4_hdr);
-		mb->vlan_tci = txp->tx_vlan_id;
-		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
-	}
+	do_macfwd(pkts_burst, nb_rx, fs);
 
 	common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 
diff --git a/app/test-pmd/macfwd.h b/app/test-pmd/macfwd.h
new file mode 100644
index 0000000000..ae2346e589
--- /dev/null
+++ b/app/test-pmd/macfwd.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _MACFWD_H_
+#define _MACFWD_H_
+
+static inline void
+do_macfwd(struct rte_mbuf *pkts_burst[], uint16_t nb_rx,
+	  struct fwd_stream *fs)
+{
+	struct rte_ether_hdr *eth_hdr;
+	uint64_t ol_flags = 0;
+	uint64_t tx_offloads;
+	struct rte_mbuf  *mb;
+	struct rte_port *txp = &ports[fs->tx_port];
+	uint16_t i;
+
+	tx_offloads = txp->dev_conf.txmode.offloads;
+	if (tx_offloads	& RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
+		ol_flags = RTE_MBUF_F_TX_VLAN;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_QINQ;
+	if (tx_offloads & RTE_ETH_TX_OFFLOAD_MACSEC_INSERT)
+		ol_flags |= RTE_MBUF_F_TX_MACSEC;
+	for (i = 0; i < nb_rx; i++) {
+		if (likely(i < nb_rx - 1))
+			rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+						       void *));
+		mb = pkts_burst[i];
+		eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+		rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+				    &eth_hdr->dst_addr);
+		rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+				    &eth_hdr->src_addr);
+		mb->ol_flags &= RTE_MBUF_F_INDIRECT | RTE_MBUF_F_EXTERNAL;
+		mb->ol_flags |= ol_flags;
+		mb->l2_len = sizeof(struct rte_ether_hdr);
+		mb->l3_len = sizeof(struct rte_ipv4_hdr);
+		mb->vlan_tci = txp->tx_vlan_id;
+		mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+	}
+}
+
+#endif /* _MACFWD_H_ */
diff --git a/app/test-pmd/noisy_vnf.c b/app/test-pmd/noisy_vnf.c
index 2bf90a983c..81d1187cfe 100644
--- a/app/test-pmd/noisy_vnf.c
+++ b/app/test-pmd/noisy_vnf.c
@@ -32,6 +32,18 @@
 #include <rte_malloc.h>
 
 #include "testpmd.h"
+#include "5tswap.h"
+#include "macfwd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(__ARM_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
 
 struct noisy_config {
 	struct rte_ring *f;
@@ -80,9 +92,6 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
 {
 	uint16_t i, j;
 
-	if (!ncf->do_sim)
-		return;
-
 	for (i = 0; i < nb_pkts; i++) {
 		for (j = 0; j < noisy_lkup_num_writes; j++)
 			do_write(ncf->vnf_mem);
@@ -110,15 +119,13 @@ sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
  *    out of the FIFO
  * 4. Cases 2 and 3 combined
  */
-static bool
-pkt_burst_noisy_vnf(struct fwd_stream *fs)
+static uint16_t
+noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
 {
 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
 	uint16_t nb_deqd = 0;
-	uint16_t nb_rx = 0;
 	uint16_t nb_tx = 0;
 	uint16_t nb_enqd;
 	unsigned int fifo_free;
@@ -126,12 +133,16 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 	bool needs_flush = false;
 	uint64_t now;
 
-	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
-	if (unlikely(nb_rx == 0))
-		goto flush;
+	if (unlikely(nb_rx == 0)) {
+		if (!ncf->do_buffering)
+			goto end;
+		else
+			goto flush;
+	}
 
 	if (!ncf->do_buffering) {
-		sim_memory_lookups(ncf, nb_rx);
+		if (ncf->do_sim)
+			sim_memory_lookups(ncf, nb_rx);
 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
 		goto end;
 	}
@@ -150,7 +161,8 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
 	}
 
-	sim_memory_lookups(ncf, nb_enqd);
+	if (ncf->do_sim)
+		sim_memory_lookups(ncf, nb_enqd);
 
 flush:
 	if (ncf->do_flush) {
@@ -169,11 +181,66 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)
 		ncf->prev_time = rte_get_timer_cycles();
 	}
 end:
+	return nb_tx;
+}
+
+static bool
+pkt_burst_io(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
 	return nb_rx > 0 || nb_tx > 0;
 }
 
-#define NOISY_STRSIZE 256
-#define NOISY_RING "noisy_ring_%d\n"
+static bool
+pkt_burst_mac(struct fwd_stream *fs)
+{
+	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macfwd(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+
+static bool
+pkt_burst_macswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
+
+static bool
+pkt_burst_5tswap(struct fwd_stream *fs)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	uint16_t nb_rx;
+	uint16_t nb_tx;
+
+	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
+	if (likely(nb_rx != 0))
+		do_5tswap(pkts_burst, nb_rx, fs);
+	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
+
+	return nb_rx > 0 || nb_tx > 0;
+}
 
 static void
 noisy_fwd_end(portid_t pi)
@@ -226,6 +293,20 @@ noisy_fwd_begin(portid_t pi)
 			 "--noisy-lkup-memory-size must be > 0\n");
 	}
 
+	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
+		noisy_vnf_engine.packet_fwd = pkt_burst_io;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
+		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
+	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
+		noisy_vnf_engine.packet_fwd = pkt_burst_5tswap;
+	else
+		rte_exit(EXIT_FAILURE,
+			 " Invalid noisy_fwd_mode specified\n");
+
+	noisy_vnf_engine.status = noisy_fwd_mode_desc[noisy_fwd_mode];
+
 	return 0;
 }
 
@@ -233,6 +314,6 @@ struct fwd_engine noisy_vnf_engine = {
 	.fwd_mode_name  = "noisy",
 	.port_fwd_begin = noisy_fwd_begin,
 	.port_fwd_end   = noisy_fwd_end,
-	.stream_init    = common_fwd_stream_init,
-	.packet_fwd     = pkt_burst_noisy_vnf,
+	.stream_init	= common_fwd_stream_init,
+	.packet_fwd     = pkt_burst_io,
 };
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3b37809baf..b676f2c6ae 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -190,6 +190,7 @@ usage(char* progname)
 	       "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
 	       "    xmem: use anonymous memory to create and populate mempool\n"
 	       "    xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
+	printf("  --noisy-forward-mode=<io|mac|macswap|5tswap>: set the sub-fwd mode, defaults to io\n");
 	printf("  --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
 	printf("  --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
 	printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
@@ -698,6 +699,7 @@ launch_args_parse(int argc, char** argv)
 		{ "mp-alloc",			1, 0, 0 },
 		{ "tx-ip",			1, 0, 0 },
 		{ "tx-udp",			1, 0, 0 },
+		{ "noisy-forward-mode",		1, 0, 0 },
 		{ "noisy-tx-sw-buffer-size",	1, 0, 0 },
 		{ "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
 		{ "noisy-lkup-memory",		1, 0, 0 },
@@ -1444,6 +1446,19 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE,
 						 "noisy-lkup-num-reads-writes must be >= 0\n");
 			}
+			if (!strcmp(lgopts[opt_idx].name,
+				    "noisy-forward-mode")) {
+				int i;
+				for (i = 0; i < NOISY_FWD_MODE_MAX; i++)
+					if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
+						noisy_fwd_mode = i;
+						break;
+					}
+				if (i == NOISY_FWD_MODE_MAX)
+					rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
+						 " must be a valid noisy-forward-mode value\n",
+						 optarg);
+			}
 			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
 				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
 
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 5cb6f92523..c6ad9b18bf 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -330,6 +330,20 @@ int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
  */
 int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
 
+/*
+ * Configurable sub-forwarding mode for the noisy_vnf forwarding mode.
+ */
+enum noisy_fwd_mode noisy_fwd_mode;
+
+/* String version of enum noisy_fwd_mode */
+const char * const noisy_fwd_mode_desc[] = {
+	[NOISY_FWD_MODE_IO] = "io",
+	[NOISY_FWD_MODE_MAC] = "mac",
+	[NOISY_FWD_MODE_MACSWAP] = "macswap",
+	[NOISY_FWD_MODE_5TSWAP] = "5tswap",
+	[NOISY_FWD_MODE_MAX] = NULL,
+};
+
 /*
  * Configurable value of buffered packets before sending.
  */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..2f18cf20a2 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -116,6 +116,14 @@ enum {
 	QUEUE_JOB_TYPE_ACTION_QUERY,
 };
 
+enum noisy_fwd_mode {
+	NOISY_FWD_MODE_IO,
+	NOISY_FWD_MODE_MAC,
+	NOISY_FWD_MODE_MACSWAP,
+	NOISY_FWD_MODE_5TSWAP,
+	NOISY_FWD_MODE_MAX,
+};
+
 /**
  * The data structure associated with RX and TX packet burst statistics
  * that are recorded for each forwarding stream.
@@ -391,6 +399,7 @@ struct fwd_engine {
 	port_fwd_end_t   port_fwd_end;   /**< NULL if nothing special to do. */
 	stream_init_t    stream_init;    /**< NULL if nothing special to do. */
 	packet_fwd_t     packet_fwd;     /**< Mandatory. */
+	const char       *status;        /**< NULL if nothing to display. */
 };
 
 void common_fwd_stream_init(struct fwd_stream *fs);
@@ -555,6 +564,8 @@ extern int8_t rx_drop_en;
 extern int16_t tx_free_thresh;
 extern int16_t tx_rs_thresh;
 
+extern enum noisy_fwd_mode noisy_fwd_mode;
+extern const char * const noisy_fwd_mode_desc[];
 extern uint16_t noisy_tx_sw_bufsz;
 extern uint16_t noisy_tx_sw_buf_flush_time;
 extern uint64_t noisy_lkup_mem_sz;
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index 57b23241cf..8319a30968 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -487,6 +487,15 @@ The command line options are:
     * xmemhuge: create and populate mempool using externally and anonymously
       allocated hugepage area
 
+*   ``--noisy-forward-mode=mode``
+
+    Set the noisy vnf forwarding mode where ``mode`` is one of the following::
+
+       io (the default)
+       mac
+       macswap
+       5tswap
+
 *   ``--noisy-tx-sw-buffer-size``
 
     Set the number of maximum elements  of the FIFO queue to be created
-- 
2.31.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v7] app/testpmd: expand noisy neighbour forward mode support
  2023-06-08 13:31       ` [PATCH v7] " Mike Pattrick
@ 2023-06-08 14:32         ` Ferruh Yigit
  0 siblings, 0 replies; 18+ messages in thread
From: Ferruh Yigit @ 2023-06-08 14:32 UTC (permalink / raw)
  To: Mike Pattrick, Aman Singh, Yuying Zhang; +Cc: ktraynor, dev

On 6/8/2023 2:31 PM, Mike Pattrick wrote:
> Previously the noisy neighbour vnf simulation would only operate in io
> mode, forwarding packets as is. However, this limited the usefulness of
> noisy neighbour simulation.
> 
> This feature has now been expanded to supporting mac, macswap, and
> 5tswap modes. To facilitate adding this support, some new header files
> were added.
> 
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>

Reviewed-by: Ferruh Yigit <ferruh.yigit@amd.com>

Applied to dpdk-next-net/main, thanks.



> @@ -4052,9 +4052,16 @@ rxtx_config_display(void)
>  {
>  	portid_t pid;
>  	queueid_t qid;
> +	char buf[32];
> +
> +	if (cur_fwd_eng->status)
> +		snprintf(buf, sizeof(buf), " (%s)", cur_fwd_eng->status);
> +	else
> +		buf[0] = '\0';
>  
> -	printf("  %s packet forwarding%s packets/burst=%d\n",
> +	printf("  %s%s packet forwarding%s packets/burst=%d\n",
>  	       cur_fwd_eng->fwd_mode_name,
> +	       buf,
>  	       retry_enabled == 0 ? "" : " with retry",
>  	       nb_pkt_per_burst);
>  
> @@ -4816,10 +4823,17 @@ pkt_fwd_config_display(struct fwd_config *cfg)
>  	struct fwd_stream *fs;
>  	lcoreid_t  lc_id;
>  	streamid_t sm_id;
> +	char buf[32];
> +
> +	if (cfg->fwd_eng->status)
> +		snprintf(buf, sizeof(buf), " (%s)", cfg->fwd_eng->status);
> +	else
> +		buf[0] = '\0';
>  
> -	printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
> +	printf("%s%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
>  		"NUMA support %s, MP allocation mode: %s\n",
>  		cfg->fwd_eng->fwd_mode_name,
> +		buf,
>  		retry_enabled == 0 ? "" : " with retry",
>  		cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
>  		numa_support == 1 ? "enabled" : "disabled",


Removed interim 'buf' variable (and 'cfg->fwd_eng->status' specific
check), and updated as following while merging:

```
 -       printf("  %s packet forwarding%s packets/burst=%d\n",
 +       printf("  %s%s%s packet forwarding%s packets/burst=%d\n",
                cur_fwd_eng->fwd_mode_name,
 +              cur_fwd_eng->status ? "-" : "",
 +              cur_fwd_eng->status ? cur_fwd_eng->status : "",
```


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2023-06-08 14:32 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-17 18:55 [PATCH v3] app/testpmd: expand noisy neighbour forward mode support Mike Pattrick
2023-05-26 15:34 ` Kevin Traynor
2023-05-26 17:32   ` Mike Pattrick
2023-06-01 16:23     ` Kevin Traynor
2023-06-06 14:17       ` Ferruh Yigit
2023-06-02 18:29 ` [PATCH v4] " Mike Pattrick
2023-06-06 14:27   ` Ferruh Yigit
2023-06-06 21:12   ` [PATCH v5] " Mike Pattrick
2023-06-06 21:37     ` Ferruh Yigit
2023-06-06 21:42       ` Ferruh Yigit
2023-06-06 22:23     ` Ferruh Yigit
2023-06-07 15:42       ` Mike Pattrick
2023-06-08  9:59     ` [PATCH v6] " Mike Pattrick
2023-06-08 10:25       ` Ferruh Yigit
2023-06-08 10:43         ` Mike Pattrick
2023-06-08 11:42           ` Ferruh Yigit
2023-06-08 13:31       ` [PATCH v7] " Mike Pattrick
2023-06-08 14:32         ` Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).