xref: /f-stack/dpdk/app/test/test_pmd_perf.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang 
64418919fSjohnjiang #include <stdio.h>
74418919fSjohnjiang #include <inttypes.h>
84418919fSjohnjiang #include <signal.h>
94418919fSjohnjiang #include <unistd.h>
104418919fSjohnjiang #include <rte_cycles.h>
114418919fSjohnjiang #include <rte_ethdev.h>
124418919fSjohnjiang #include <rte_byteorder.h>
134418919fSjohnjiang #include <rte_atomic.h>
144418919fSjohnjiang #include <rte_malloc.h>
154418919fSjohnjiang #include "packet_burst_generator.h"
164418919fSjohnjiang #include "test.h"
174418919fSjohnjiang 
184418919fSjohnjiang #define NB_ETHPORTS_USED                (1)
194418919fSjohnjiang #define NB_SOCKETS                      (2)
204418919fSjohnjiang #define MEMPOOL_CACHE_SIZE 250
214418919fSjohnjiang #define MAX_PKT_BURST                   (32)
224418919fSjohnjiang #define RTE_TEST_RX_DESC_DEFAULT        (1024)
234418919fSjohnjiang #define RTE_TEST_TX_DESC_DEFAULT        (1024)
244418919fSjohnjiang #define RTE_PORT_ALL            (~(uint16_t)0x0)
254418919fSjohnjiang 
264418919fSjohnjiang /* how long test would take at full line rate */
274418919fSjohnjiang #define RTE_TEST_DURATION                (2)
284418919fSjohnjiang 
294418919fSjohnjiang /*
304418919fSjohnjiang  * RX and TX Prefetch, Host, and Write-back threshold values should be
314418919fSjohnjiang  * carefully set for optimal performance. Consult the network
324418919fSjohnjiang  * controller's datasheet and supporting DPDK documentation for guidance
334418919fSjohnjiang  * on how these parameters should be set.
344418919fSjohnjiang  */
354418919fSjohnjiang #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
364418919fSjohnjiang #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
374418919fSjohnjiang #define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */
384418919fSjohnjiang 
394418919fSjohnjiang /*
404418919fSjohnjiang  * These default values are optimized for use with the Intel(R) 82599 10 GbE
414418919fSjohnjiang  * Controller and the DPDK ixgbe PMD. Consider using other values for other
424418919fSjohnjiang  * network controllers and/or network drivers.
434418919fSjohnjiang  */
444418919fSjohnjiang #define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */
454418919fSjohnjiang #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
464418919fSjohnjiang #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
474418919fSjohnjiang 
484418919fSjohnjiang #define MAX_TRAFFIC_BURST              2048
494418919fSjohnjiang 
504418919fSjohnjiang #define NB_MBUF RTE_MAX(						\
514418919fSjohnjiang 		(unsigned)(nb_ports*nb_rx_queue*nb_rxd +		\
524418919fSjohnjiang 			   nb_ports*nb_lcores*MAX_PKT_BURST +		\
534418919fSjohnjiang 			   nb_ports*nb_tx_queue*nb_txd +		\
544418919fSjohnjiang 			   nb_lcores*MEMPOOL_CACHE_SIZE +		\
554418919fSjohnjiang 			   nb_ports*MAX_TRAFFIC_BURST),			\
564418919fSjohnjiang 			(unsigned)8192)
574418919fSjohnjiang 
584418919fSjohnjiang 
594418919fSjohnjiang static struct rte_mempool *mbufpool[NB_SOCKETS];
604418919fSjohnjiang /* ethernet addresses of ports */
614418919fSjohnjiang static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
624418919fSjohnjiang 
634418919fSjohnjiang static struct rte_eth_conf port_conf = {
644418919fSjohnjiang 	.rxmode = {
654418919fSjohnjiang 		.mq_mode = ETH_MQ_RX_NONE,
664418919fSjohnjiang 		.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
674418919fSjohnjiang 		.split_hdr_size = 0,
684418919fSjohnjiang 	},
694418919fSjohnjiang 	.txmode = {
704418919fSjohnjiang 		.mq_mode = ETH_MQ_TX_NONE,
714418919fSjohnjiang 	},
724418919fSjohnjiang 	.lpbk_mode = 1,  /* enable loopback */
734418919fSjohnjiang };
744418919fSjohnjiang 
754418919fSjohnjiang static struct rte_eth_rxconf rx_conf = {
764418919fSjohnjiang 	.rx_thresh = {
774418919fSjohnjiang 		.pthresh = RX_PTHRESH,
784418919fSjohnjiang 		.hthresh = RX_HTHRESH,
794418919fSjohnjiang 		.wthresh = RX_WTHRESH,
804418919fSjohnjiang 	},
814418919fSjohnjiang 	.rx_free_thresh = 32,
824418919fSjohnjiang };
834418919fSjohnjiang 
844418919fSjohnjiang static struct rte_eth_txconf tx_conf = {
854418919fSjohnjiang 	.tx_thresh = {
864418919fSjohnjiang 		.pthresh = TX_PTHRESH,
874418919fSjohnjiang 		.hthresh = TX_HTHRESH,
884418919fSjohnjiang 		.wthresh = TX_WTHRESH,
894418919fSjohnjiang 	},
904418919fSjohnjiang 	.tx_free_thresh = 32, /* Use PMD default values */
914418919fSjohnjiang 	.tx_rs_thresh = 32, /* Use PMD default values */
924418919fSjohnjiang };
934418919fSjohnjiang 
944418919fSjohnjiang enum {
954418919fSjohnjiang 	LCORE_INVALID = 0,
964418919fSjohnjiang 	LCORE_AVAIL,
974418919fSjohnjiang 	LCORE_USED,
984418919fSjohnjiang };
994418919fSjohnjiang 
1004418919fSjohnjiang struct lcore_conf {
1014418919fSjohnjiang 	uint8_t status;
1024418919fSjohnjiang 	uint8_t socketid;
1034418919fSjohnjiang 	uint16_t nb_ports;
1044418919fSjohnjiang 	uint16_t portlist[RTE_MAX_ETHPORTS];
1054418919fSjohnjiang } __rte_cache_aligned;
1064418919fSjohnjiang 
1074418919fSjohnjiang struct lcore_conf lcore_conf[RTE_MAX_LCORE];
1084418919fSjohnjiang 
1094418919fSjohnjiang static uint64_t link_mbps;
1104418919fSjohnjiang 
1114418919fSjohnjiang enum {
1124418919fSjohnjiang 	SC_CONTINUOUS = 0,
1134418919fSjohnjiang 	SC_BURST_POLL_FIRST,
1144418919fSjohnjiang 	SC_BURST_XMIT_FIRST,
1154418919fSjohnjiang };
1164418919fSjohnjiang 
1174418919fSjohnjiang static uint32_t sc_flag;
1184418919fSjohnjiang 
1194418919fSjohnjiang /* Check the link status of all ports in up to 3s, and print them finally */
1204418919fSjohnjiang static void
check_all_ports_link_status(uint16_t port_num,uint32_t port_mask)1214418919fSjohnjiang check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
1224418919fSjohnjiang {
1234418919fSjohnjiang #define CHECK_INTERVAL 100 /* 100ms */
1244418919fSjohnjiang #define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */
1254418919fSjohnjiang 	uint16_t portid;
1264418919fSjohnjiang 	uint8_t count, all_ports_up, print_flag = 0;
1274418919fSjohnjiang 	struct rte_eth_link link;
1284418919fSjohnjiang 	int ret;
129*2d9fd380Sjfb8856606 	char link_status[RTE_ETH_LINK_MAX_STR_LEN];
1304418919fSjohnjiang 
1314418919fSjohnjiang 	printf("Checking link statuses...\n");
1324418919fSjohnjiang 	fflush(stdout);
1334418919fSjohnjiang 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
1344418919fSjohnjiang 		all_ports_up = 1;
1354418919fSjohnjiang 		for (portid = 0; portid < port_num; portid++) {
1364418919fSjohnjiang 			if ((port_mask & (1 << portid)) == 0)
1374418919fSjohnjiang 				continue;
1384418919fSjohnjiang 			memset(&link, 0, sizeof(link));
1394418919fSjohnjiang 			ret = rte_eth_link_get_nowait(portid, &link);
1404418919fSjohnjiang 			if (ret < 0) {
1414418919fSjohnjiang 				all_ports_up = 0;
1424418919fSjohnjiang 				if (print_flag == 1)
1434418919fSjohnjiang 					printf("Port %u link get failed: %s\n",
1444418919fSjohnjiang 						portid, rte_strerror(-ret));
1454418919fSjohnjiang 				continue;
1464418919fSjohnjiang 			}
1474418919fSjohnjiang 
1484418919fSjohnjiang 			/* print link status if flag set */
1494418919fSjohnjiang 			if (print_flag == 1) {
150*2d9fd380Sjfb8856606 				if (link.link_status && link_mbps == 0)
1514418919fSjohnjiang 					link_mbps = link.link_speed;
152*2d9fd380Sjfb8856606 
153*2d9fd380Sjfb8856606 				rte_eth_link_to_str(link_status,
154*2d9fd380Sjfb8856606 					sizeof(link_status), &link);
155*2d9fd380Sjfb8856606 				printf("Port %d %s\n", portid, link_status);
1564418919fSjohnjiang 				continue;
1574418919fSjohnjiang 			}
1584418919fSjohnjiang 			/* clear all_ports_up flag if any link down */
1594418919fSjohnjiang 			if (link.link_status == ETH_LINK_DOWN) {
1604418919fSjohnjiang 				all_ports_up = 0;
1614418919fSjohnjiang 				break;
1624418919fSjohnjiang 			}
1634418919fSjohnjiang 		}
1644418919fSjohnjiang 		/* after finally printing all link status, get out */
1654418919fSjohnjiang 		if (print_flag == 1)
1664418919fSjohnjiang 			break;
1674418919fSjohnjiang 
1684418919fSjohnjiang 		if (all_ports_up == 0) {
1694418919fSjohnjiang 			fflush(stdout);
1704418919fSjohnjiang 			rte_delay_ms(CHECK_INTERVAL);
1714418919fSjohnjiang 		}
1724418919fSjohnjiang 
1734418919fSjohnjiang 		/* set the print_flag if all ports up or timeout */
1744418919fSjohnjiang 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1))
1754418919fSjohnjiang 			print_flag = 1;
1764418919fSjohnjiang 	}
1774418919fSjohnjiang }
1784418919fSjohnjiang 
1794418919fSjohnjiang static void
print_ethaddr(const char * name,const struct rte_ether_addr * eth_addr)1804418919fSjohnjiang print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
1814418919fSjohnjiang {
1824418919fSjohnjiang 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
1834418919fSjohnjiang 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
1844418919fSjohnjiang 	printf("%s%s", name, buf);
1854418919fSjohnjiang }
1864418919fSjohnjiang 
1874418919fSjohnjiang static int
init_traffic(struct rte_mempool * mp,struct rte_mbuf ** pkts_burst,uint32_t burst_size)1884418919fSjohnjiang init_traffic(struct rte_mempool *mp,
1894418919fSjohnjiang 	     struct rte_mbuf **pkts_burst, uint32_t burst_size)
1904418919fSjohnjiang {
1914418919fSjohnjiang 	struct rte_ether_hdr pkt_eth_hdr;
1924418919fSjohnjiang 	struct rte_ipv4_hdr pkt_ipv4_hdr;
1934418919fSjohnjiang 	struct rte_udp_hdr pkt_udp_hdr;
1944418919fSjohnjiang 	uint32_t pktlen;
1954418919fSjohnjiang 	static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
1964418919fSjohnjiang 	static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
1974418919fSjohnjiang 
1984418919fSjohnjiang 
1994418919fSjohnjiang 	initialize_eth_header(&pkt_eth_hdr,
2004418919fSjohnjiang 		(struct rte_ether_addr *)src_mac,
2014418919fSjohnjiang 		(struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
2024418919fSjohnjiang 
2034418919fSjohnjiang 	pktlen = initialize_ipv4_header(&pkt_ipv4_hdr,
2044418919fSjohnjiang 					IPV4_ADDR(10, 0, 0, 1),
2054418919fSjohnjiang 					IPV4_ADDR(10, 0, 0, 2), 26);
2064418919fSjohnjiang 	printf("IPv4 pktlen %u\n", pktlen);
2074418919fSjohnjiang 
2084418919fSjohnjiang 	pktlen = initialize_udp_header(&pkt_udp_hdr, 0, 0, 18);
2094418919fSjohnjiang 
2104418919fSjohnjiang 	printf("UDP pktlen %u\n", pktlen);
2114418919fSjohnjiang 
2124418919fSjohnjiang 	return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr,
2134418919fSjohnjiang 				     0, &pkt_ipv4_hdr, 1,
2144418919fSjohnjiang 				     &pkt_udp_hdr, burst_size,
2154418919fSjohnjiang 				     PACKET_BURST_GEN_PKT_LEN, 1);
2164418919fSjohnjiang }
2174418919fSjohnjiang 
2184418919fSjohnjiang static int
init_lcores(void)2194418919fSjohnjiang init_lcores(void)
2204418919fSjohnjiang {
2214418919fSjohnjiang 	unsigned lcore_id;
2224418919fSjohnjiang 
2234418919fSjohnjiang 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2244418919fSjohnjiang 		lcore_conf[lcore_id].socketid =
2254418919fSjohnjiang 			rte_lcore_to_socket_id(lcore_id);
2264418919fSjohnjiang 		if (rte_lcore_is_enabled(lcore_id) == 0) {
2274418919fSjohnjiang 			lcore_conf[lcore_id].status = LCORE_INVALID;
2284418919fSjohnjiang 			continue;
2294418919fSjohnjiang 		} else
2304418919fSjohnjiang 			lcore_conf[lcore_id].status = LCORE_AVAIL;
2314418919fSjohnjiang 	}
2324418919fSjohnjiang 	return 0;
2334418919fSjohnjiang }
2344418919fSjohnjiang 
2354418919fSjohnjiang static int
init_mbufpool(unsigned nb_mbuf)2364418919fSjohnjiang init_mbufpool(unsigned nb_mbuf)
2374418919fSjohnjiang {
2384418919fSjohnjiang 	int socketid;
2394418919fSjohnjiang 	unsigned lcore_id;
2404418919fSjohnjiang 	char s[64];
2414418919fSjohnjiang 
2424418919fSjohnjiang 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2434418919fSjohnjiang 		if (rte_lcore_is_enabled(lcore_id) == 0)
2444418919fSjohnjiang 			continue;
2454418919fSjohnjiang 
2464418919fSjohnjiang 		socketid = rte_lcore_to_socket_id(lcore_id);
2474418919fSjohnjiang 		if (socketid >= NB_SOCKETS) {
2484418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
2494418919fSjohnjiang 				"Socket %d of lcore %u is out of range %d\n",
2504418919fSjohnjiang 				socketid, lcore_id, NB_SOCKETS);
2514418919fSjohnjiang 		}
2524418919fSjohnjiang 		if (mbufpool[socketid] == NULL) {
2534418919fSjohnjiang 			snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
2544418919fSjohnjiang 			mbufpool[socketid] =
2554418919fSjohnjiang 				rte_pktmbuf_pool_create(s, nb_mbuf,
2564418919fSjohnjiang 					MEMPOOL_CACHE_SIZE, 0,
2574418919fSjohnjiang 					RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
2584418919fSjohnjiang 			if (mbufpool[socketid] == NULL)
2594418919fSjohnjiang 				rte_exit(EXIT_FAILURE,
2604418919fSjohnjiang 					"Cannot init mbuf pool on socket %d\n",
2614418919fSjohnjiang 					socketid);
2624418919fSjohnjiang 			else
2634418919fSjohnjiang 				printf("Allocated mbuf pool on socket %d\n",
2644418919fSjohnjiang 					socketid);
2654418919fSjohnjiang 		}
2664418919fSjohnjiang 	}
2674418919fSjohnjiang 	return 0;
2684418919fSjohnjiang }
2694418919fSjohnjiang 
2704418919fSjohnjiang static uint16_t
alloc_lcore(uint16_t socketid)2714418919fSjohnjiang alloc_lcore(uint16_t socketid)
2724418919fSjohnjiang {
2734418919fSjohnjiang 	unsigned lcore_id;
2744418919fSjohnjiang 
2754418919fSjohnjiang 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2764418919fSjohnjiang 		if (LCORE_AVAIL != lcore_conf[lcore_id].status ||
2774418919fSjohnjiang 		    lcore_conf[lcore_id].socketid != socketid ||
278*2d9fd380Sjfb8856606 		    lcore_id == rte_get_main_lcore())
2794418919fSjohnjiang 			continue;
2804418919fSjohnjiang 		lcore_conf[lcore_id].status = LCORE_USED;
2814418919fSjohnjiang 		lcore_conf[lcore_id].nb_ports = 0;
2824418919fSjohnjiang 		return lcore_id;
2834418919fSjohnjiang 	}
2844418919fSjohnjiang 
2854418919fSjohnjiang 	return (uint16_t)-1;
2864418919fSjohnjiang }
2874418919fSjohnjiang 
2884418919fSjohnjiang static volatile uint64_t stop;
2894418919fSjohnjiang static uint64_t count;
2904418919fSjohnjiang static uint64_t drop;
2914418919fSjohnjiang static uint64_t idle;
2924418919fSjohnjiang 
2934418919fSjohnjiang static void
reset_count(void)2944418919fSjohnjiang reset_count(void)
2954418919fSjohnjiang {
2964418919fSjohnjiang 	count = 0;
2974418919fSjohnjiang 	drop = 0;
2984418919fSjohnjiang 	idle = 0;
2994418919fSjohnjiang }
3004418919fSjohnjiang 
3014418919fSjohnjiang static void
stats_display(uint16_t port_id)3024418919fSjohnjiang stats_display(uint16_t port_id)
3034418919fSjohnjiang {
3044418919fSjohnjiang 	struct rte_eth_stats stats;
3054418919fSjohnjiang 	rte_eth_stats_get(port_id, &stats);
3064418919fSjohnjiang 
3074418919fSjohnjiang 	printf("  RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes:  "
3084418919fSjohnjiang 	       "%-"PRIu64"\n",
3094418919fSjohnjiang 	       stats.ipackets, stats.imissed, stats.ibytes);
3104418919fSjohnjiang 	printf("  RX-errors: %-10"PRIu64" RX-nombuf:  %-10"PRIu64"\n",
3114418919fSjohnjiang 	       stats.ierrors, stats.rx_nombuf);
3124418919fSjohnjiang 	printf("  TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes:  "
3134418919fSjohnjiang 	       "%-"PRIu64"\n",
3144418919fSjohnjiang 	       stats.opackets, stats.oerrors, stats.obytes);
3154418919fSjohnjiang }
3164418919fSjohnjiang 
3174418919fSjohnjiang static void
signal_handler(int signum)3184418919fSjohnjiang signal_handler(int signum)
3194418919fSjohnjiang {
3204418919fSjohnjiang 	/*  USR1 signal, stop testing */
3214418919fSjohnjiang 	if (signum == SIGUSR1) {
3224418919fSjohnjiang 		printf("Force Stop!\n");
3234418919fSjohnjiang 		stop = 1;
3244418919fSjohnjiang 	}
3254418919fSjohnjiang 
3264418919fSjohnjiang 	/*  USR2 signal, print stats */
3274418919fSjohnjiang 	if (signum == SIGUSR2)
3284418919fSjohnjiang 		stats_display(0);
3294418919fSjohnjiang }
3304418919fSjohnjiang 
3314418919fSjohnjiang struct rte_mbuf **tx_burst;
3324418919fSjohnjiang 
3334418919fSjohnjiang uint64_t (*do_measure)(struct lcore_conf *conf,
3344418919fSjohnjiang 		       struct rte_mbuf *pkts_burst[],
3354418919fSjohnjiang 		       uint64_t total_pkts);
3364418919fSjohnjiang 
3374418919fSjohnjiang static uint64_t
measure_rxtx(struct lcore_conf * conf,struct rte_mbuf * pkts_burst[],uint64_t total_pkts)3384418919fSjohnjiang measure_rxtx(struct lcore_conf *conf,
3394418919fSjohnjiang 	     struct rte_mbuf *pkts_burst[],
3404418919fSjohnjiang 	     uint64_t total_pkts)
3414418919fSjohnjiang {
3424418919fSjohnjiang 	unsigned i, portid, nb_rx, nb_tx;
3434418919fSjohnjiang 	uint64_t prev_tsc, cur_tsc;
3444418919fSjohnjiang 
3454418919fSjohnjiang 	prev_tsc = rte_rdtsc();
3464418919fSjohnjiang 
3474418919fSjohnjiang 	while (likely(!stop)) {
3484418919fSjohnjiang 		for (i = 0; i < conf->nb_ports; i++) {
3494418919fSjohnjiang 			portid = conf->portlist[i];
3504418919fSjohnjiang 			nb_rx = rte_eth_rx_burst(portid, 0,
3514418919fSjohnjiang 						 pkts_burst, MAX_PKT_BURST);
3524418919fSjohnjiang 			if (unlikely(nb_rx == 0)) {
3534418919fSjohnjiang 				idle++;
3544418919fSjohnjiang 				continue;
3554418919fSjohnjiang 			}
3564418919fSjohnjiang 
3574418919fSjohnjiang 			count += nb_rx;
3584418919fSjohnjiang 			nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
3594418919fSjohnjiang 			if (unlikely(nb_tx < nb_rx)) {
3604418919fSjohnjiang 				drop += (nb_rx - nb_tx);
3614418919fSjohnjiang 				do {
3624418919fSjohnjiang 					rte_pktmbuf_free(pkts_burst[nb_tx]);
3634418919fSjohnjiang 				} while (++nb_tx < nb_rx);
3644418919fSjohnjiang 			}
3654418919fSjohnjiang 		}
3664418919fSjohnjiang 		if (unlikely(count >= total_pkts))
3674418919fSjohnjiang 			break;
3684418919fSjohnjiang 	}
3694418919fSjohnjiang 
3704418919fSjohnjiang 	cur_tsc = rte_rdtsc();
3714418919fSjohnjiang 
3724418919fSjohnjiang 	return cur_tsc - prev_tsc;
3734418919fSjohnjiang }
3744418919fSjohnjiang 
3754418919fSjohnjiang static uint64_t
measure_rxonly(struct lcore_conf * conf,struct rte_mbuf * pkts_burst[],uint64_t total_pkts)3764418919fSjohnjiang measure_rxonly(struct lcore_conf *conf,
3774418919fSjohnjiang 	       struct rte_mbuf *pkts_burst[],
3784418919fSjohnjiang 	       uint64_t total_pkts)
3794418919fSjohnjiang {
3804418919fSjohnjiang 	unsigned i, portid, nb_rx, nb_tx;
3814418919fSjohnjiang 	uint64_t diff_tsc, cur_tsc;
3824418919fSjohnjiang 
3834418919fSjohnjiang 	diff_tsc = 0;
3844418919fSjohnjiang 	while (likely(!stop)) {
3854418919fSjohnjiang 		for (i = 0; i < conf->nb_ports; i++) {
3864418919fSjohnjiang 			portid = conf->portlist[i];
3874418919fSjohnjiang 
3884418919fSjohnjiang 			cur_tsc = rte_rdtsc();
3894418919fSjohnjiang 			nb_rx = rte_eth_rx_burst(portid, 0,
3904418919fSjohnjiang 						 pkts_burst, MAX_PKT_BURST);
3914418919fSjohnjiang 			if (unlikely(nb_rx == 0)) {
3924418919fSjohnjiang 				idle++;
3934418919fSjohnjiang 				continue;
3944418919fSjohnjiang 			}
3954418919fSjohnjiang 			diff_tsc += rte_rdtsc() - cur_tsc;
3964418919fSjohnjiang 
3974418919fSjohnjiang 			count += nb_rx;
3984418919fSjohnjiang 			nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
3994418919fSjohnjiang 			if (unlikely(nb_tx < nb_rx)) {
4004418919fSjohnjiang 				drop += (nb_rx - nb_tx);
4014418919fSjohnjiang 				do {
4024418919fSjohnjiang 					rte_pktmbuf_free(pkts_burst[nb_tx]);
4034418919fSjohnjiang 				} while (++nb_tx < nb_rx);
4044418919fSjohnjiang 			}
4054418919fSjohnjiang 		}
4064418919fSjohnjiang 		if (unlikely(count >= total_pkts))
4074418919fSjohnjiang 			break;
4084418919fSjohnjiang 	}
4094418919fSjohnjiang 
4104418919fSjohnjiang 	return diff_tsc;
4114418919fSjohnjiang }
4124418919fSjohnjiang 
4134418919fSjohnjiang static uint64_t
measure_txonly(struct lcore_conf * conf,struct rte_mbuf * pkts_burst[],uint64_t total_pkts)4144418919fSjohnjiang measure_txonly(struct lcore_conf *conf,
4154418919fSjohnjiang 	       struct rte_mbuf *pkts_burst[],
4164418919fSjohnjiang 	       uint64_t total_pkts)
4174418919fSjohnjiang {
4184418919fSjohnjiang 	unsigned i, portid, nb_rx, nb_tx;
4194418919fSjohnjiang 	uint64_t diff_tsc, cur_tsc;
4204418919fSjohnjiang 
4214418919fSjohnjiang 	printf("do tx measure\n");
4224418919fSjohnjiang 	diff_tsc = 0;
4234418919fSjohnjiang 	while (likely(!stop)) {
4244418919fSjohnjiang 		for (i = 0; i < conf->nb_ports; i++) {
4254418919fSjohnjiang 			portid = conf->portlist[i];
4264418919fSjohnjiang 			nb_rx = rte_eth_rx_burst(portid, 0,
4274418919fSjohnjiang 						 pkts_burst, MAX_PKT_BURST);
4284418919fSjohnjiang 			if (unlikely(nb_rx == 0)) {
4294418919fSjohnjiang 				idle++;
4304418919fSjohnjiang 				continue;
4314418919fSjohnjiang 			}
4324418919fSjohnjiang 
4334418919fSjohnjiang 			count += nb_rx;
4344418919fSjohnjiang 
4354418919fSjohnjiang 			cur_tsc = rte_rdtsc();
4364418919fSjohnjiang 			nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
4374418919fSjohnjiang 			if (unlikely(nb_tx < nb_rx)) {
4384418919fSjohnjiang 				drop += (nb_rx - nb_tx);
4394418919fSjohnjiang 				do {
4404418919fSjohnjiang 					rte_pktmbuf_free(pkts_burst[nb_tx]);
4414418919fSjohnjiang 				} while (++nb_tx < nb_rx);
4424418919fSjohnjiang 			}
4434418919fSjohnjiang 			diff_tsc += rte_rdtsc() - cur_tsc;
4444418919fSjohnjiang 		}
4454418919fSjohnjiang 		if (unlikely(count >= total_pkts))
4464418919fSjohnjiang 			break;
4474418919fSjohnjiang 	}
4484418919fSjohnjiang 
4494418919fSjohnjiang 	return diff_tsc;
4504418919fSjohnjiang }
4514418919fSjohnjiang 
4524418919fSjohnjiang /* main processing loop */
4534418919fSjohnjiang static int
main_loop(__rte_unused void * args)4544418919fSjohnjiang main_loop(__rte_unused void *args)
4554418919fSjohnjiang {
4564418919fSjohnjiang #define PACKET_SIZE 64
4574418919fSjohnjiang #define FRAME_GAP 12
4584418919fSjohnjiang #define MAC_PREAMBLE 8
4594418919fSjohnjiang 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
4604418919fSjohnjiang 	unsigned lcore_id;
4614418919fSjohnjiang 	unsigned i, portid, nb_rx = 0, nb_tx = 0;
4624418919fSjohnjiang 	struct lcore_conf *conf;
4634418919fSjohnjiang 	int pkt_per_port;
4644418919fSjohnjiang 	uint64_t diff_tsc;
4654418919fSjohnjiang 	uint64_t packets_per_second, total_packets;
4664418919fSjohnjiang 
4674418919fSjohnjiang 	lcore_id = rte_lcore_id();
4684418919fSjohnjiang 	conf = &lcore_conf[lcore_id];
4694418919fSjohnjiang 	if (conf->status != LCORE_USED)
4704418919fSjohnjiang 		return 0;
4714418919fSjohnjiang 
4724418919fSjohnjiang 	pkt_per_port = MAX_TRAFFIC_BURST;
4734418919fSjohnjiang 
4744418919fSjohnjiang 	int idx = 0;
4754418919fSjohnjiang 	for (i = 0; i < conf->nb_ports; i++) {
4764418919fSjohnjiang 		int num = pkt_per_port;
4774418919fSjohnjiang 		portid = conf->portlist[i];
4784418919fSjohnjiang 		printf("inject %d packet to port %d\n", num, portid);
4794418919fSjohnjiang 		while (num) {
4804418919fSjohnjiang 			nb_tx = RTE_MIN(MAX_PKT_BURST, num);
4814418919fSjohnjiang 			nb_tx = rte_eth_tx_burst(portid, 0,
4824418919fSjohnjiang 						&tx_burst[idx], nb_tx);
4834418919fSjohnjiang 			num -= nb_tx;
4844418919fSjohnjiang 			idx += nb_tx;
4854418919fSjohnjiang 		}
4864418919fSjohnjiang 	}
4874418919fSjohnjiang 	printf("Total packets inject to prime ports = %u\n", idx);
4884418919fSjohnjiang 
4894418919fSjohnjiang 	packets_per_second = (link_mbps * 1000 * 1000) /
4904418919fSjohnjiang 		((PACKET_SIZE + FRAME_GAP + MAC_PREAMBLE) * CHAR_BIT);
4914418919fSjohnjiang 	printf("Each port will do %"PRIu64" packets per second\n",
4924418919fSjohnjiang 	       packets_per_second);
4934418919fSjohnjiang 
4944418919fSjohnjiang 	total_packets = RTE_TEST_DURATION * conf->nb_ports * packets_per_second;
4954418919fSjohnjiang 	printf("Test will stop after at least %"PRIu64" packets received\n",
4964418919fSjohnjiang 		+ total_packets);
4974418919fSjohnjiang 
4984418919fSjohnjiang 	diff_tsc = do_measure(conf, pkts_burst, total_packets);
4994418919fSjohnjiang 
5004418919fSjohnjiang 	for (i = 0; i < conf->nb_ports; i++) {
5014418919fSjohnjiang 		portid = conf->portlist[i];
5024418919fSjohnjiang 		int nb_free = 0;
5034418919fSjohnjiang 		uint64_t timeout = 10000;
5044418919fSjohnjiang 		do { /* dry out */
5054418919fSjohnjiang 			nb_rx = rte_eth_rx_burst(portid, 0,
5064418919fSjohnjiang 						 pkts_burst, MAX_PKT_BURST);
5074418919fSjohnjiang 			nb_tx = 0;
5084418919fSjohnjiang 			while (nb_tx < nb_rx)
5094418919fSjohnjiang 				rte_pktmbuf_free(pkts_burst[nb_tx++]);
5104418919fSjohnjiang 			nb_free += nb_rx;
5114418919fSjohnjiang 
5124418919fSjohnjiang 			if (unlikely(nb_rx == 0))
5134418919fSjohnjiang 				timeout--;
5144418919fSjohnjiang 		} while (nb_free != pkt_per_port && timeout != 0);
5154418919fSjohnjiang 		printf("free %d (expected %d) mbuf left in port %u\n", nb_free,
5164418919fSjohnjiang 		       pkt_per_port, portid);
5174418919fSjohnjiang 	}
5184418919fSjohnjiang 
5194418919fSjohnjiang 	if (count == 0)
5204418919fSjohnjiang 		return -1;
5214418919fSjohnjiang 
5224418919fSjohnjiang 	printf("%"PRIu64" packet, %"PRIu64" drop, %"PRIu64" idle\n",
5234418919fSjohnjiang 	       count, drop, idle);
5244418919fSjohnjiang 	printf("Result: %"PRIu64" cycles per packet\n", diff_tsc / count);
5254418919fSjohnjiang 
5264418919fSjohnjiang 	return 0;
5274418919fSjohnjiang }
5284418919fSjohnjiang 
5294418919fSjohnjiang static rte_atomic64_t start;
5304418919fSjohnjiang 
5314418919fSjohnjiang static inline int
poll_burst(void * args)5324418919fSjohnjiang poll_burst(void *args)
5334418919fSjohnjiang {
5344418919fSjohnjiang #define MAX_IDLE           (10000)
5354418919fSjohnjiang 	unsigned lcore_id;
5364418919fSjohnjiang 	struct rte_mbuf **pkts_burst;
5374418919fSjohnjiang 	uint64_t diff_tsc, cur_tsc;
5384418919fSjohnjiang 	uint16_t next[RTE_MAX_ETHPORTS];
5394418919fSjohnjiang 	struct lcore_conf *conf;
5404418919fSjohnjiang 	uint32_t pkt_per_port = *((uint32_t *)args);
5414418919fSjohnjiang 	unsigned i, portid, nb_rx = 0;
5424418919fSjohnjiang 	uint64_t total;
5434418919fSjohnjiang 	uint64_t timeout = MAX_IDLE;
5444418919fSjohnjiang 	int num[RTE_MAX_ETHPORTS];
5454418919fSjohnjiang 
5464418919fSjohnjiang 	lcore_id = rte_lcore_id();
5474418919fSjohnjiang 	conf = &lcore_conf[lcore_id];
5484418919fSjohnjiang 	if (conf->status != LCORE_USED)
5494418919fSjohnjiang 		return 0;
5504418919fSjohnjiang 
5514418919fSjohnjiang 	total = pkt_per_port * conf->nb_ports;
5524418919fSjohnjiang 	printf("start to receive total expect %"PRIu64"\n", total);
5534418919fSjohnjiang 
5544418919fSjohnjiang 	pkts_burst = (struct rte_mbuf **)
5554418919fSjohnjiang 		rte_calloc_socket("poll_burst",
5564418919fSjohnjiang 				  total, sizeof(void *),
5574418919fSjohnjiang 				  RTE_CACHE_LINE_SIZE, conf->socketid);
5584418919fSjohnjiang 	if (!pkts_burst)
5594418919fSjohnjiang 		return -1;
5604418919fSjohnjiang 
5614418919fSjohnjiang 	for (i = 0; i < conf->nb_ports; i++) {
5624418919fSjohnjiang 		portid = conf->portlist[i];
5634418919fSjohnjiang 		next[portid] = i * pkt_per_port;
5644418919fSjohnjiang 		num[portid] = pkt_per_port;
5654418919fSjohnjiang 	}
5664418919fSjohnjiang 
5674418919fSjohnjiang 	while (!rte_atomic64_read(&start))
5684418919fSjohnjiang 		;
5694418919fSjohnjiang 
5704418919fSjohnjiang 	cur_tsc = rte_rdtsc();
5714418919fSjohnjiang 	while (total) {
5724418919fSjohnjiang 		for (i = 0; i < conf->nb_ports; i++) {
5734418919fSjohnjiang 			portid = conf->portlist[i];
5744418919fSjohnjiang 			nb_rx = rte_eth_rx_burst(portid, 0,
5754418919fSjohnjiang 					&pkts_burst[next[portid]],
5764418919fSjohnjiang 					RTE_MIN(MAX_PKT_BURST, num[portid]));
5774418919fSjohnjiang 			if (unlikely(nb_rx == 0)) {
5784418919fSjohnjiang 				timeout--;
5794418919fSjohnjiang 				if (unlikely(timeout == 0))
5804418919fSjohnjiang 					goto timeout;
5814418919fSjohnjiang 				continue;
5824418919fSjohnjiang 			}
5834418919fSjohnjiang 			next[portid] += nb_rx;
5844418919fSjohnjiang 			num[portid] -= nb_rx;
5854418919fSjohnjiang 			total -= nb_rx;
5864418919fSjohnjiang 		}
5874418919fSjohnjiang 	}
5884418919fSjohnjiang timeout:
5894418919fSjohnjiang 	diff_tsc = rte_rdtsc() - cur_tsc;
5904418919fSjohnjiang 
5914418919fSjohnjiang 	printf("%"PRIu64" packets lost, IDLE %"PRIu64" times\n",
5924418919fSjohnjiang 	       total, MAX_IDLE - timeout);
5934418919fSjohnjiang 	/* clean up */
5944418919fSjohnjiang 	total = pkt_per_port * conf->nb_ports - total;
5954418919fSjohnjiang 	for (i = 0; i < total; i++)
5964418919fSjohnjiang 		rte_pktmbuf_free(pkts_burst[i]);
5974418919fSjohnjiang 
5984418919fSjohnjiang 	rte_free(pkts_burst);
5994418919fSjohnjiang 
6004418919fSjohnjiang 	if (total > 0)
6014418919fSjohnjiang 		return diff_tsc / total;
6024418919fSjohnjiang 	else
6034418919fSjohnjiang 		return -1;
6044418919fSjohnjiang }
6054418919fSjohnjiang 
6064418919fSjohnjiang static int
exec_burst(uint32_t flags,int lcore)6074418919fSjohnjiang exec_burst(uint32_t flags, int lcore)
6084418919fSjohnjiang {
6094418919fSjohnjiang 	unsigned i, portid, nb_tx = 0;
6104418919fSjohnjiang 	struct lcore_conf *conf;
6114418919fSjohnjiang 	uint32_t pkt_per_port;
6124418919fSjohnjiang 	int num, idx = 0;
6134418919fSjohnjiang 	int diff_tsc;
6144418919fSjohnjiang 
6154418919fSjohnjiang 	conf = &lcore_conf[lcore];
6164418919fSjohnjiang 
6174418919fSjohnjiang 	pkt_per_port = MAX_TRAFFIC_BURST;
6184418919fSjohnjiang 	num = pkt_per_port * conf->nb_ports;
6194418919fSjohnjiang 
6204418919fSjohnjiang 	rte_atomic64_init(&start);
6214418919fSjohnjiang 
6224418919fSjohnjiang 	/* start polling thread, but not actually poll yet */
6234418919fSjohnjiang 	rte_eal_remote_launch(poll_burst,
6244418919fSjohnjiang 			      (void *)&pkt_per_port, lcore);
6254418919fSjohnjiang 
6264418919fSjohnjiang 	/* Only when polling first */
6274418919fSjohnjiang 	if (flags == SC_BURST_POLL_FIRST)
6284418919fSjohnjiang 		rte_atomic64_set(&start, 1);
6294418919fSjohnjiang 
6304418919fSjohnjiang 	/* start xmit */
6314418919fSjohnjiang 	while (num) {
6324418919fSjohnjiang 		nb_tx = RTE_MIN(MAX_PKT_BURST, num);
6334418919fSjohnjiang 		for (i = 0; i < conf->nb_ports; i++) {
6344418919fSjohnjiang 			portid = conf->portlist[i];
6354418919fSjohnjiang 			nb_tx = rte_eth_tx_burst(portid, 0,
6364418919fSjohnjiang 					 &tx_burst[idx], nb_tx);
6374418919fSjohnjiang 			idx += nb_tx;
6384418919fSjohnjiang 			num -= nb_tx;
6394418919fSjohnjiang 		}
6404418919fSjohnjiang 
6414418919fSjohnjiang 	}
6424418919fSjohnjiang 
6434418919fSjohnjiang 	sleep(5);
6444418919fSjohnjiang 
6454418919fSjohnjiang 	/* only when polling second  */
6464418919fSjohnjiang 	if (flags == SC_BURST_XMIT_FIRST)
6474418919fSjohnjiang 		rte_atomic64_set(&start, 1);
6484418919fSjohnjiang 
6494418919fSjohnjiang 	/* wait for polling finished */
6504418919fSjohnjiang 	diff_tsc = rte_eal_wait_lcore(lcore);
6514418919fSjohnjiang 	if (diff_tsc < 0) {
6524418919fSjohnjiang 		printf("exec_burst: Failed to measure cycles per packet\n");
6534418919fSjohnjiang 		return -1;
6544418919fSjohnjiang 	}
6554418919fSjohnjiang 
6564418919fSjohnjiang 	printf("Result: %d cycles per packet\n", diff_tsc);
6574418919fSjohnjiang 
6584418919fSjohnjiang 	return 0;
6594418919fSjohnjiang }
6604418919fSjohnjiang 
6614418919fSjohnjiang static int
test_pmd_perf(void)6624418919fSjohnjiang test_pmd_perf(void)
6634418919fSjohnjiang {
664*2d9fd380Sjfb8856606 	uint16_t nb_ports, num, nb_lcores, worker_id = (uint16_t)-1;
6654418919fSjohnjiang 	uint16_t nb_rxd = MAX_TRAFFIC_BURST;
6664418919fSjohnjiang 	uint16_t nb_txd = MAX_TRAFFIC_BURST;
6674418919fSjohnjiang 	uint16_t portid;
6684418919fSjohnjiang 	uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
6694418919fSjohnjiang 	int socketid = -1;
6704418919fSjohnjiang 	int ret;
6714418919fSjohnjiang 
6724418919fSjohnjiang 	printf("Start PMD RXTX cycles cost test.\n");
6734418919fSjohnjiang 
6744418919fSjohnjiang 	signal(SIGUSR1, signal_handler);
6754418919fSjohnjiang 	signal(SIGUSR2, signal_handler);
6764418919fSjohnjiang 
6774418919fSjohnjiang 	nb_ports = rte_eth_dev_count_avail();
6784418919fSjohnjiang 	if (nb_ports < NB_ETHPORTS_USED) {
6794418919fSjohnjiang 		printf("At least %u port(s) used for perf. test\n",
6804418919fSjohnjiang 		       NB_ETHPORTS_USED);
6814418919fSjohnjiang 		return -1;
6824418919fSjohnjiang 	}
6834418919fSjohnjiang 
6844418919fSjohnjiang 	nb_lcores = rte_lcore_count();
6854418919fSjohnjiang 
6864418919fSjohnjiang 	memset(lcore_conf, 0, sizeof(lcore_conf));
6874418919fSjohnjiang 	init_lcores();
6884418919fSjohnjiang 
6894418919fSjohnjiang 	init_mbufpool(NB_MBUF);
6904418919fSjohnjiang 
6914418919fSjohnjiang 	if (sc_flag == SC_CONTINUOUS) {
6924418919fSjohnjiang 		nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
6934418919fSjohnjiang 		nb_txd = RTE_TEST_TX_DESC_DEFAULT;
6944418919fSjohnjiang 	}
6954418919fSjohnjiang 	printf("CONFIG RXD=%d TXD=%d\n", nb_rxd, nb_txd);
6964418919fSjohnjiang 
6974418919fSjohnjiang 	reset_count();
6984418919fSjohnjiang 	num = 0;
6994418919fSjohnjiang 	RTE_ETH_FOREACH_DEV(portid) {
7004418919fSjohnjiang 		if (socketid == -1) {
7014418919fSjohnjiang 			socketid = rte_eth_dev_socket_id(portid);
702*2d9fd380Sjfb8856606 			worker_id = alloc_lcore(socketid);
703*2d9fd380Sjfb8856606 			if (worker_id == (uint16_t)-1) {
7044418919fSjohnjiang 				printf("No avail lcore to run test\n");
7054418919fSjohnjiang 				return -1;
7064418919fSjohnjiang 			}
7074418919fSjohnjiang 			printf("Performance test runs on lcore %u socket %u\n",
708*2d9fd380Sjfb8856606 			       worker_id, socketid);
7094418919fSjohnjiang 		}
7104418919fSjohnjiang 
7114418919fSjohnjiang 		if (socketid != rte_eth_dev_socket_id(portid)) {
7124418919fSjohnjiang 			printf("Skip port %d\n", portid);
7134418919fSjohnjiang 			continue;
7144418919fSjohnjiang 		}
7154418919fSjohnjiang 
7164418919fSjohnjiang 		/* port configure */
7174418919fSjohnjiang 		ret = rte_eth_dev_configure(portid, nb_rx_queue,
7184418919fSjohnjiang 					    nb_tx_queue, &port_conf);
7194418919fSjohnjiang 		if (ret < 0)
7204418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
7214418919fSjohnjiang 				"Cannot configure device: err=%d, port=%d\n",
7224418919fSjohnjiang 				 ret, portid);
7234418919fSjohnjiang 
7244418919fSjohnjiang 		ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
7254418919fSjohnjiang 		if (ret < 0)
7264418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
7274418919fSjohnjiang 				"Cannot get mac address: err=%d, port=%d\n",
7284418919fSjohnjiang 				 ret, portid);
7294418919fSjohnjiang 
7304418919fSjohnjiang 		printf("Port %u ", portid);
7314418919fSjohnjiang 		print_ethaddr("Address:", &ports_eth_addr[portid]);
7324418919fSjohnjiang 		printf("\n");
7334418919fSjohnjiang 
7344418919fSjohnjiang 		/* tx queue setup */
7354418919fSjohnjiang 		ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
7364418919fSjohnjiang 					     socketid, &tx_conf);
7374418919fSjohnjiang 		if (ret < 0)
7384418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
7394418919fSjohnjiang 				"rte_eth_tx_queue_setup: err=%d, "
7404418919fSjohnjiang 				"port=%d\n", ret, portid);
7414418919fSjohnjiang 
7424418919fSjohnjiang 		/* rx queue steup */
7434418919fSjohnjiang 		ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
7444418919fSjohnjiang 						socketid, &rx_conf,
7454418919fSjohnjiang 						mbufpool[socketid]);
7464418919fSjohnjiang 		if (ret < 0)
7474418919fSjohnjiang 			rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d,"
7484418919fSjohnjiang 				 "port=%d\n", ret, portid);
7494418919fSjohnjiang 
7504418919fSjohnjiang 		/* Start device */
7514418919fSjohnjiang 		stop = 0;
7524418919fSjohnjiang 		ret = rte_eth_dev_start(portid);
7534418919fSjohnjiang 		if (ret < 0)
7544418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
7554418919fSjohnjiang 				"rte_eth_dev_start: err=%d, port=%d\n",
7564418919fSjohnjiang 				ret, portid);
7574418919fSjohnjiang 
7584418919fSjohnjiang 		/* always eanble promiscuous */
7594418919fSjohnjiang 		ret = rte_eth_promiscuous_enable(portid);
7604418919fSjohnjiang 		if (ret != 0)
7614418919fSjohnjiang 			rte_exit(EXIT_FAILURE,
7624418919fSjohnjiang 				 "rte_eth_promiscuous_enable: err=%s, port=%d\n",
7634418919fSjohnjiang 				 rte_strerror(-ret), portid);
7644418919fSjohnjiang 
765*2d9fd380Sjfb8856606 		lcore_conf[worker_id].portlist[num++] = portid;
766*2d9fd380Sjfb8856606 		lcore_conf[worker_id].nb_ports++;
7674418919fSjohnjiang 	}
7684418919fSjohnjiang 	check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
7694418919fSjohnjiang 
7704418919fSjohnjiang 	if (tx_burst == NULL) {
7714418919fSjohnjiang 		tx_burst = (struct rte_mbuf **)
7724418919fSjohnjiang 			rte_calloc_socket("tx_buff",
7734418919fSjohnjiang 					  MAX_TRAFFIC_BURST * nb_ports,
7744418919fSjohnjiang 					  sizeof(void *),
7754418919fSjohnjiang 					  RTE_CACHE_LINE_SIZE, socketid);
7764418919fSjohnjiang 		if (!tx_burst)
7774418919fSjohnjiang 			return -1;
7784418919fSjohnjiang 	}
7794418919fSjohnjiang 
7804418919fSjohnjiang 	init_traffic(mbufpool[socketid],
7814418919fSjohnjiang 		     tx_burst, MAX_TRAFFIC_BURST * nb_ports);
7824418919fSjohnjiang 
7834418919fSjohnjiang 	printf("Generate %d packets @socket %d\n",
7844418919fSjohnjiang 	       MAX_TRAFFIC_BURST * nb_ports, socketid);
7854418919fSjohnjiang 
7864418919fSjohnjiang 	if (sc_flag == SC_CONTINUOUS) {
7874418919fSjohnjiang 		/* do both rxtx by default */
7884418919fSjohnjiang 		if (NULL == do_measure)
7894418919fSjohnjiang 			do_measure = measure_rxtx;
7904418919fSjohnjiang 
791*2d9fd380Sjfb8856606 		rte_eal_remote_launch(main_loop, NULL, worker_id);
7924418919fSjohnjiang 
793*2d9fd380Sjfb8856606 		if (rte_eal_wait_lcore(worker_id) < 0)
7944418919fSjohnjiang 			return -1;
7954418919fSjohnjiang 	} else if (sc_flag == SC_BURST_POLL_FIRST ||
7964418919fSjohnjiang 		   sc_flag == SC_BURST_XMIT_FIRST)
797*2d9fd380Sjfb8856606 		if (exec_burst(sc_flag, worker_id) < 0)
7984418919fSjohnjiang 			return -1;
7994418919fSjohnjiang 
8004418919fSjohnjiang 	/* port tear down */
8014418919fSjohnjiang 	RTE_ETH_FOREACH_DEV(portid) {
8024418919fSjohnjiang 		if (socketid != rte_eth_dev_socket_id(portid))
8034418919fSjohnjiang 			continue;
8044418919fSjohnjiang 
805*2d9fd380Sjfb8856606 		ret = rte_eth_dev_stop(portid);
806*2d9fd380Sjfb8856606 		if (ret != 0)
807*2d9fd380Sjfb8856606 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
808*2d9fd380Sjfb8856606 			       rte_strerror(-ret), portid);
8094418919fSjohnjiang 	}
8104418919fSjohnjiang 
8114418919fSjohnjiang 	return 0;
8124418919fSjohnjiang }
8134418919fSjohnjiang 
8144418919fSjohnjiang int
test_set_rxtx_conf(cmdline_fixed_string_t mode)8154418919fSjohnjiang test_set_rxtx_conf(cmdline_fixed_string_t mode)
8164418919fSjohnjiang {
8174418919fSjohnjiang 	printf("mode switch to %s\n", mode);
8184418919fSjohnjiang 
8194418919fSjohnjiang 	if (!strcmp(mode, "vector")) {
8204418919fSjohnjiang 		/* vector rx, tx */
8214418919fSjohnjiang 		tx_conf.tx_rs_thresh = 32;
8224418919fSjohnjiang 		tx_conf.tx_free_thresh = 32;
8234418919fSjohnjiang 		return 0;
8244418919fSjohnjiang 	} else if (!strcmp(mode, "scalar")) {
8254418919fSjohnjiang 		/* bulk alloc rx, full-featured tx */
8264418919fSjohnjiang 		tx_conf.tx_rs_thresh = 32;
8274418919fSjohnjiang 		tx_conf.tx_free_thresh = 32;
8284418919fSjohnjiang 		port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
8294418919fSjohnjiang 		return 0;
8304418919fSjohnjiang 	} else if (!strcmp(mode, "hybrid")) {
8314418919fSjohnjiang 		/* bulk alloc rx, vector tx
8324418919fSjohnjiang 		 * when vec macro not define,
8334418919fSjohnjiang 		 * using the same rx/tx as scalar
8344418919fSjohnjiang 		 */
8354418919fSjohnjiang 		tx_conf.tx_rs_thresh = 32;
8364418919fSjohnjiang 		tx_conf.tx_free_thresh = 32;
8374418919fSjohnjiang 		port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
8384418919fSjohnjiang 		return 0;
8394418919fSjohnjiang 	} else if (!strcmp(mode, "full")) {
8404418919fSjohnjiang 		/* full feature rx,tx pair */
8414418919fSjohnjiang 		tx_conf.tx_rs_thresh = 32;
8424418919fSjohnjiang 		tx_conf.tx_free_thresh = 32;
8434418919fSjohnjiang 		port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER;
8444418919fSjohnjiang 		return 0;
8454418919fSjohnjiang 	}
8464418919fSjohnjiang 
8474418919fSjohnjiang 	return -1;
8484418919fSjohnjiang }
8494418919fSjohnjiang 
8504418919fSjohnjiang int
test_set_rxtx_anchor(cmdline_fixed_string_t type)8514418919fSjohnjiang test_set_rxtx_anchor(cmdline_fixed_string_t type)
8524418919fSjohnjiang {
8534418919fSjohnjiang 	printf("type switch to %s\n", type);
8544418919fSjohnjiang 
8554418919fSjohnjiang 	if (!strcmp(type, "rxtx")) {
8564418919fSjohnjiang 		do_measure = measure_rxtx;
8574418919fSjohnjiang 		return 0;
8584418919fSjohnjiang 	} else if (!strcmp(type, "rxonly")) {
8594418919fSjohnjiang 		do_measure = measure_rxonly;
8604418919fSjohnjiang 		return 0;
8614418919fSjohnjiang 	} else if (!strcmp(type, "txonly")) {
8624418919fSjohnjiang 		do_measure = measure_txonly;
8634418919fSjohnjiang 		return 0;
8644418919fSjohnjiang 	}
8654418919fSjohnjiang 
8664418919fSjohnjiang 	return -1;
8674418919fSjohnjiang }
8684418919fSjohnjiang 
8694418919fSjohnjiang int
test_set_rxtx_sc(cmdline_fixed_string_t type)8704418919fSjohnjiang test_set_rxtx_sc(cmdline_fixed_string_t type)
8714418919fSjohnjiang {
8724418919fSjohnjiang 	printf("stream control switch to %s\n", type);
8734418919fSjohnjiang 
8744418919fSjohnjiang 	if (!strcmp(type, "continuous")) {
8754418919fSjohnjiang 		sc_flag = SC_CONTINUOUS;
8764418919fSjohnjiang 		return 0;
8774418919fSjohnjiang 	} else if (!strcmp(type, "poll_before_xmit")) {
8784418919fSjohnjiang 		sc_flag = SC_BURST_POLL_FIRST;
8794418919fSjohnjiang 		return 0;
8804418919fSjohnjiang 	} else if (!strcmp(type, "poll_after_xmit")) {
8814418919fSjohnjiang 		sc_flag = SC_BURST_XMIT_FIRST;
8824418919fSjohnjiang 		return 0;
8834418919fSjohnjiang 	}
8844418919fSjohnjiang 
8854418919fSjohnjiang 	return -1;
8864418919fSjohnjiang }
8874418919fSjohnjiang 
8884418919fSjohnjiang REGISTER_TEST_COMMAND(pmd_perf_autotest, test_pmd_perf);
889