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