xref: /dpdk/app/test-pmd/noisy_vnf.c (revision 1d343c19330a11f05e3ea369ae5780d38772358e)
13c156061SJens Freimann /* SPDX-License-Identifier: BSD-3-Clause
23c156061SJens Freimann  * Copyright(c) 2018 Red Hat Corp.
33c156061SJens Freimann  */
43c156061SJens Freimann 
53c156061SJens Freimann #include <stdarg.h>
63c156061SJens Freimann #include <stdio.h>
71bcb7ba9SDavid Marchand #include <stdlib.h>
83c156061SJens Freimann #include <stdbool.h>
93c156061SJens Freimann #include <string.h>
103c156061SJens Freimann #include <errno.h>
113c156061SJens Freimann #include <stdint.h>
123c156061SJens Freimann #include <unistd.h>
133c156061SJens Freimann #include <inttypes.h>
143c156061SJens Freimann 
153c156061SJens Freimann #include <sys/queue.h>
163c156061SJens Freimann #include <sys/stat.h>
173c156061SJens Freimann 
183c156061SJens Freimann #include <rte_common.h>
193c156061SJens Freimann #include <rte_log.h>
203c156061SJens Freimann #include <rte_debug.h>
213c156061SJens Freimann #include <rte_cycles.h>
223c156061SJens Freimann #include <rte_memory.h>
233c156061SJens Freimann #include <rte_launch.h>
243c156061SJens Freimann #include <rte_eal.h>
253c156061SJens Freimann #include <rte_per_lcore.h>
263c156061SJens Freimann #include <rte_lcore.h>
273c156061SJens Freimann #include <rte_memcpy.h>
283c156061SJens Freimann #include <rte_mempool.h>
293c156061SJens Freimann #include <rte_mbuf.h>
303c156061SJens Freimann #include <rte_ethdev.h>
313c156061SJens Freimann #include <rte_flow.h>
323c156061SJens Freimann #include <rte_malloc.h>
333c156061SJens Freimann 
343c156061SJens Freimann #include "testpmd.h"
35*1d343c19SMike Pattrick #include "5tswap.h"
36*1d343c19SMike Pattrick #include "macfwd.h"
37*1d343c19SMike Pattrick #if defined(RTE_ARCH_X86)
38*1d343c19SMike Pattrick #include "macswap_sse.h"
39*1d343c19SMike Pattrick #elif defined(__ARM_NEON)
40*1d343c19SMike Pattrick #include "macswap_neon.h"
41*1d343c19SMike Pattrick #else
42*1d343c19SMike Pattrick #include "macswap.h"
43*1d343c19SMike Pattrick #endif
44*1d343c19SMike Pattrick 
45*1d343c19SMike Pattrick #define NOISY_STRSIZE 256
46*1d343c19SMike Pattrick #define NOISY_RING "noisy_ring_%d\n"
473c156061SJens Freimann 
483c156061SJens Freimann struct noisy_config {
493c156061SJens Freimann 	struct rte_ring *f;
503c156061SJens Freimann 	uint64_t prev_time;
513c156061SJens Freimann 	char *vnf_mem;
523c156061SJens Freimann 	bool do_buffering;
533c156061SJens Freimann 	bool do_flush;
543c156061SJens Freimann 	bool do_sim;
553c156061SJens Freimann };
563c156061SJens Freimann 
573c156061SJens Freimann struct noisy_config *noisy_cfg[RTE_MAX_ETHPORTS];
583c156061SJens Freimann 
593c156061SJens Freimann static inline void
do_write(char * vnf_mem)603c156061SJens Freimann do_write(char *vnf_mem)
613c156061SJens Freimann {
623c156061SJens Freimann 	uint64_t i = rte_rand();
633c156061SJens Freimann 	uint64_t w = rte_rand();
643c156061SJens Freimann 
653c156061SJens Freimann 	vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
663c156061SJens Freimann 			RTE_CACHE_LINE_SIZE)] = w;
673c156061SJens Freimann }
683c156061SJens Freimann 
693c156061SJens Freimann static inline void
do_read(char * vnf_mem)703c156061SJens Freimann do_read(char *vnf_mem)
713c156061SJens Freimann {
72ff3cc865SDavid Marchand 	uint64_t r __rte_unused;
733c156061SJens Freimann 	uint64_t i = rte_rand();
743c156061SJens Freimann 
753c156061SJens Freimann 	r = vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
763c156061SJens Freimann 			RTE_CACHE_LINE_SIZE)];
773c156061SJens Freimann 	r++;
783c156061SJens Freimann }
793c156061SJens Freimann 
803c156061SJens Freimann static inline void
do_readwrite(char * vnf_mem)813c156061SJens Freimann do_readwrite(char *vnf_mem)
823c156061SJens Freimann {
833c156061SJens Freimann 	do_read(vnf_mem);
843c156061SJens Freimann 	do_write(vnf_mem);
853c156061SJens Freimann }
863c156061SJens Freimann 
873c156061SJens Freimann /*
883c156061SJens Freimann  * Simulate route lookups as defined by commandline parameters
893c156061SJens Freimann  */
903c156061SJens Freimann static void
sim_memory_lookups(struct noisy_config * ncf,uint16_t nb_pkts)913c156061SJens Freimann sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
923c156061SJens Freimann {
933c156061SJens Freimann 	uint16_t i, j;
943c156061SJens Freimann 
953c156061SJens Freimann 	for (i = 0; i < nb_pkts; i++) {
963c156061SJens Freimann 		for (j = 0; j < noisy_lkup_num_writes; j++)
973c156061SJens Freimann 			do_write(ncf->vnf_mem);
983c156061SJens Freimann 		for (j = 0; j < noisy_lkup_num_reads; j++)
993c156061SJens Freimann 			do_read(ncf->vnf_mem);
1003c156061SJens Freimann 		for (j = 0; j < noisy_lkup_num_reads_writes; j++)
1013c156061SJens Freimann 			do_readwrite(ncf->vnf_mem);
1023c156061SJens Freimann 	}
1033c156061SJens Freimann }
1043c156061SJens Freimann 
1053c156061SJens Freimann /*
1063c156061SJens Freimann  * Forwarding of packets in noisy VNF mode.  Forward packets but perform
1073c156061SJens Freimann  * memory operations first as specified on cmdline.
1083c156061SJens Freimann  *
1093c156061SJens Freimann  * Depending on which commandline parameters are specified we have
1103c156061SJens Freimann  * different cases to handle:
1113c156061SJens Freimann  *
1123c156061SJens Freimann  * 1. No FIFO size was given, so we don't do buffering of incoming
1133c156061SJens Freimann  *    packets.  This case is pretty much what iofwd does but in this case
1143c156061SJens Freimann  *    we also do simulation of memory accesses (depending on which
1153c156061SJens Freimann  *    parameters were specified for it).
1163c156061SJens Freimann  * 2. User wants do buffer packets in a FIFO and sent out overflowing
1173c156061SJens Freimann  *    packets.
1183c156061SJens Freimann  * 3. User wants a FIFO and specifies a time in ms to flush all packets
1193c156061SJens Freimann  *    out of the FIFO
1203c156061SJens Freimann  * 4. Cases 2 and 3 combined
1213c156061SJens Freimann  */
122*1d343c19SMike Pattrick static uint16_t
noisy_eth_tx_burst(struct fwd_stream * fs,uint16_t nb_rx,struct rte_mbuf ** pkts_burst)123*1d343c19SMike Pattrick noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
1243c156061SJens Freimann {
1253c156061SJens Freimann 	const uint64_t freq_khz = rte_get_timer_hz() / 1000;
1263c156061SJens Freimann 	struct noisy_config *ncf = noisy_cfg[fs->rx_port];
1273c156061SJens Freimann 	struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
1283c156061SJens Freimann 	uint16_t nb_deqd = 0;
1293c156061SJens Freimann 	uint16_t nb_tx = 0;
1303c156061SJens Freimann 	uint16_t nb_enqd;
1313c156061SJens Freimann 	unsigned int fifo_free;
1323c156061SJens Freimann 	uint64_t delta_ms;
1333c156061SJens Freimann 	bool needs_flush = false;
1343c156061SJens Freimann 	uint64_t now;
1353c156061SJens Freimann 
136*1d343c19SMike Pattrick 	if (unlikely(nb_rx == 0)) {
137*1d343c19SMike Pattrick 		if (!ncf->do_buffering)
138*1d343c19SMike Pattrick 			goto end;
139*1d343c19SMike Pattrick 		else
1403c156061SJens Freimann 			goto flush;
141*1d343c19SMike Pattrick 	}
1423c156061SJens Freimann 
1433c156061SJens Freimann 	if (!ncf->do_buffering) {
144*1d343c19SMike Pattrick 		if (ncf->do_sim)
1453c156061SJens Freimann 			sim_memory_lookups(ncf, nb_rx);
146655131ccSDavid Marchand 		nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
14799a4974aSRobin Jarry 		goto end;
1483c156061SJens Freimann 	}
1493c156061SJens Freimann 
1503c156061SJens Freimann 	fifo_free = rte_ring_free_count(ncf->f);
1513c156061SJens Freimann 	if (fifo_free >= nb_rx) {
152655131ccSDavid Marchand 		nb_enqd = rte_ring_enqueue_burst(ncf->f, (void **) pkts_burst, nb_rx, NULL);
153655131ccSDavid Marchand 		if (nb_enqd < nb_rx) {
154655131ccSDavid Marchand 			fs->fwd_dropped += nb_rx - nb_enqd;
155655131ccSDavid Marchand 			rte_pktmbuf_free_bulk(&pkts_burst[nb_enqd], nb_rx - nb_enqd);
1563c156061SJens Freimann 		}
157655131ccSDavid Marchand 	} else {
158655131ccSDavid Marchand 		nb_deqd = rte_ring_dequeue_burst(ncf->f, (void **) tmp_pkts, nb_rx, NULL);
159655131ccSDavid Marchand 		nb_enqd = rte_ring_enqueue_burst(ncf->f, (void **) pkts_burst, nb_deqd, NULL);
160655131ccSDavid Marchand 		if (nb_deqd > 0)
161655131ccSDavid Marchand 			nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
1623c156061SJens Freimann 	}
1633c156061SJens Freimann 
164*1d343c19SMike Pattrick 	if (ncf->do_sim)
1653c156061SJens Freimann 		sim_memory_lookups(ncf, nb_enqd);
1663c156061SJens Freimann 
1673c156061SJens Freimann flush:
1683c156061SJens Freimann 	if (ncf->do_flush) {
1693c156061SJens Freimann 		if (!ncf->prev_time)
1703c156061SJens Freimann 			now = ncf->prev_time = rte_get_timer_cycles();
1713c156061SJens Freimann 		else
1723c156061SJens Freimann 			now = rte_get_timer_cycles();
1733c156061SJens Freimann 		delta_ms = (now - ncf->prev_time) / freq_khz;
1743c156061SJens Freimann 		needs_flush = delta_ms >= noisy_tx_sw_buf_flush_time &&
1753c156061SJens Freimann 				noisy_tx_sw_buf_flush_time > 0 && !nb_tx;
1763c156061SJens Freimann 	}
1773c156061SJens Freimann 	while (needs_flush && !rte_ring_empty(ncf->f)) {
1783c156061SJens Freimann 		nb_deqd = rte_ring_dequeue_burst(ncf->f, (void **)tmp_pkts,
1793c156061SJens Freimann 				MAX_PKT_BURST, NULL);
180655131ccSDavid Marchand 		nb_tx += common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
1813c156061SJens Freimann 		ncf->prev_time = rte_get_timer_cycles();
1823c156061SJens Freimann 	}
18399a4974aSRobin Jarry end:
184*1d343c19SMike Pattrick 	return nb_tx;
185*1d343c19SMike Pattrick }
186*1d343c19SMike Pattrick 
187*1d343c19SMike Pattrick static bool
pkt_burst_io(struct fwd_stream * fs)188*1d343c19SMike Pattrick pkt_burst_io(struct fwd_stream *fs)
189*1d343c19SMike Pattrick {
190*1d343c19SMike Pattrick 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
191*1d343c19SMike Pattrick 	uint16_t nb_rx;
192*1d343c19SMike Pattrick 	uint16_t nb_tx;
193*1d343c19SMike Pattrick 
194*1d343c19SMike Pattrick 	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
195*1d343c19SMike Pattrick 	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
196*1d343c19SMike Pattrick 
19706c20561SDavid Marchand 	return nb_rx > 0 || nb_tx > 0;
1983c156061SJens Freimann }
1993c156061SJens Freimann 
200*1d343c19SMike Pattrick static bool
pkt_burst_mac(struct fwd_stream * fs)201*1d343c19SMike Pattrick pkt_burst_mac(struct fwd_stream *fs)
202*1d343c19SMike Pattrick {
203*1d343c19SMike Pattrick 	struct rte_mbuf  *pkts_burst[MAX_PKT_BURST];
204*1d343c19SMike Pattrick 	uint16_t nb_rx;
205*1d343c19SMike Pattrick 	uint16_t nb_tx;
206*1d343c19SMike Pattrick 
207*1d343c19SMike Pattrick 	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
208*1d343c19SMike Pattrick 	if (likely(nb_rx != 0))
209*1d343c19SMike Pattrick 		do_macfwd(pkts_burst, nb_rx, fs);
210*1d343c19SMike Pattrick 	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
211*1d343c19SMike Pattrick 
212*1d343c19SMike Pattrick 	return nb_rx > 0 || nb_tx > 0;
213*1d343c19SMike Pattrick }
214*1d343c19SMike Pattrick 
215*1d343c19SMike Pattrick static bool
pkt_burst_macswap(struct fwd_stream * fs)216*1d343c19SMike Pattrick pkt_burst_macswap(struct fwd_stream *fs)
217*1d343c19SMike Pattrick {
218*1d343c19SMike Pattrick 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
219*1d343c19SMike Pattrick 	uint16_t nb_rx;
220*1d343c19SMike Pattrick 	uint16_t nb_tx;
221*1d343c19SMike Pattrick 
222*1d343c19SMike Pattrick 	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
223*1d343c19SMike Pattrick 	if (likely(nb_rx != 0))
224*1d343c19SMike Pattrick 		do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
225*1d343c19SMike Pattrick 	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
226*1d343c19SMike Pattrick 
227*1d343c19SMike Pattrick 	return nb_rx > 0 || nb_tx > 0;
228*1d343c19SMike Pattrick }
229*1d343c19SMike Pattrick 
230*1d343c19SMike Pattrick static bool
pkt_burst_5tswap(struct fwd_stream * fs)231*1d343c19SMike Pattrick pkt_burst_5tswap(struct fwd_stream *fs)
232*1d343c19SMike Pattrick {
233*1d343c19SMike Pattrick 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
234*1d343c19SMike Pattrick 	uint16_t nb_rx;
235*1d343c19SMike Pattrick 	uint16_t nb_tx;
236*1d343c19SMike Pattrick 
237*1d343c19SMike Pattrick 	nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
238*1d343c19SMike Pattrick 	if (likely(nb_rx != 0))
239*1d343c19SMike Pattrick 		do_5tswap(pkts_burst, nb_rx, fs);
240*1d343c19SMike Pattrick 	nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
241*1d343c19SMike Pattrick 
242*1d343c19SMike Pattrick 	return nb_rx > 0 || nb_tx > 0;
243*1d343c19SMike Pattrick }
2443c156061SJens Freimann 
2453c156061SJens Freimann static void
noisy_fwd_end(portid_t pi)2463c156061SJens Freimann noisy_fwd_end(portid_t pi)
2473c156061SJens Freimann {
2483c156061SJens Freimann 	rte_ring_free(noisy_cfg[pi]->f);
2493c156061SJens Freimann 	rte_free(noisy_cfg[pi]->vnf_mem);
2503c156061SJens Freimann 	rte_free(noisy_cfg[pi]);
2513c156061SJens Freimann }
2523c156061SJens Freimann 
253a78040c9SAlvin Zhang static int
noisy_fwd_begin(portid_t pi)2543c156061SJens Freimann noisy_fwd_begin(portid_t pi)
2553c156061SJens Freimann {
2563c156061SJens Freimann 	struct noisy_config *n;
2573c156061SJens Freimann 	char name[NOISY_STRSIZE];
2583c156061SJens Freimann 
2593c156061SJens Freimann 	noisy_cfg[pi] = rte_zmalloc("testpmd noisy fifo and timers",
2603c156061SJens Freimann 				sizeof(struct noisy_config),
2613c156061SJens Freimann 				RTE_CACHE_LINE_SIZE);
2623c156061SJens Freimann 	if (noisy_cfg[pi] == NULL) {
2633c156061SJens Freimann 		rte_exit(EXIT_FAILURE,
2643c156061SJens Freimann 			 "rte_zmalloc(%d) struct noisy_config) failed\n",
2653c156061SJens Freimann 			 (int) pi);
2663c156061SJens Freimann 	}
2673c156061SJens Freimann 	n = noisy_cfg[pi];
2683c156061SJens Freimann 	n->do_buffering = noisy_tx_sw_bufsz > 0;
2693c156061SJens Freimann 	n->do_sim = noisy_lkup_num_writes + noisy_lkup_num_reads +
2703c156061SJens Freimann 		    noisy_lkup_num_reads_writes;
2713c156061SJens Freimann 	n->do_flush = noisy_tx_sw_buf_flush_time > 0;
2723c156061SJens Freimann 
2733c156061SJens Freimann 	if (n->do_buffering) {
2743c156061SJens Freimann 		snprintf(name, NOISY_STRSIZE, NOISY_RING, pi);
2753c156061SJens Freimann 		n->f = rte_ring_create(name, noisy_tx_sw_bufsz,
2763c156061SJens Freimann 				rte_socket_id(), 0);
2773c156061SJens Freimann 		if (!n->f)
2783c156061SJens Freimann 			rte_exit(EXIT_FAILURE,
2793c156061SJens Freimann 				 "rte_ring_create(%d), size %d) failed\n",
2803c156061SJens Freimann 				 (int) pi,
2813c156061SJens Freimann 				 noisy_tx_sw_bufsz);
2823c156061SJens Freimann 	}
2833c156061SJens Freimann 	if (noisy_lkup_mem_sz > 0) {
2843c156061SJens Freimann 		n->vnf_mem = (char *) rte_zmalloc("vnf sim memory",
2853c156061SJens Freimann 				 noisy_lkup_mem_sz * 1024 * 1024,
2863c156061SJens Freimann 				 RTE_CACHE_LINE_SIZE);
2873c156061SJens Freimann 		if (!n->vnf_mem)
2883c156061SJens Freimann 			rte_exit(EXIT_FAILURE,
2893c156061SJens Freimann 			   "rte_zmalloc(%" PRIu64 ") for vnf memory) failed\n",
2903c156061SJens Freimann 			   noisy_lkup_mem_sz);
2913c156061SJens Freimann 	} else if (n->do_sim) {
2923c156061SJens Freimann 		rte_exit(EXIT_FAILURE,
2933c156061SJens Freimann 			 "--noisy-lkup-memory-size must be > 0\n");
2943c156061SJens Freimann 	}
295a78040c9SAlvin Zhang 
296*1d343c19SMike Pattrick 	if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
297*1d343c19SMike Pattrick 		noisy_vnf_engine.packet_fwd = pkt_burst_io;
298*1d343c19SMike Pattrick 	else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
299*1d343c19SMike Pattrick 		noisy_vnf_engine.packet_fwd = pkt_burst_mac;
300*1d343c19SMike Pattrick 	else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
301*1d343c19SMike Pattrick 		noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
302*1d343c19SMike Pattrick 	else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
303*1d343c19SMike Pattrick 		noisy_vnf_engine.packet_fwd = pkt_burst_5tswap;
304*1d343c19SMike Pattrick 	else
305*1d343c19SMike Pattrick 		rte_exit(EXIT_FAILURE,
306*1d343c19SMike Pattrick 			 " Invalid noisy_fwd_mode specified\n");
307*1d343c19SMike Pattrick 
308*1d343c19SMike Pattrick 	noisy_vnf_engine.status = noisy_fwd_mode_desc[noisy_fwd_mode];
309*1d343c19SMike Pattrick 
310a78040c9SAlvin Zhang 	return 0;
3113c156061SJens Freimann }
3123c156061SJens Freimann 
3133c156061SJens Freimann struct fwd_engine noisy_vnf_engine = {
3143c156061SJens Freimann 	.fwd_mode_name  = "noisy",
3153c156061SJens Freimann 	.port_fwd_begin = noisy_fwd_begin,
3163c156061SJens Freimann 	.port_fwd_end   = noisy_fwd_end,
317180ba023SDavid Marchand 	.stream_init	= common_fwd_stream_init,
318*1d343c19SMike Pattrick 	.packet_fwd     = pkt_burst_io,
3193c156061SJens Freimann };
320