xref: /dpdk/app/test-pmd/testpmd.c (revision 36db4f6c70b43f307dd2a1ece19d910a3548349d)
1174a1631SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2174a1631SBruce Richardson  * Copyright(c) 2010-2017 Intel Corporation
3af75078fSIntel  */
4af75078fSIntel 
5af75078fSIntel #include <stdarg.h>
6af75078fSIntel #include <stdio.h>
7af75078fSIntel #include <stdlib.h>
8af75078fSIntel #include <signal.h>
9af75078fSIntel #include <string.h>
10af75078fSIntel #include <time.h>
11af75078fSIntel #include <fcntl.h>
121c036b16SEelco Chaudron #include <sys/mman.h>
13af75078fSIntel #include <sys/types.h>
14af75078fSIntel #include <errno.h>
15af75078fSIntel 
16af75078fSIntel #include <sys/queue.h>
17af75078fSIntel #include <sys/stat.h>
18af75078fSIntel 
19af75078fSIntel #include <stdint.h>
20af75078fSIntel #include <unistd.h>
21af75078fSIntel #include <inttypes.h>
22af75078fSIntel 
23af75078fSIntel #include <rte_common.h>
24d1eb542eSOlivier Matz #include <rte_errno.h>
25af75078fSIntel #include <rte_byteorder.h>
26af75078fSIntel #include <rte_log.h>
27af75078fSIntel #include <rte_debug.h>
28af75078fSIntel #include <rte_cycles.h>
29af75078fSIntel #include <rte_memory.h>
30af75078fSIntel #include <rte_memcpy.h>
31af75078fSIntel #include <rte_launch.h>
32af75078fSIntel #include <rte_eal.h>
33284c908cSGaetan Rivet #include <rte_alarm.h>
34af75078fSIntel #include <rte_per_lcore.h>
35af75078fSIntel #include <rte_lcore.h>
36af75078fSIntel #include <rte_atomic.h>
37af75078fSIntel #include <rte_branch_prediction.h>
38af75078fSIntel #include <rte_mempool.h>
39af75078fSIntel #include <rte_malloc.h>
40af75078fSIntel #include <rte_mbuf.h>
41af75078fSIntel #include <rte_interrupts.h>
42af75078fSIntel #include <rte_pci.h>
43af75078fSIntel #include <rte_ether.h>
44af75078fSIntel #include <rte_ethdev.h>
45edab33b1STetsuya Mukawa #include <rte_dev.h>
46af75078fSIntel #include <rte_string_fns.h>
47e261265eSRadu Nicolau #ifdef RTE_LIBRTE_IXGBE_PMD
48e261265eSRadu Nicolau #include <rte_pmd_ixgbe.h>
49e261265eSRadu Nicolau #endif
50102b7329SReshma Pattan #ifdef RTE_LIBRTE_PDUMP
51102b7329SReshma Pattan #include <rte_pdump.h>
52102b7329SReshma Pattan #endif
53938a184aSAdrien Mazarguil #include <rte_flow.h>
547e4441c8SRemy Horton #include <rte_metrics.h>
557e4441c8SRemy Horton #ifdef RTE_LIBRTE_BITRATE
567e4441c8SRemy Horton #include <rte_bitrate.h>
577e4441c8SRemy Horton #endif
5862d3216dSReshma Pattan #ifdef RTE_LIBRTE_LATENCY_STATS
5962d3216dSReshma Pattan #include <rte_latencystats.h>
6062d3216dSReshma Pattan #endif
61af75078fSIntel 
62af75078fSIntel #include "testpmd.h"
63af75078fSIntel 
64af75078fSIntel uint16_t verbose_level = 0; /**< Silent by default. */
65285fd101SOlivier Matz int testpmd_logtype; /**< Log type for testpmd logs */
66af75078fSIntel 
67af75078fSIntel /* use master core for command line ? */
68af75078fSIntel uint8_t interactive = 0;
69ca7feb22SCyril Chemparathy uint8_t auto_start = 0;
7099cabef0SPablo de Lara uint8_t tx_first;
7181ef862bSAllain Legacy char cmdline_filename[PATH_MAX] = {0};
72af75078fSIntel 
73af75078fSIntel /*
74af75078fSIntel  * NUMA support configuration.
75af75078fSIntel  * When set, the NUMA support attempts to dispatch the allocation of the
76af75078fSIntel  * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the
77af75078fSIntel  * probed ports among the CPU sockets 0 and 1.
78af75078fSIntel  * Otherwise, all memory is allocated from CPU socket 0.
79af75078fSIntel  */
80999b2ee0SBruce Richardson uint8_t numa_support = 1; /**< numa enabled by default */
81af75078fSIntel 
82af75078fSIntel /*
83b6ea6408SIntel  * In UMA mode,all memory is allocated from socket 0 if --socket-num is
84b6ea6408SIntel  * not configured.
85b6ea6408SIntel  */
86b6ea6408SIntel uint8_t socket_num = UMA_NO_CONFIG;
87b6ea6408SIntel 
88b6ea6408SIntel /*
89148f963fSBruce Richardson  * Use ANONYMOUS mapped memory (might be not physically continuous) for mbufs.
90148f963fSBruce Richardson  */
91148f963fSBruce Richardson uint8_t mp_anon = 0;
92148f963fSBruce Richardson 
93148f963fSBruce Richardson /*
94af75078fSIntel  * Record the Ethernet address of peer target ports to which packets are
95af75078fSIntel  * forwarded.
96547d946cSNirmoy Das  * Must be instantiated with the ethernet addresses of peer traffic generator
97af75078fSIntel  * ports.
98af75078fSIntel  */
99af75078fSIntel struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
100af75078fSIntel portid_t nb_peer_eth_addrs = 0;
101af75078fSIntel 
102af75078fSIntel /*
103af75078fSIntel  * Probed Target Environment.
104af75078fSIntel  */
105af75078fSIntel struct rte_port *ports;	       /**< For all probed ethernet ports. */
106af75078fSIntel portid_t nb_ports;             /**< Number of probed ethernet ports. */
107af75078fSIntel struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */
108af75078fSIntel lcoreid_t nb_lcores;           /**< Number of probed logical cores. */
109af75078fSIntel 
110af75078fSIntel /*
111af75078fSIntel  * Test Forwarding Configuration.
112af75078fSIntel  *    nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
113af75078fSIntel  *    nb_fwd_ports  <= nb_cfg_ports  <= nb_ports
114af75078fSIntel  */
115af75078fSIntel lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
116af75078fSIntel lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
117af75078fSIntel portid_t  nb_cfg_ports;  /**< Number of configured ports. */
118af75078fSIntel portid_t  nb_fwd_ports;  /**< Number of forwarding ports. */
119af75078fSIntel 
120af75078fSIntel unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */
121af75078fSIntel portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids configuration. */
122af75078fSIntel 
123af75078fSIntel struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
124af75078fSIntel streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */
125af75078fSIntel 
126af75078fSIntel /*
127af75078fSIntel  * Forwarding engines.
128af75078fSIntel  */
129af75078fSIntel struct fwd_engine * fwd_engines[] = {
130af75078fSIntel 	&io_fwd_engine,
131af75078fSIntel 	&mac_fwd_engine,
132d47388f1SCyril Chemparathy 	&mac_swap_engine,
133e9e23a61SCyril Chemparathy 	&flow_gen_engine,
134af75078fSIntel 	&rx_only_engine,
135af75078fSIntel 	&tx_only_engine,
136af75078fSIntel 	&csum_fwd_engine,
137168dfa61SIvan Boule 	&icmp_echo_engine,
1385b590fbeSJasvinder Singh #if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
1395b590fbeSJasvinder Singh 	&softnic_tm_engine,
1405b590fbeSJasvinder Singh 	&softnic_tm_bypass_engine,
1415b590fbeSJasvinder Singh #endif
142af75078fSIntel #ifdef RTE_LIBRTE_IEEE1588
143af75078fSIntel 	&ieee1588_fwd_engine,
144af75078fSIntel #endif
145af75078fSIntel 	NULL,
146af75078fSIntel };
147af75078fSIntel 
148af75078fSIntel struct fwd_config cur_fwd_config;
149af75078fSIntel struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */
150bf56fce1SZhihong Wang uint32_t retry_enabled;
151bf56fce1SZhihong Wang uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;
152bf56fce1SZhihong Wang uint32_t burst_tx_retry_num = BURST_TX_RETRIES;
153af75078fSIntel 
154af75078fSIntel uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */
155c8798818SIntel uint32_t param_total_num_mbufs = 0;  /**< number of mbufs in all pools - if
156c8798818SIntel                                       * specified on command-line. */
157cfea1f30SPablo de Lara uint16_t stats_period; /**< Period to show statistics (disabled by default) */
158d9a191a0SPhil Yang 
159d9a191a0SPhil Yang /*
160d9a191a0SPhil Yang  * In container, it cannot terminate the process which running with 'stats-period'
161d9a191a0SPhil Yang  * option. Set flag to exit stats period loop after received SIGINT/SIGTERM.
162d9a191a0SPhil Yang  */
163d9a191a0SPhil Yang uint8_t f_quit;
164d9a191a0SPhil Yang 
165af75078fSIntel /*
166af75078fSIntel  * Configuration of packet segments used by the "txonly" processing engine.
167af75078fSIntel  */
168af75078fSIntel uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */
169af75078fSIntel uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
170af75078fSIntel 	TXONLY_DEF_PACKET_LEN,
171af75078fSIntel };
172af75078fSIntel uint8_t  tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */
173af75078fSIntel 
17479bec05bSKonstantin Ananyev enum tx_pkt_split tx_pkt_split = TX_PKT_SPLIT_OFF;
17579bec05bSKonstantin Ananyev /**< Split policy for packets to TX. */
17679bec05bSKonstantin Ananyev 
177af75078fSIntel uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */
178e9378bbcSCunming Liang uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */
179af75078fSIntel 
180900550deSIntel /* current configuration is in DCB or not,0 means it is not in DCB mode */
181900550deSIntel uint8_t dcb_config = 0;
182900550deSIntel 
183900550deSIntel /* Whether the dcb is in testing status */
184900550deSIntel uint8_t dcb_test = 0;
185900550deSIntel 
186af75078fSIntel /*
187af75078fSIntel  * Configurable number of RX/TX queues.
188af75078fSIntel  */
189af75078fSIntel queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
190af75078fSIntel queueid_t nb_txq = 1; /**< Number of TX queues per port. */
191af75078fSIntel 
192af75078fSIntel /*
193af75078fSIntel  * Configurable number of RX/TX ring descriptors.
194af75078fSIntel  */
195af75078fSIntel #define RTE_TEST_RX_DESC_DEFAULT 128
196af75078fSIntel #define RTE_TEST_TX_DESC_DEFAULT 512
197af75078fSIntel uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
198af75078fSIntel uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
199af75078fSIntel 
200f2c5125aSPablo de Lara #define RTE_PMD_PARAM_UNSET -1
201af75078fSIntel /*
202af75078fSIntel  * Configurable values of RX and TX ring threshold registers.
203af75078fSIntel  */
204af75078fSIntel 
205f2c5125aSPablo de Lara int8_t rx_pthresh = RTE_PMD_PARAM_UNSET;
206f2c5125aSPablo de Lara int8_t rx_hthresh = RTE_PMD_PARAM_UNSET;
207f2c5125aSPablo de Lara int8_t rx_wthresh = RTE_PMD_PARAM_UNSET;
208af75078fSIntel 
209f2c5125aSPablo de Lara int8_t tx_pthresh = RTE_PMD_PARAM_UNSET;
210f2c5125aSPablo de Lara int8_t tx_hthresh = RTE_PMD_PARAM_UNSET;
211f2c5125aSPablo de Lara int8_t tx_wthresh = RTE_PMD_PARAM_UNSET;
212af75078fSIntel 
213af75078fSIntel /*
214af75078fSIntel  * Configurable value of RX free threshold.
215af75078fSIntel  */
216f2c5125aSPablo de Lara int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET;
217af75078fSIntel 
218af75078fSIntel /*
219ce8d5614SIntel  * Configurable value of RX drop enable.
220ce8d5614SIntel  */
221f2c5125aSPablo de Lara int8_t rx_drop_en = RTE_PMD_PARAM_UNSET;
222ce8d5614SIntel 
223ce8d5614SIntel /*
224af75078fSIntel  * Configurable value of TX free threshold.
225af75078fSIntel  */
226f2c5125aSPablo de Lara int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
227af75078fSIntel 
228af75078fSIntel /*
229af75078fSIntel  * Configurable value of TX RS bit threshold.
230af75078fSIntel  */
231f2c5125aSPablo de Lara int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
232af75078fSIntel 
233af75078fSIntel /*
234af75078fSIntel  * Receive Side Scaling (RSS) configuration.
235af75078fSIntel  */
2368a387fa8SHelin Zhang uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */
237af75078fSIntel 
238af75078fSIntel /*
239af75078fSIntel  * Port topology configuration
240af75078fSIntel  */
241af75078fSIntel uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */
242af75078fSIntel 
2437741e4cfSIntel /*
2447741e4cfSIntel  * Avoids to flush all the RX streams before starts forwarding.
2457741e4cfSIntel  */
2467741e4cfSIntel uint8_t no_flush_rx = 0; /* flush by default */
2477741e4cfSIntel 
248af75078fSIntel /*
2497ee3e944SVasily Philipov  * Flow API isolated mode.
2507ee3e944SVasily Philipov  */
2517ee3e944SVasily Philipov uint8_t flow_isolate_all;
2527ee3e944SVasily Philipov 
2537ee3e944SVasily Philipov /*
254bc202406SDavid Marchand  * Avoids to check link status when starting/stopping a port.
255bc202406SDavid Marchand  */
256bc202406SDavid Marchand uint8_t no_link_check = 0; /* check by default */
257bc202406SDavid Marchand 
258bc202406SDavid Marchand /*
2598ea656f8SGaetan Rivet  * Enable link status change notification
2608ea656f8SGaetan Rivet  */
2618ea656f8SGaetan Rivet uint8_t lsc_interrupt = 1; /* enabled by default */
2628ea656f8SGaetan Rivet 
2638ea656f8SGaetan Rivet /*
264284c908cSGaetan Rivet  * Enable device removal notification.
265284c908cSGaetan Rivet  */
266284c908cSGaetan Rivet uint8_t rmv_interrupt = 1; /* enabled by default */
267284c908cSGaetan Rivet 
268284c908cSGaetan Rivet /*
2693af72783SGaetan Rivet  * Display or mask ether events
2703af72783SGaetan Rivet  * Default to all events except VF_MBOX
2713af72783SGaetan Rivet  */
2723af72783SGaetan Rivet uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) |
2733af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) |
2743af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) |
2753af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) |
2763af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) |
2773af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV);
2783af72783SGaetan Rivet 
2793af72783SGaetan Rivet /*
2807b7e5ba7SIntel  * NIC bypass mode configuration options.
2817b7e5ba7SIntel  */
2827b7e5ba7SIntel 
28350c4440eSThomas Monjalon #if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
2847b7e5ba7SIntel /* The NIC bypass watchdog timeout. */
285e261265eSRadu Nicolau uint32_t bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
2867b7e5ba7SIntel #endif
2877b7e5ba7SIntel 
288e261265eSRadu Nicolau 
28962d3216dSReshma Pattan #ifdef RTE_LIBRTE_LATENCY_STATS
29062d3216dSReshma Pattan 
29162d3216dSReshma Pattan /*
29262d3216dSReshma Pattan  * Set when latency stats is enabled in the commandline
29362d3216dSReshma Pattan  */
29462d3216dSReshma Pattan uint8_t latencystats_enabled;
29562d3216dSReshma Pattan 
29662d3216dSReshma Pattan /*
29762d3216dSReshma Pattan  * Lcore ID to serive latency statistics.
29862d3216dSReshma Pattan  */
29962d3216dSReshma Pattan lcoreid_t latencystats_lcore_id = -1;
30062d3216dSReshma Pattan 
30162d3216dSReshma Pattan #endif
30262d3216dSReshma Pattan 
3037b7e5ba7SIntel /*
304af75078fSIntel  * Ethernet device configuration.
305af75078fSIntel  */
306af75078fSIntel struct rte_eth_rxmode rx_mode = {
307af75078fSIntel 	.max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
3080074d02fSShahaf Shuler 	.offloads = (DEV_RX_OFFLOAD_VLAN_FILTER |
3090074d02fSShahaf Shuler 		     DEV_RX_OFFLOAD_VLAN_STRIP |
3100074d02fSShahaf Shuler 		     DEV_RX_OFFLOAD_CRC_STRIP),
3110074d02fSShahaf Shuler 	.ignore_offload_bitfield = 1,
312af75078fSIntel };
313af75078fSIntel 
31407e5f7bdSShahaf Shuler struct rte_eth_txmode tx_mode = {
31507e5f7bdSShahaf Shuler 	.offloads = DEV_TX_OFFLOAD_MBUF_FAST_FREE,
31607e5f7bdSShahaf Shuler };
317fd8c20aaSShahaf Shuler 
318af75078fSIntel struct rte_fdir_conf fdir_conf = {
319af75078fSIntel 	.mode = RTE_FDIR_MODE_NONE,
320af75078fSIntel 	.pballoc = RTE_FDIR_PBALLOC_64K,
321af75078fSIntel 	.status = RTE_FDIR_REPORT_STATUS,
322d9d5e6f2SJingjing Wu 	.mask = {
323d9d5e6f2SJingjing Wu 		.vlan_tci_mask = 0x0,
324d9d5e6f2SJingjing Wu 		.ipv4_mask     = {
325d9d5e6f2SJingjing Wu 			.src_ip = 0xFFFFFFFF,
326d9d5e6f2SJingjing Wu 			.dst_ip = 0xFFFFFFFF,
327d9d5e6f2SJingjing Wu 		},
328d9d5e6f2SJingjing Wu 		.ipv6_mask     = {
329d9d5e6f2SJingjing Wu 			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
330d9d5e6f2SJingjing Wu 			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
331d9d5e6f2SJingjing Wu 		},
332d9d5e6f2SJingjing Wu 		.src_port_mask = 0xFFFF,
333d9d5e6f2SJingjing Wu 		.dst_port_mask = 0xFFFF,
33447b3ac6bSWenzhuo Lu 		.mac_addr_byte_mask = 0xFF,
33547b3ac6bSWenzhuo Lu 		.tunnel_type_mask = 1,
33647b3ac6bSWenzhuo Lu 		.tunnel_id_mask = 0xFFFFFFFF,
337d9d5e6f2SJingjing Wu 	},
338af75078fSIntel 	.drop_queue = 127,
339af75078fSIntel };
340af75078fSIntel 
3412950a769SDeclan Doherty volatile int test_done = 1; /* stop packet forwarding when set to 1. */
342af75078fSIntel 
343ed30d9b6SIntel struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS];
344ed30d9b6SIntel struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS];
345ed30d9b6SIntel 
346ed30d9b6SIntel struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array;
347ed30d9b6SIntel struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array;
348ed30d9b6SIntel 
349ed30d9b6SIntel uint16_t nb_tx_queue_stats_mappings = 0;
350ed30d9b6SIntel uint16_t nb_rx_queue_stats_mappings = 0;
351ed30d9b6SIntel 
352a4fd5eeeSElza Mathew /*
353a4fd5eeeSElza Mathew  * Display zero values by default for xstats
354a4fd5eeeSElza Mathew  */
355a4fd5eeeSElza Mathew uint8_t xstats_hide_zero;
356a4fd5eeeSElza Mathew 
357c9cafcc8SShahaf Shuler unsigned int num_sockets = 0;
358c9cafcc8SShahaf Shuler unsigned int socket_ids[RTE_MAX_NUMA_NODES];
3597acf894dSStephen Hurd 
360e25e6c70SRemy Horton #ifdef RTE_LIBRTE_BITRATE
3617e4441c8SRemy Horton /* Bitrate statistics */
3627e4441c8SRemy Horton struct rte_stats_bitrates *bitrate_data;
363e25e6c70SRemy Horton lcoreid_t bitrate_lcore_id;
364e25e6c70SRemy Horton uint8_t bitrate_enabled;
365e25e6c70SRemy Horton #endif
3667e4441c8SRemy Horton 
367b40f8d78SJiayu Hu struct gro_status gro_ports[RTE_MAX_ETHPORTS];
368b7091f1dSJiayu Hu uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES;
369b40f8d78SJiayu Hu 
370ed30d9b6SIntel /* Forward function declarations */
37128caa76aSZhiyong Yang static void map_port_queue_stats_mapping_registers(portid_t pi,
37228caa76aSZhiyong Yang 						   struct rte_port *port);
373edab33b1STetsuya Mukawa static void check_all_ports_link_status(uint32_t port_mask);
374f8244c63SZhiyong Yang static int eth_event_callback(portid_t port_id,
37576ad4a2dSGaetan Rivet 			      enum rte_eth_event_type type,
376d6af1a13SBernard Iremonger 			      void *param, void *ret_param);
377ce8d5614SIntel 
378ce8d5614SIntel /*
379ce8d5614SIntel  * Check if all the ports are started.
380ce8d5614SIntel  * If yes, return positive value. If not, return zero.
381ce8d5614SIntel  */
382ce8d5614SIntel static int all_ports_started(void);
383ed30d9b6SIntel 
38452f38a20SJiayu Hu struct gso_status gso_ports[RTE_MAX_ETHPORTS];
38552f38a20SJiayu Hu uint16_t gso_max_segment_size = ETHER_MAX_LEN - ETHER_CRC_LEN;
38652f38a20SJiayu Hu 
387af75078fSIntel /*
38898a7ea33SJerin Jacob  * Helper function to check if socket is already discovered.
389c9cafcc8SShahaf Shuler  * If yes, return positive value. If not, return zero.
390c9cafcc8SShahaf Shuler  */
391c9cafcc8SShahaf Shuler int
392c9cafcc8SShahaf Shuler new_socket_id(unsigned int socket_id)
393c9cafcc8SShahaf Shuler {
394c9cafcc8SShahaf Shuler 	unsigned int i;
395c9cafcc8SShahaf Shuler 
396c9cafcc8SShahaf Shuler 	for (i = 0; i < num_sockets; i++) {
397c9cafcc8SShahaf Shuler 		if (socket_ids[i] == socket_id)
398c9cafcc8SShahaf Shuler 			return 0;
399c9cafcc8SShahaf Shuler 	}
400c9cafcc8SShahaf Shuler 	return 1;
401c9cafcc8SShahaf Shuler }
402c9cafcc8SShahaf Shuler 
403c9cafcc8SShahaf Shuler /*
404af75078fSIntel  * Setup default configuration.
405af75078fSIntel  */
406af75078fSIntel static void
407af75078fSIntel set_default_fwd_lcores_config(void)
408af75078fSIntel {
409af75078fSIntel 	unsigned int i;
410af75078fSIntel 	unsigned int nb_lc;
4117acf894dSStephen Hurd 	unsigned int sock_num;
412af75078fSIntel 
413af75078fSIntel 	nb_lc = 0;
414af75078fSIntel 	for (i = 0; i < RTE_MAX_LCORE; i++) {
415c9cafcc8SShahaf Shuler 		sock_num = rte_lcore_to_socket_id(i);
416c9cafcc8SShahaf Shuler 		if (new_socket_id(sock_num)) {
417c9cafcc8SShahaf Shuler 			if (num_sockets >= RTE_MAX_NUMA_NODES) {
418c9cafcc8SShahaf Shuler 				rte_exit(EXIT_FAILURE,
419c9cafcc8SShahaf Shuler 					 "Total sockets greater than %u\n",
420c9cafcc8SShahaf Shuler 					 RTE_MAX_NUMA_NODES);
421c9cafcc8SShahaf Shuler 			}
422c9cafcc8SShahaf Shuler 			socket_ids[num_sockets++] = sock_num;
4237acf894dSStephen Hurd 		}
424f54fe5eeSStephen Hurd 		if (!rte_lcore_is_enabled(i))
425f54fe5eeSStephen Hurd 			continue;
426f54fe5eeSStephen Hurd 		if (i == rte_get_master_lcore())
427f54fe5eeSStephen Hurd 			continue;
428f54fe5eeSStephen Hurd 		fwd_lcores_cpuids[nb_lc++] = i;
429af75078fSIntel 	}
430af75078fSIntel 	nb_lcores = (lcoreid_t) nb_lc;
431af75078fSIntel 	nb_cfg_lcores = nb_lcores;
432af75078fSIntel 	nb_fwd_lcores = 1;
433af75078fSIntel }
434af75078fSIntel 
435af75078fSIntel static void
436af75078fSIntel set_def_peer_eth_addrs(void)
437af75078fSIntel {
438af75078fSIntel 	portid_t i;
439af75078fSIntel 
440af75078fSIntel 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
441af75078fSIntel 		peer_eth_addrs[i].addr_bytes[0] = ETHER_LOCAL_ADMIN_ADDR;
442af75078fSIntel 		peer_eth_addrs[i].addr_bytes[5] = i;
443af75078fSIntel 	}
444af75078fSIntel }
445af75078fSIntel 
446af75078fSIntel static void
447af75078fSIntel set_default_fwd_ports_config(void)
448af75078fSIntel {
449af75078fSIntel 	portid_t pt_id;
45065a7360cSMatan Azrad 	int i = 0;
451af75078fSIntel 
45265a7360cSMatan Azrad 	RTE_ETH_FOREACH_DEV(pt_id)
45365a7360cSMatan Azrad 		fwd_ports_ids[i++] = pt_id;
454af75078fSIntel 
455af75078fSIntel 	nb_cfg_ports = nb_ports;
456af75078fSIntel 	nb_fwd_ports = nb_ports;
457af75078fSIntel }
458af75078fSIntel 
459af75078fSIntel void
460af75078fSIntel set_def_fwd_config(void)
461af75078fSIntel {
462af75078fSIntel 	set_default_fwd_lcores_config();
463af75078fSIntel 	set_def_peer_eth_addrs();
464af75078fSIntel 	set_default_fwd_ports_config();
465af75078fSIntel }
466af75078fSIntel 
467af75078fSIntel /*
468af75078fSIntel  * Configuration initialisation done once at init time.
469af75078fSIntel  */
470af75078fSIntel static void
471af75078fSIntel mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
472af75078fSIntel 		 unsigned int socket_id)
473af75078fSIntel {
474af75078fSIntel 	char pool_name[RTE_MEMPOOL_NAMESIZE];
475bece7b6cSChristian Ehrhardt 	struct rte_mempool *rte_mp = NULL;
476af75078fSIntel 	uint32_t mb_size;
477af75078fSIntel 
478dfb03bbeSOlivier Matz 	mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size;
479af75078fSIntel 	mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name));
480148f963fSBruce Richardson 
481285fd101SOlivier Matz 	TESTPMD_LOG(INFO,
482d1eb542eSOlivier Matz 		"create a new mbuf pool <%s>: n=%u, size=%u, socket=%u\n",
483d1eb542eSOlivier Matz 		pool_name, nb_mbuf, mbuf_seg_size, socket_id);
484d1eb542eSOlivier Matz 
485b19a0c75SOlivier Matz 	if (mp_anon != 0) {
486b19a0c75SOlivier Matz 		rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf,
487bece7b6cSChristian Ehrhardt 			mb_size, (unsigned) mb_mempool_cache,
488148f963fSBruce Richardson 			sizeof(struct rte_pktmbuf_pool_private),
489148f963fSBruce Richardson 			socket_id, 0);
49024427bb9SOlivier Matz 		if (rte_mp == NULL)
49124427bb9SOlivier Matz 			goto err;
492b19a0c75SOlivier Matz 
493b19a0c75SOlivier Matz 		if (rte_mempool_populate_anon(rte_mp) == 0) {
494b19a0c75SOlivier Matz 			rte_mempool_free(rte_mp);
495b19a0c75SOlivier Matz 			rte_mp = NULL;
49624427bb9SOlivier Matz 			goto err;
497b19a0c75SOlivier Matz 		}
498b19a0c75SOlivier Matz 		rte_pktmbuf_pool_init(rte_mp, NULL);
499b19a0c75SOlivier Matz 		rte_mempool_obj_iter(rte_mp, rte_pktmbuf_init, NULL);
500b19a0c75SOlivier Matz 	} else {
501ea0c20eaSOlivier Matz 		/* wrapper to rte_mempool_create() */
502ea0c20eaSOlivier Matz 		rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
503ea0c20eaSOlivier Matz 			mb_mempool_cache, 0, mbuf_seg_size, socket_id);
504bece7b6cSChristian Ehrhardt 	}
505148f963fSBruce Richardson 
50624427bb9SOlivier Matz err:
507af75078fSIntel 	if (rte_mp == NULL) {
508d1eb542eSOlivier Matz 		rte_exit(EXIT_FAILURE,
509d1eb542eSOlivier Matz 			"Creation of mbuf pool for socket %u failed: %s\n",
510d1eb542eSOlivier Matz 			socket_id, rte_strerror(rte_errno));
511148f963fSBruce Richardson 	} else if (verbose_level > 0) {
512591a9d79SStephen Hemminger 		rte_mempool_dump(stdout, rte_mp);
513af75078fSIntel 	}
514af75078fSIntel }
515af75078fSIntel 
51620a0286fSLiu Xiaofeng /*
51720a0286fSLiu Xiaofeng  * Check given socket id is valid or not with NUMA mode,
51820a0286fSLiu Xiaofeng  * if valid, return 0, else return -1
51920a0286fSLiu Xiaofeng  */
52020a0286fSLiu Xiaofeng static int
52120a0286fSLiu Xiaofeng check_socket_id(const unsigned int socket_id)
52220a0286fSLiu Xiaofeng {
52320a0286fSLiu Xiaofeng 	static int warning_once = 0;
52420a0286fSLiu Xiaofeng 
525c9cafcc8SShahaf Shuler 	if (new_socket_id(socket_id)) {
52620a0286fSLiu Xiaofeng 		if (!warning_once && numa_support)
52720a0286fSLiu Xiaofeng 			printf("Warning: NUMA should be configured manually by"
52820a0286fSLiu Xiaofeng 			       " using --port-numa-config and"
52920a0286fSLiu Xiaofeng 			       " --ring-numa-config parameters along with"
53020a0286fSLiu Xiaofeng 			       " --numa.\n");
53120a0286fSLiu Xiaofeng 		warning_once = 1;
53220a0286fSLiu Xiaofeng 		return -1;
53320a0286fSLiu Xiaofeng 	}
53420a0286fSLiu Xiaofeng 	return 0;
53520a0286fSLiu Xiaofeng }
53620a0286fSLiu Xiaofeng 
5373f7311baSWei Dai /*
5383f7311baSWei Dai  * Get the allowed maximum number of RX queues.
5393f7311baSWei Dai  * *pid return the port id which has minimal value of
5403f7311baSWei Dai  * max_rx_queues in all ports.
5413f7311baSWei Dai  */
5423f7311baSWei Dai queueid_t
5433f7311baSWei Dai get_allowed_max_nb_rxq(portid_t *pid)
5443f7311baSWei Dai {
5453f7311baSWei Dai 	queueid_t allowed_max_rxq = MAX_QUEUE_ID;
5463f7311baSWei Dai 	portid_t pi;
5473f7311baSWei Dai 	struct rte_eth_dev_info dev_info;
5483f7311baSWei Dai 
5493f7311baSWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
5503f7311baSWei Dai 		rte_eth_dev_info_get(pi, &dev_info);
5513f7311baSWei Dai 		if (dev_info.max_rx_queues < allowed_max_rxq) {
5523f7311baSWei Dai 			allowed_max_rxq = dev_info.max_rx_queues;
5533f7311baSWei Dai 			*pid = pi;
5543f7311baSWei Dai 		}
5553f7311baSWei Dai 	}
5563f7311baSWei Dai 	return allowed_max_rxq;
5573f7311baSWei Dai }
5583f7311baSWei Dai 
5593f7311baSWei Dai /*
5603f7311baSWei Dai  * Check input rxq is valid or not.
5613f7311baSWei Dai  * If input rxq is not greater than any of maximum number
5623f7311baSWei Dai  * of RX queues of all ports, it is valid.
5633f7311baSWei Dai  * if valid, return 0, else return -1
5643f7311baSWei Dai  */
5653f7311baSWei Dai int
5663f7311baSWei Dai check_nb_rxq(queueid_t rxq)
5673f7311baSWei Dai {
5683f7311baSWei Dai 	queueid_t allowed_max_rxq;
5693f7311baSWei Dai 	portid_t pid = 0;
5703f7311baSWei Dai 
5713f7311baSWei Dai 	allowed_max_rxq = get_allowed_max_nb_rxq(&pid);
5723f7311baSWei Dai 	if (rxq > allowed_max_rxq) {
5733f7311baSWei Dai 		printf("Fail: input rxq (%u) can't be greater "
5743f7311baSWei Dai 		       "than max_rx_queues (%u) of port %u\n",
5753f7311baSWei Dai 		       rxq,
5763f7311baSWei Dai 		       allowed_max_rxq,
5773f7311baSWei Dai 		       pid);
5783f7311baSWei Dai 		return -1;
5793f7311baSWei Dai 	}
5803f7311baSWei Dai 	return 0;
5813f7311baSWei Dai }
5823f7311baSWei Dai 
583*36db4f6cSWei Dai /*
584*36db4f6cSWei Dai  * Get the allowed maximum number of TX queues.
585*36db4f6cSWei Dai  * *pid return the port id which has minimal value of
586*36db4f6cSWei Dai  * max_tx_queues in all ports.
587*36db4f6cSWei Dai  */
588*36db4f6cSWei Dai queueid_t
589*36db4f6cSWei Dai get_allowed_max_nb_txq(portid_t *pid)
590*36db4f6cSWei Dai {
591*36db4f6cSWei Dai 	queueid_t allowed_max_txq = MAX_QUEUE_ID;
592*36db4f6cSWei Dai 	portid_t pi;
593*36db4f6cSWei Dai 	struct rte_eth_dev_info dev_info;
594*36db4f6cSWei Dai 
595*36db4f6cSWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
596*36db4f6cSWei Dai 		rte_eth_dev_info_get(pi, &dev_info);
597*36db4f6cSWei Dai 		if (dev_info.max_tx_queues < allowed_max_txq) {
598*36db4f6cSWei Dai 			allowed_max_txq = dev_info.max_tx_queues;
599*36db4f6cSWei Dai 			*pid = pi;
600*36db4f6cSWei Dai 		}
601*36db4f6cSWei Dai 	}
602*36db4f6cSWei Dai 	return allowed_max_txq;
603*36db4f6cSWei Dai }
604*36db4f6cSWei Dai 
605*36db4f6cSWei Dai /*
606*36db4f6cSWei Dai  * Check input txq is valid or not.
607*36db4f6cSWei Dai  * If input txq is not greater than any of maximum number
608*36db4f6cSWei Dai  * of TX queues of all ports, it is valid.
609*36db4f6cSWei Dai  * if valid, return 0, else return -1
610*36db4f6cSWei Dai  */
611*36db4f6cSWei Dai int
612*36db4f6cSWei Dai check_nb_txq(queueid_t txq)
613*36db4f6cSWei Dai {
614*36db4f6cSWei Dai 	queueid_t allowed_max_txq;
615*36db4f6cSWei Dai 	portid_t pid = 0;
616*36db4f6cSWei Dai 
617*36db4f6cSWei Dai 	allowed_max_txq = get_allowed_max_nb_txq(&pid);
618*36db4f6cSWei Dai 	if (txq > allowed_max_txq) {
619*36db4f6cSWei Dai 		printf("Fail: input txq (%u) can't be greater "
620*36db4f6cSWei Dai 		       "than max_tx_queues (%u) of port %u\n",
621*36db4f6cSWei Dai 		       txq,
622*36db4f6cSWei Dai 		       allowed_max_txq,
623*36db4f6cSWei Dai 		       pid);
624*36db4f6cSWei Dai 		return -1;
625*36db4f6cSWei Dai 	}
626*36db4f6cSWei Dai 	return 0;
627*36db4f6cSWei Dai }
628*36db4f6cSWei Dai 
629af75078fSIntel static void
630af75078fSIntel init_config(void)
631af75078fSIntel {
632ce8d5614SIntel 	portid_t pid;
633af75078fSIntel 	struct rte_port *port;
634af75078fSIntel 	struct rte_mempool *mbp;
635af75078fSIntel 	unsigned int nb_mbuf_per_pool;
636af75078fSIntel 	lcoreid_t  lc_id;
6377acf894dSStephen Hurd 	uint8_t port_per_socket[RTE_MAX_NUMA_NODES];
638b7091f1dSJiayu Hu 	struct rte_gro_param gro_param;
63952f38a20SJiayu Hu 	uint32_t gso_types;
640af75078fSIntel 
6417acf894dSStephen Hurd 	memset(port_per_socket,0,RTE_MAX_NUMA_NODES);
642487f9a59SYulong Pei 
643487f9a59SYulong Pei 	if (numa_support) {
644487f9a59SYulong Pei 		memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
645487f9a59SYulong Pei 		memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
646487f9a59SYulong Pei 		memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
647487f9a59SYulong Pei 	}
648487f9a59SYulong Pei 
649af75078fSIntel 	/* Configuration of logical cores. */
650af75078fSIntel 	fwd_lcores = rte_zmalloc("testpmd: fwd_lcores",
651af75078fSIntel 				sizeof(struct fwd_lcore *) * nb_lcores,
652fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
653af75078fSIntel 	if (fwd_lcores == NULL) {
654ce8d5614SIntel 		rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) "
655ce8d5614SIntel 							"failed\n", nb_lcores);
656af75078fSIntel 	}
657af75078fSIntel 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
658af75078fSIntel 		fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore",
659af75078fSIntel 					       sizeof(struct fwd_lcore),
660fdf20fa7SSergio Gonzalez Monroy 					       RTE_CACHE_LINE_SIZE);
661af75078fSIntel 		if (fwd_lcores[lc_id] == NULL) {
662ce8d5614SIntel 			rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) "
663ce8d5614SIntel 								"failed\n");
664af75078fSIntel 		}
665af75078fSIntel 		fwd_lcores[lc_id]->cpuid_idx = lc_id;
666af75078fSIntel 	}
667af75078fSIntel 
6687d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
669ce8d5614SIntel 		port = &ports[pid];
670fd8c20aaSShahaf Shuler 		/* Apply default Tx configuration for all ports */
671fd8c20aaSShahaf Shuler 		port->dev_conf.txmode = tx_mode;
672384161e0SShahaf Shuler 		port->dev_conf.rxmode = rx_mode;
673ce8d5614SIntel 		rte_eth_dev_info_get(pid, &port->dev_info);
67407e5f7bdSShahaf Shuler 		if (!(port->dev_info.tx_offload_capa &
67507e5f7bdSShahaf Shuler 		      DEV_TX_OFFLOAD_MBUF_FAST_FREE))
67607e5f7bdSShahaf Shuler 			port->dev_conf.txmode.offloads &=
67707e5f7bdSShahaf Shuler 				~DEV_TX_OFFLOAD_MBUF_FAST_FREE;
678ce8d5614SIntel 
679b6ea6408SIntel 		if (numa_support) {
680b6ea6408SIntel 			if (port_numa[pid] != NUMA_NO_CONFIG)
681b6ea6408SIntel 				port_per_socket[port_numa[pid]]++;
682b6ea6408SIntel 			else {
683b6ea6408SIntel 				uint32_t socket_id = rte_eth_dev_socket_id(pid);
68420a0286fSLiu Xiaofeng 
68520a0286fSLiu Xiaofeng 				/* if socket_id is invalid, set to 0 */
68620a0286fSLiu Xiaofeng 				if (check_socket_id(socket_id) < 0)
68720a0286fSLiu Xiaofeng 					socket_id = 0;
688b6ea6408SIntel 				port_per_socket[socket_id]++;
689b6ea6408SIntel 			}
690b6ea6408SIntel 		}
691b6ea6408SIntel 
692ce8d5614SIntel 		/* set flag to initialize port/queue */
693ce8d5614SIntel 		port->need_reconfig = 1;
694ce8d5614SIntel 		port->need_reconfig_queues = 1;
695ce8d5614SIntel 	}
696ce8d5614SIntel 
6973ab64341SOlivier Matz 	/*
6983ab64341SOlivier Matz 	 * Create pools of mbuf.
6993ab64341SOlivier Matz 	 * If NUMA support is disabled, create a single pool of mbuf in
7003ab64341SOlivier Matz 	 * socket 0 memory by default.
7013ab64341SOlivier Matz 	 * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1.
7023ab64341SOlivier Matz 	 *
7033ab64341SOlivier Matz 	 * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and
7043ab64341SOlivier Matz 	 * nb_txd can be configured at run time.
7053ab64341SOlivier Matz 	 */
7063ab64341SOlivier Matz 	if (param_total_num_mbufs)
7073ab64341SOlivier Matz 		nb_mbuf_per_pool = param_total_num_mbufs;
7083ab64341SOlivier Matz 	else {
7093ab64341SOlivier Matz 		nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX +
7103ab64341SOlivier Matz 			(nb_lcores * mb_mempool_cache) +
7113ab64341SOlivier Matz 			RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
7123ab64341SOlivier Matz 		nb_mbuf_per_pool *= RTE_MAX_ETHPORTS;
7133ab64341SOlivier Matz 	}
7143ab64341SOlivier Matz 
715b6ea6408SIntel 	if (numa_support) {
716b6ea6408SIntel 		uint8_t i;
717ce8d5614SIntel 
718c9cafcc8SShahaf Shuler 		for (i = 0; i < num_sockets; i++)
719c9cafcc8SShahaf Shuler 			mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool,
720c9cafcc8SShahaf Shuler 					 socket_ids[i]);
7213ab64341SOlivier Matz 	} else {
7223ab64341SOlivier Matz 		if (socket_num == UMA_NO_CONFIG)
7233ab64341SOlivier Matz 			mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0);
7243ab64341SOlivier Matz 		else
7253ab64341SOlivier Matz 			mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool,
7263ab64341SOlivier Matz 						 socket_num);
7273ab64341SOlivier Matz 	}
728b6ea6408SIntel 
729b6ea6408SIntel 	init_port_config();
7305886ae07SAdrien Mazarguil 
73152f38a20SJiayu Hu 	gso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
73252f38a20SJiayu Hu 		DEV_TX_OFFLOAD_GRE_TNL_TSO;
7335886ae07SAdrien Mazarguil 	/*
7345886ae07SAdrien Mazarguil 	 * Records which Mbuf pool to use by each logical core, if needed.
7355886ae07SAdrien Mazarguil 	 */
7365886ae07SAdrien Mazarguil 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
7378fd8bebcSAdrien Mazarguil 		mbp = mbuf_pool_find(
7388fd8bebcSAdrien Mazarguil 			rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]));
7398fd8bebcSAdrien Mazarguil 
7405886ae07SAdrien Mazarguil 		if (mbp == NULL)
7415886ae07SAdrien Mazarguil 			mbp = mbuf_pool_find(0);
7425886ae07SAdrien Mazarguil 		fwd_lcores[lc_id]->mbp = mbp;
74352f38a20SJiayu Hu 		/* initialize GSO context */
74452f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.direct_pool = mbp;
74552f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.indirect_pool = mbp;
74652f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.gso_types = gso_types;
74752f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.gso_size = ETHER_MAX_LEN -
74852f38a20SJiayu Hu 			ETHER_CRC_LEN;
74952f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.flag = 0;
7505886ae07SAdrien Mazarguil 	}
7515886ae07SAdrien Mazarguil 
752ce8d5614SIntel 	/* Configuration of packet forwarding streams. */
753ce8d5614SIntel 	if (init_fwd_streams() < 0)
754ce8d5614SIntel 		rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n");
7550c0db76fSBernard Iremonger 
7560c0db76fSBernard Iremonger 	fwd_config_setup();
757b7091f1dSJiayu Hu 
758b7091f1dSJiayu Hu 	/* create a gro context for each lcore */
759b7091f1dSJiayu Hu 	gro_param.gro_types = RTE_GRO_TCP_IPV4;
760b7091f1dSJiayu Hu 	gro_param.max_flow_num = GRO_MAX_FLUSH_CYCLES;
761b7091f1dSJiayu Hu 	gro_param.max_item_per_flow = MAX_PKT_BURST;
762b7091f1dSJiayu Hu 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
763b7091f1dSJiayu Hu 		gro_param.socket_id = rte_lcore_to_socket_id(
764b7091f1dSJiayu Hu 				fwd_lcores_cpuids[lc_id]);
765b7091f1dSJiayu Hu 		fwd_lcores[lc_id]->gro_ctx = rte_gro_ctx_create(&gro_param);
766b7091f1dSJiayu Hu 		if (fwd_lcores[lc_id]->gro_ctx == NULL) {
767b7091f1dSJiayu Hu 			rte_exit(EXIT_FAILURE,
768b7091f1dSJiayu Hu 					"rte_gro_ctx_create() failed\n");
769b7091f1dSJiayu Hu 		}
770b7091f1dSJiayu Hu 	}
771ce8d5614SIntel }
772ce8d5614SIntel 
7732950a769SDeclan Doherty 
7742950a769SDeclan Doherty void
775a21d5a4bSDeclan Doherty reconfig(portid_t new_port_id, unsigned socket_id)
7762950a769SDeclan Doherty {
7772950a769SDeclan Doherty 	struct rte_port *port;
7782950a769SDeclan Doherty 
7792950a769SDeclan Doherty 	/* Reconfiguration of Ethernet ports. */
7802950a769SDeclan Doherty 	port = &ports[new_port_id];
7812950a769SDeclan Doherty 	rte_eth_dev_info_get(new_port_id, &port->dev_info);
7822950a769SDeclan Doherty 
7832950a769SDeclan Doherty 	/* set flag to initialize port/queue */
7842950a769SDeclan Doherty 	port->need_reconfig = 1;
7852950a769SDeclan Doherty 	port->need_reconfig_queues = 1;
786a21d5a4bSDeclan Doherty 	port->socket_id = socket_id;
7872950a769SDeclan Doherty 
7882950a769SDeclan Doherty 	init_port_config();
7892950a769SDeclan Doherty }
7902950a769SDeclan Doherty 
7912950a769SDeclan Doherty 
792ce8d5614SIntel int
793ce8d5614SIntel init_fwd_streams(void)
794ce8d5614SIntel {
795ce8d5614SIntel 	portid_t pid;
796ce8d5614SIntel 	struct rte_port *port;
797ce8d5614SIntel 	streamid_t sm_id, nb_fwd_streams_new;
7985a8fb55cSReshma Pattan 	queueid_t q;
799ce8d5614SIntel 
800ce8d5614SIntel 	/* set socket id according to numa or not */
8017d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
802ce8d5614SIntel 		port = &ports[pid];
803ce8d5614SIntel 		if (nb_rxq > port->dev_info.max_rx_queues) {
804ce8d5614SIntel 			printf("Fail: nb_rxq(%d) is greater than "
805ce8d5614SIntel 				"max_rx_queues(%d)\n", nb_rxq,
806ce8d5614SIntel 				port->dev_info.max_rx_queues);
807ce8d5614SIntel 			return -1;
808ce8d5614SIntel 		}
809ce8d5614SIntel 		if (nb_txq > port->dev_info.max_tx_queues) {
810ce8d5614SIntel 			printf("Fail: nb_txq(%d) is greater than "
811ce8d5614SIntel 				"max_tx_queues(%d)\n", nb_txq,
812ce8d5614SIntel 				port->dev_info.max_tx_queues);
813ce8d5614SIntel 			return -1;
814ce8d5614SIntel 		}
81520a0286fSLiu Xiaofeng 		if (numa_support) {
81620a0286fSLiu Xiaofeng 			if (port_numa[pid] != NUMA_NO_CONFIG)
81720a0286fSLiu Xiaofeng 				port->socket_id = port_numa[pid];
81820a0286fSLiu Xiaofeng 			else {
819b6ea6408SIntel 				port->socket_id = rte_eth_dev_socket_id(pid);
82020a0286fSLiu Xiaofeng 
82120a0286fSLiu Xiaofeng 				/* if socket_id is invalid, set to 0 */
82220a0286fSLiu Xiaofeng 				if (check_socket_id(port->socket_id) < 0)
82320a0286fSLiu Xiaofeng 					port->socket_id = 0;
82420a0286fSLiu Xiaofeng 			}
82520a0286fSLiu Xiaofeng 		}
826b6ea6408SIntel 		else {
827b6ea6408SIntel 			if (socket_num == UMA_NO_CONFIG)
828af75078fSIntel 				port->socket_id = 0;
829b6ea6408SIntel 			else
830b6ea6408SIntel 				port->socket_id = socket_num;
831b6ea6408SIntel 		}
832af75078fSIntel 	}
833af75078fSIntel 
8345a8fb55cSReshma Pattan 	q = RTE_MAX(nb_rxq, nb_txq);
8355a8fb55cSReshma Pattan 	if (q == 0) {
8365a8fb55cSReshma Pattan 		printf("Fail: Cannot allocate fwd streams as number of queues is 0\n");
8375a8fb55cSReshma Pattan 		return -1;
8385a8fb55cSReshma Pattan 	}
8395a8fb55cSReshma Pattan 	nb_fwd_streams_new = (streamid_t)(nb_ports * q);
840ce8d5614SIntel 	if (nb_fwd_streams_new == nb_fwd_streams)
841ce8d5614SIntel 		return 0;
842ce8d5614SIntel 	/* clear the old */
843ce8d5614SIntel 	if (fwd_streams != NULL) {
844ce8d5614SIntel 		for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
845ce8d5614SIntel 			if (fwd_streams[sm_id] == NULL)
846ce8d5614SIntel 				continue;
847ce8d5614SIntel 			rte_free(fwd_streams[sm_id]);
848ce8d5614SIntel 			fwd_streams[sm_id] = NULL;
849af75078fSIntel 		}
850ce8d5614SIntel 		rte_free(fwd_streams);
851ce8d5614SIntel 		fwd_streams = NULL;
852ce8d5614SIntel 	}
853ce8d5614SIntel 
854ce8d5614SIntel 	/* init new */
855ce8d5614SIntel 	nb_fwd_streams = nb_fwd_streams_new;
856ce8d5614SIntel 	fwd_streams = rte_zmalloc("testpmd: fwd_streams",
857fdf20fa7SSergio Gonzalez Monroy 		sizeof(struct fwd_stream *) * nb_fwd_streams, RTE_CACHE_LINE_SIZE);
858ce8d5614SIntel 	if (fwd_streams == NULL)
859ce8d5614SIntel 		rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) "
860ce8d5614SIntel 						"failed\n", nb_fwd_streams);
861ce8d5614SIntel 
862af75078fSIntel 	for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
863af75078fSIntel 		fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream",
864fdf20fa7SSergio Gonzalez Monroy 				sizeof(struct fwd_stream), RTE_CACHE_LINE_SIZE);
865ce8d5614SIntel 		if (fwd_streams[sm_id] == NULL)
866ce8d5614SIntel 			rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)"
867ce8d5614SIntel 								" failed\n");
868af75078fSIntel 	}
869ce8d5614SIntel 
870ce8d5614SIntel 	return 0;
871af75078fSIntel }
872af75078fSIntel 
873af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
874af75078fSIntel static void
875af75078fSIntel pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
876af75078fSIntel {
877af75078fSIntel 	unsigned int total_burst;
878af75078fSIntel 	unsigned int nb_burst;
879af75078fSIntel 	unsigned int burst_stats[3];
880af75078fSIntel 	uint16_t pktnb_stats[3];
881af75078fSIntel 	uint16_t nb_pkt;
882af75078fSIntel 	int burst_percent[3];
883af75078fSIntel 
884af75078fSIntel 	/*
885af75078fSIntel 	 * First compute the total number of packet bursts and the
886af75078fSIntel 	 * two highest numbers of bursts of the same number of packets.
887af75078fSIntel 	 */
888af75078fSIntel 	total_burst = 0;
889af75078fSIntel 	burst_stats[0] = burst_stats[1] = burst_stats[2] = 0;
890af75078fSIntel 	pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0;
891af75078fSIntel 	for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) {
892af75078fSIntel 		nb_burst = pbs->pkt_burst_spread[nb_pkt];
893af75078fSIntel 		if (nb_burst == 0)
894af75078fSIntel 			continue;
895af75078fSIntel 		total_burst += nb_burst;
896af75078fSIntel 		if (nb_burst > burst_stats[0]) {
897af75078fSIntel 			burst_stats[1] = burst_stats[0];
898af75078fSIntel 			pktnb_stats[1] = pktnb_stats[0];
899af75078fSIntel 			burst_stats[0] = nb_burst;
900af75078fSIntel 			pktnb_stats[0] = nb_pkt;
901af75078fSIntel 		}
902af75078fSIntel 	}
903af75078fSIntel 	if (total_burst == 0)
904af75078fSIntel 		return;
905af75078fSIntel 	burst_percent[0] = (burst_stats[0] * 100) / total_burst;
906af75078fSIntel 	printf("  %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst,
907af75078fSIntel 	       burst_percent[0], (int) pktnb_stats[0]);
908af75078fSIntel 	if (burst_stats[0] == total_burst) {
909af75078fSIntel 		printf("]\n");
910af75078fSIntel 		return;
911af75078fSIntel 	}
912af75078fSIntel 	if (burst_stats[0] + burst_stats[1] == total_burst) {
913af75078fSIntel 		printf(" + %d%% of %d pkts]\n",
914af75078fSIntel 		       100 - burst_percent[0], pktnb_stats[1]);
915af75078fSIntel 		return;
916af75078fSIntel 	}
917af75078fSIntel 	burst_percent[1] = (burst_stats[1] * 100) / total_burst;
918af75078fSIntel 	burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]);
919af75078fSIntel 	if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) {
920af75078fSIntel 		printf(" + %d%% of others]\n", 100 - burst_percent[0]);
921af75078fSIntel 		return;
922af75078fSIntel 	}
923af75078fSIntel 	printf(" + %d%% of %d pkts + %d%% of others]\n",
924af75078fSIntel 	       burst_percent[1], (int) pktnb_stats[1], burst_percent[2]);
925af75078fSIntel }
926af75078fSIntel #endif /* RTE_TEST_PMD_RECORD_BURST_STATS */
927af75078fSIntel 
928af75078fSIntel static void
929af75078fSIntel fwd_port_stats_display(portid_t port_id, struct rte_eth_stats *stats)
930af75078fSIntel {
931af75078fSIntel 	struct rte_port *port;
932013af9b6SIntel 	uint8_t i;
933af75078fSIntel 
934af75078fSIntel 	static const char *fwd_stats_border = "----------------------";
935af75078fSIntel 
936af75078fSIntel 	port = &ports[port_id];
937af75078fSIntel 	printf("\n  %s Forward statistics for port %-2d %s\n",
938af75078fSIntel 	       fwd_stats_border, port_id, fwd_stats_border);
939013af9b6SIntel 
940013af9b6SIntel 	if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
941af75078fSIntel 		printf("  RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
942af75078fSIntel 		       "%-"PRIu64"\n",
94370bdb186SIvan Boule 		       stats->ipackets, stats->imissed,
94470bdb186SIvan Boule 		       (uint64_t) (stats->ipackets + stats->imissed));
945af75078fSIntel 
946af75078fSIntel 		if (cur_fwd_eng == &csum_fwd_engine)
947af75078fSIntel 			printf("  Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n",
948af75078fSIntel 			       port->rx_bad_ip_csum, port->rx_bad_l4_csum);
94986057c99SIgor Ryzhov 		if ((stats->ierrors + stats->rx_nombuf) > 0) {
950f72a0fa6SStephen Hemminger 			printf("  RX-error: %-"PRIu64"\n",  stats->ierrors);
95170bdb186SIvan Boule 			printf("  RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf);
95270bdb186SIvan Boule 		}
953af75078fSIntel 
954af75078fSIntel 		printf("  TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
955af75078fSIntel 		       "%-"PRIu64"\n",
956af75078fSIntel 		       stats->opackets, port->tx_dropped,
957af75078fSIntel 		       (uint64_t) (stats->opackets + port->tx_dropped));
958013af9b6SIntel 	}
959013af9b6SIntel 	else {
960013af9b6SIntel 		printf("  RX-packets:             %14"PRIu64"    RX-dropped:%14"PRIu64"    RX-total:"
961013af9b6SIntel 		       "%14"PRIu64"\n",
96270bdb186SIvan Boule 		       stats->ipackets, stats->imissed,
96370bdb186SIvan Boule 		       (uint64_t) (stats->ipackets + stats->imissed));
964013af9b6SIntel 
965013af9b6SIntel 		if (cur_fwd_eng == &csum_fwd_engine)
966013af9b6SIntel 			printf("  Bad-ipcsum:%14"PRIu64"    Bad-l4csum:%14"PRIu64"\n",
967013af9b6SIntel 			       port->rx_bad_ip_csum, port->rx_bad_l4_csum);
96886057c99SIgor Ryzhov 		if ((stats->ierrors + stats->rx_nombuf) > 0) {
969f72a0fa6SStephen Hemminger 			printf("  RX-error:%"PRIu64"\n", stats->ierrors);
97070bdb186SIvan Boule 			printf("  RX-nombufs:             %14"PRIu64"\n",
97170bdb186SIvan Boule 			       stats->rx_nombuf);
97270bdb186SIvan Boule 		}
973013af9b6SIntel 
974013af9b6SIntel 		printf("  TX-packets:             %14"PRIu64"    TX-dropped:%14"PRIu64"    TX-total:"
975013af9b6SIntel 		       "%14"PRIu64"\n",
976013af9b6SIntel 		       stats->opackets, port->tx_dropped,
977013af9b6SIntel 		       (uint64_t) (stats->opackets + port->tx_dropped));
978013af9b6SIntel 	}
979e659b6b4SIvan Boule 
980af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
981af75078fSIntel 	if (port->rx_stream)
982013af9b6SIntel 		pkt_burst_stats_display("RX",
983013af9b6SIntel 			&port->rx_stream->rx_burst_stats);
984af75078fSIntel 	if (port->tx_stream)
985013af9b6SIntel 		pkt_burst_stats_display("TX",
986013af9b6SIntel 			&port->tx_stream->tx_burst_stats);
987af75078fSIntel #endif
988af75078fSIntel 
989013af9b6SIntel 	if (port->rx_queue_stats_mapping_enabled) {
990013af9b6SIntel 		printf("\n");
991013af9b6SIntel 		for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
992013af9b6SIntel 			printf("  Stats reg %2d RX-packets:%14"PRIu64
993013af9b6SIntel 			       "     RX-errors:%14"PRIu64
994013af9b6SIntel 			       "    RX-bytes:%14"PRIu64"\n",
995013af9b6SIntel 			       i, stats->q_ipackets[i], stats->q_errors[i], stats->q_ibytes[i]);
996013af9b6SIntel 		}
997013af9b6SIntel 		printf("\n");
998013af9b6SIntel 	}
999013af9b6SIntel 	if (port->tx_queue_stats_mapping_enabled) {
1000013af9b6SIntel 		for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
1001013af9b6SIntel 			printf("  Stats reg %2d TX-packets:%14"PRIu64
1002013af9b6SIntel 			       "                                 TX-bytes:%14"PRIu64"\n",
1003013af9b6SIntel 			       i, stats->q_opackets[i], stats->q_obytes[i]);
1004013af9b6SIntel 		}
1005013af9b6SIntel 	}
1006013af9b6SIntel 
1007af75078fSIntel 	printf("  %s--------------------------------%s\n",
1008af75078fSIntel 	       fwd_stats_border, fwd_stats_border);
1009af75078fSIntel }
1010af75078fSIntel 
1011af75078fSIntel static void
1012af75078fSIntel fwd_stream_stats_display(streamid_t stream_id)
1013af75078fSIntel {
1014af75078fSIntel 	struct fwd_stream *fs;
1015af75078fSIntel 	static const char *fwd_top_stats_border = "-------";
1016af75078fSIntel 
1017af75078fSIntel 	fs = fwd_streams[stream_id];
1018af75078fSIntel 	if ((fs->rx_packets == 0) && (fs->tx_packets == 0) &&
1019af75078fSIntel 	    (fs->fwd_dropped == 0))
1020af75078fSIntel 		return;
1021af75078fSIntel 	printf("\n  %s Forward Stats for RX Port=%2d/Queue=%2d -> "
1022af75078fSIntel 	       "TX Port=%2d/Queue=%2d %s\n",
1023af75078fSIntel 	       fwd_top_stats_border, fs->rx_port, fs->rx_queue,
1024af75078fSIntel 	       fs->tx_port, fs->tx_queue, fwd_top_stats_border);
1025af75078fSIntel 	printf("  RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u",
1026af75078fSIntel 	       fs->rx_packets, fs->tx_packets, fs->fwd_dropped);
1027af75078fSIntel 
1028af75078fSIntel 	/* if checksum mode */
1029af75078fSIntel 	if (cur_fwd_eng == &csum_fwd_engine) {
1030013af9b6SIntel 	       printf("  RX- bad IP checksum: %-14u  Rx- bad L4 checksum: "
1031013af9b6SIntel 			"%-14u\n", fs->rx_bad_ip_csum, fs->rx_bad_l4_csum);
1032af75078fSIntel 	}
1033af75078fSIntel 
1034af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
1035af75078fSIntel 	pkt_burst_stats_display("RX", &fs->rx_burst_stats);
1036af75078fSIntel 	pkt_burst_stats_display("TX", &fs->tx_burst_stats);
1037af75078fSIntel #endif
1038af75078fSIntel }
1039af75078fSIntel 
1040af75078fSIntel static void
10417741e4cfSIntel flush_fwd_rx_queues(void)
1042af75078fSIntel {
1043af75078fSIntel 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1044af75078fSIntel 	portid_t  rxp;
10457741e4cfSIntel 	portid_t port_id;
1046af75078fSIntel 	queueid_t rxq;
1047af75078fSIntel 	uint16_t  nb_rx;
1048af75078fSIntel 	uint16_t  i;
1049af75078fSIntel 	uint8_t   j;
1050f487715fSReshma Pattan 	uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
1051594302c7SJames Poole 	uint64_t timer_period;
1052f487715fSReshma Pattan 
1053f487715fSReshma Pattan 	/* convert to number of cycles */
1054594302c7SJames Poole 	timer_period = rte_get_timer_hz(); /* 1 second timeout */
1055af75078fSIntel 
1056af75078fSIntel 	for (j = 0; j < 2; j++) {
10577741e4cfSIntel 		for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) {
1058af75078fSIntel 			for (rxq = 0; rxq < nb_rxq; rxq++) {
10597741e4cfSIntel 				port_id = fwd_ports_ids[rxp];
1060f487715fSReshma Pattan 				/**
1061f487715fSReshma Pattan 				* testpmd can stuck in the below do while loop
1062f487715fSReshma Pattan 				* if rte_eth_rx_burst() always returns nonzero
1063f487715fSReshma Pattan 				* packets. So timer is added to exit this loop
1064f487715fSReshma Pattan 				* after 1sec timer expiry.
1065f487715fSReshma Pattan 				*/
1066f487715fSReshma Pattan 				prev_tsc = rte_rdtsc();
1067af75078fSIntel 				do {
10687741e4cfSIntel 					nb_rx = rte_eth_rx_burst(port_id, rxq,
1069013af9b6SIntel 						pkts_burst, MAX_PKT_BURST);
1070af75078fSIntel 					for (i = 0; i < nb_rx; i++)
1071af75078fSIntel 						rte_pktmbuf_free(pkts_burst[i]);
1072f487715fSReshma Pattan 
1073f487715fSReshma Pattan 					cur_tsc = rte_rdtsc();
1074f487715fSReshma Pattan 					diff_tsc = cur_tsc - prev_tsc;
1075f487715fSReshma Pattan 					timer_tsc += diff_tsc;
1076f487715fSReshma Pattan 				} while ((nb_rx > 0) &&
1077f487715fSReshma Pattan 					(timer_tsc < timer_period));
1078f487715fSReshma Pattan 				timer_tsc = 0;
1079af75078fSIntel 			}
1080af75078fSIntel 		}
1081af75078fSIntel 		rte_delay_ms(10); /* wait 10 milli-seconds before retrying */
1082af75078fSIntel 	}
1083af75078fSIntel }
1084af75078fSIntel 
1085af75078fSIntel static void
1086af75078fSIntel run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
1087af75078fSIntel {
1088af75078fSIntel 	struct fwd_stream **fsm;
1089af75078fSIntel 	streamid_t nb_fs;
1090af75078fSIntel 	streamid_t sm_id;
10917e4441c8SRemy Horton #ifdef RTE_LIBRTE_BITRATE
10927e4441c8SRemy Horton 	uint64_t tics_per_1sec;
10937e4441c8SRemy Horton 	uint64_t tics_datum;
10947e4441c8SRemy Horton 	uint64_t tics_current;
10957e4441c8SRemy Horton 	uint8_t idx_port, cnt_ports;
1096af75078fSIntel 
10977e4441c8SRemy Horton 	cnt_ports = rte_eth_dev_count();
10987e4441c8SRemy Horton 	tics_datum = rte_rdtsc();
10997e4441c8SRemy Horton 	tics_per_1sec = rte_get_timer_hz();
11007e4441c8SRemy Horton #endif
1101af75078fSIntel 	fsm = &fwd_streams[fc->stream_idx];
1102af75078fSIntel 	nb_fs = fc->stream_nb;
1103af75078fSIntel 	do {
1104af75078fSIntel 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
1105af75078fSIntel 			(*pkt_fwd)(fsm[sm_id]);
11067e4441c8SRemy Horton #ifdef RTE_LIBRTE_BITRATE
1107e25e6c70SRemy Horton 		if (bitrate_enabled != 0 &&
1108e25e6c70SRemy Horton 				bitrate_lcore_id == rte_lcore_id()) {
11097e4441c8SRemy Horton 			tics_current = rte_rdtsc();
11107e4441c8SRemy Horton 			if (tics_current - tics_datum >= tics_per_1sec) {
11117e4441c8SRemy Horton 				/* Periodic bitrate calculation */
1112e25e6c70SRemy Horton 				for (idx_port = 0;
1113e25e6c70SRemy Horton 						idx_port < cnt_ports;
1114e25e6c70SRemy Horton 						idx_port++)
1115e25e6c70SRemy Horton 					rte_stats_bitrate_calc(bitrate_data,
1116e25e6c70SRemy Horton 						idx_port);
11177e4441c8SRemy Horton 				tics_datum = tics_current;
11187e4441c8SRemy Horton 			}
1119e25e6c70SRemy Horton 		}
11207e4441c8SRemy Horton #endif
112162d3216dSReshma Pattan #ifdef RTE_LIBRTE_LATENCY_STATS
112265eb1e54SPablo de Lara 		if (latencystats_enabled != 0 &&
112365eb1e54SPablo de Lara 				latencystats_lcore_id == rte_lcore_id())
112462d3216dSReshma Pattan 			rte_latencystats_update();
112562d3216dSReshma Pattan #endif
112662d3216dSReshma Pattan 
1127af75078fSIntel 	} while (! fc->stopped);
1128af75078fSIntel }
1129af75078fSIntel 
1130af75078fSIntel static int
1131af75078fSIntel start_pkt_forward_on_core(void *fwd_arg)
1132af75078fSIntel {
1133af75078fSIntel 	run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg,
1134af75078fSIntel 			     cur_fwd_config.fwd_eng->packet_fwd);
1135af75078fSIntel 	return 0;
1136af75078fSIntel }
1137af75078fSIntel 
1138af75078fSIntel /*
1139af75078fSIntel  * Run the TXONLY packet forwarding engine to send a single burst of packets.
1140af75078fSIntel  * Used to start communication flows in network loopback test configurations.
1141af75078fSIntel  */
1142af75078fSIntel static int
1143af75078fSIntel run_one_txonly_burst_on_core(void *fwd_arg)
1144af75078fSIntel {
1145af75078fSIntel 	struct fwd_lcore *fwd_lc;
1146af75078fSIntel 	struct fwd_lcore tmp_lcore;
1147af75078fSIntel 
1148af75078fSIntel 	fwd_lc = (struct fwd_lcore *) fwd_arg;
1149af75078fSIntel 	tmp_lcore = *fwd_lc;
1150af75078fSIntel 	tmp_lcore.stopped = 1;
1151af75078fSIntel 	run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd);
1152af75078fSIntel 	return 0;
1153af75078fSIntel }
1154af75078fSIntel 
1155af75078fSIntel /*
1156af75078fSIntel  * Launch packet forwarding:
1157af75078fSIntel  *     - Setup per-port forwarding context.
1158af75078fSIntel  *     - launch logical cores with their forwarding configuration.
1159af75078fSIntel  */
1160af75078fSIntel static void
1161af75078fSIntel launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore)
1162af75078fSIntel {
1163af75078fSIntel 	port_fwd_begin_t port_fwd_begin;
1164af75078fSIntel 	unsigned int i;
1165af75078fSIntel 	unsigned int lc_id;
1166af75078fSIntel 	int diag;
1167af75078fSIntel 
1168af75078fSIntel 	port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin;
1169af75078fSIntel 	if (port_fwd_begin != NULL) {
1170af75078fSIntel 		for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
1171af75078fSIntel 			(*port_fwd_begin)(fwd_ports_ids[i]);
1172af75078fSIntel 	}
1173af75078fSIntel 	for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) {
1174af75078fSIntel 		lc_id = fwd_lcores_cpuids[i];
1175af75078fSIntel 		if ((interactive == 0) || (lc_id != rte_lcore_id())) {
1176af75078fSIntel 			fwd_lcores[i]->stopped = 0;
1177af75078fSIntel 			diag = rte_eal_remote_launch(pkt_fwd_on_lcore,
1178af75078fSIntel 						     fwd_lcores[i], lc_id);
1179af75078fSIntel 			if (diag != 0)
1180af75078fSIntel 				printf("launch lcore %u failed - diag=%d\n",
1181af75078fSIntel 				       lc_id, diag);
1182af75078fSIntel 		}
1183af75078fSIntel 	}
1184af75078fSIntel }
1185af75078fSIntel 
1186af75078fSIntel /*
1187af75078fSIntel  * Launch packet forwarding configuration.
1188af75078fSIntel  */
1189af75078fSIntel void
1190af75078fSIntel start_packet_forwarding(int with_tx_first)
1191af75078fSIntel {
1192af75078fSIntel 	port_fwd_begin_t port_fwd_begin;
1193af75078fSIntel 	port_fwd_end_t  port_fwd_end;
1194af75078fSIntel 	struct rte_port *port;
1195af75078fSIntel 	unsigned int i;
1196af75078fSIntel 	portid_t   pt_id;
1197af75078fSIntel 	streamid_t sm_id;
1198af75078fSIntel 
11995a8fb55cSReshma Pattan 	if (strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") == 0 && !nb_rxq)
12005a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE, "rxq are 0, cannot use rxonly fwd mode\n");
12015a8fb55cSReshma Pattan 
12025a8fb55cSReshma Pattan 	if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 && !nb_txq)
12035a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE, "txq are 0, cannot use txonly fwd mode\n");
12045a8fb55cSReshma Pattan 
12055a8fb55cSReshma Pattan 	if ((strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") != 0 &&
12065a8fb55cSReshma Pattan 		strcmp(cur_fwd_eng->fwd_mode_name, "txonly") != 0) &&
12075a8fb55cSReshma Pattan 		(!nb_rxq || !nb_txq))
12085a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE,
12095a8fb55cSReshma Pattan 			"Either rxq or txq are 0, cannot use %s fwd mode\n",
12105a8fb55cSReshma Pattan 			cur_fwd_eng->fwd_mode_name);
12115a8fb55cSReshma Pattan 
1212ce8d5614SIntel 	if (all_ports_started() == 0) {
1213ce8d5614SIntel 		printf("Not all ports were started\n");
1214ce8d5614SIntel 		return;
1215ce8d5614SIntel 	}
1216af75078fSIntel 	if (test_done == 0) {
1217af75078fSIntel 		printf("Packet forwarding already started\n");
1218af75078fSIntel 		return;
1219af75078fSIntel 	}
1220edf87b4aSBernard Iremonger 
1221edf87b4aSBernard Iremonger 	if (init_fwd_streams() < 0) {
1222edf87b4aSBernard Iremonger 		printf("Fail from init_fwd_streams()\n");
1223edf87b4aSBernard Iremonger 		return;
1224edf87b4aSBernard Iremonger 	}
1225edf87b4aSBernard Iremonger 
12267741e4cfSIntel 	if(dcb_test) {
12277741e4cfSIntel 		for (i = 0; i < nb_fwd_ports; i++) {
12287741e4cfSIntel 			pt_id = fwd_ports_ids[i];
12297741e4cfSIntel 			port = &ports[pt_id];
12307741e4cfSIntel 			if (!port->dcb_flag) {
12317741e4cfSIntel 				printf("In DCB mode, all forwarding ports must "
12327741e4cfSIntel                                        "be configured in this mode.\n");
1233013af9b6SIntel 				return;
1234013af9b6SIntel 			}
12357741e4cfSIntel 		}
12367741e4cfSIntel 		if (nb_fwd_lcores == 1) {
12377741e4cfSIntel 			printf("In DCB mode,the nb forwarding cores "
12387741e4cfSIntel                                "should be larger than 1.\n");
12397741e4cfSIntel 			return;
12407741e4cfSIntel 		}
12417741e4cfSIntel 	}
1242af75078fSIntel 	test_done = 0;
12437741e4cfSIntel 
12447741e4cfSIntel 	if(!no_flush_rx)
12457741e4cfSIntel 		flush_fwd_rx_queues();
12467741e4cfSIntel 
1247af75078fSIntel 	fwd_config_setup();
1248933617d8SZhihong Wang 	pkt_fwd_config_display(&cur_fwd_config);
1249af75078fSIntel 	rxtx_config_display();
1250af75078fSIntel 
1251af75078fSIntel 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
1252af75078fSIntel 		pt_id = fwd_ports_ids[i];
1253af75078fSIntel 		port = &ports[pt_id];
1254af75078fSIntel 		rte_eth_stats_get(pt_id, &port->stats);
1255af75078fSIntel 		port->tx_dropped = 0;
1256013af9b6SIntel 
1257013af9b6SIntel 		map_port_queue_stats_mapping_registers(pt_id, port);
1258af75078fSIntel 	}
1259af75078fSIntel 	for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
1260af75078fSIntel 		fwd_streams[sm_id]->rx_packets = 0;
1261af75078fSIntel 		fwd_streams[sm_id]->tx_packets = 0;
1262af75078fSIntel 		fwd_streams[sm_id]->fwd_dropped = 0;
1263af75078fSIntel 		fwd_streams[sm_id]->rx_bad_ip_csum = 0;
1264af75078fSIntel 		fwd_streams[sm_id]->rx_bad_l4_csum = 0;
1265af75078fSIntel 
1266af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
1267af75078fSIntel 		memset(&fwd_streams[sm_id]->rx_burst_stats, 0,
1268af75078fSIntel 		       sizeof(fwd_streams[sm_id]->rx_burst_stats));
1269af75078fSIntel 		memset(&fwd_streams[sm_id]->tx_burst_stats, 0,
1270af75078fSIntel 		       sizeof(fwd_streams[sm_id]->tx_burst_stats));
1271af75078fSIntel #endif
1272af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
1273af75078fSIntel 		fwd_streams[sm_id]->core_cycles = 0;
1274af75078fSIntel #endif
1275af75078fSIntel 	}
1276af75078fSIntel 	if (with_tx_first) {
1277af75078fSIntel 		port_fwd_begin = tx_only_engine.port_fwd_begin;
1278af75078fSIntel 		if (port_fwd_begin != NULL) {
1279af75078fSIntel 			for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
1280af75078fSIntel 				(*port_fwd_begin)(fwd_ports_ids[i]);
1281af75078fSIntel 		}
1282acbf77a6SZhihong Wang 		while (with_tx_first--) {
1283acbf77a6SZhihong Wang 			launch_packet_forwarding(
1284acbf77a6SZhihong Wang 					run_one_txonly_burst_on_core);
1285af75078fSIntel 			rte_eal_mp_wait_lcore();
1286acbf77a6SZhihong Wang 		}
1287af75078fSIntel 		port_fwd_end = tx_only_engine.port_fwd_end;
1288af75078fSIntel 		if (port_fwd_end != NULL) {
1289af75078fSIntel 			for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
1290af75078fSIntel 				(*port_fwd_end)(fwd_ports_ids[i]);
1291af75078fSIntel 		}
1292af75078fSIntel 	}
1293af75078fSIntel 	launch_packet_forwarding(start_pkt_forward_on_core);
1294af75078fSIntel }
1295af75078fSIntel 
1296af75078fSIntel void
1297af75078fSIntel stop_packet_forwarding(void)
1298af75078fSIntel {
1299af75078fSIntel 	struct rte_eth_stats stats;
1300af75078fSIntel 	struct rte_port *port;
1301af75078fSIntel 	port_fwd_end_t  port_fwd_end;
1302af75078fSIntel 	int i;
1303af75078fSIntel 	portid_t   pt_id;
1304af75078fSIntel 	streamid_t sm_id;
1305af75078fSIntel 	lcoreid_t  lc_id;
1306af75078fSIntel 	uint64_t total_recv;
1307af75078fSIntel 	uint64_t total_xmit;
1308af75078fSIntel 	uint64_t total_rx_dropped;
1309af75078fSIntel 	uint64_t total_tx_dropped;
1310af75078fSIntel 	uint64_t total_rx_nombuf;
1311af75078fSIntel 	uint64_t tx_dropped;
1312af75078fSIntel 	uint64_t rx_bad_ip_csum;
1313af75078fSIntel 	uint64_t rx_bad_l4_csum;
1314af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
1315af75078fSIntel 	uint64_t fwd_cycles;
1316af75078fSIntel #endif
1317b7091f1dSJiayu Hu 
1318af75078fSIntel 	static const char *acc_stats_border = "+++++++++++++++";
1319af75078fSIntel 
1320af75078fSIntel 	if (test_done) {
1321af75078fSIntel 		printf("Packet forwarding not started\n");
1322af75078fSIntel 		return;
1323af75078fSIntel 	}
1324af75078fSIntel 	printf("Telling cores to stop...");
1325af75078fSIntel 	for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++)
1326af75078fSIntel 		fwd_lcores[lc_id]->stopped = 1;
1327af75078fSIntel 	printf("\nWaiting for lcores to finish...\n");
1328af75078fSIntel 	rte_eal_mp_wait_lcore();
1329af75078fSIntel 	port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end;
1330af75078fSIntel 	if (port_fwd_end != NULL) {
1331af75078fSIntel 		for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
1332af75078fSIntel 			pt_id = fwd_ports_ids[i];
1333af75078fSIntel 			(*port_fwd_end)(pt_id);
1334af75078fSIntel 		}
1335af75078fSIntel 	}
1336af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
1337af75078fSIntel 	fwd_cycles = 0;
1338af75078fSIntel #endif
1339af75078fSIntel 	for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
1340af75078fSIntel 		if (cur_fwd_config.nb_fwd_streams >
1341af75078fSIntel 		    cur_fwd_config.nb_fwd_ports) {
1342af75078fSIntel 			fwd_stream_stats_display(sm_id);
1343af75078fSIntel 			ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL;
1344af75078fSIntel 			ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL;
1345af75078fSIntel 		} else {
1346af75078fSIntel 			ports[fwd_streams[sm_id]->tx_port].tx_stream =
1347af75078fSIntel 				fwd_streams[sm_id];
1348af75078fSIntel 			ports[fwd_streams[sm_id]->rx_port].rx_stream =
1349af75078fSIntel 				fwd_streams[sm_id];
1350af75078fSIntel 		}
1351af75078fSIntel 		tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped;
1352af75078fSIntel 		tx_dropped = (uint64_t) (tx_dropped +
1353af75078fSIntel 					 fwd_streams[sm_id]->fwd_dropped);
1354af75078fSIntel 		ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped;
1355af75078fSIntel 
1356013af9b6SIntel 		rx_bad_ip_csum =
1357013af9b6SIntel 			ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum;
1358af75078fSIntel 		rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum +
1359af75078fSIntel 					 fwd_streams[sm_id]->rx_bad_ip_csum);
1360013af9b6SIntel 		ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum =
1361013af9b6SIntel 							rx_bad_ip_csum;
1362af75078fSIntel 
1363013af9b6SIntel 		rx_bad_l4_csum =
1364013af9b6SIntel 			ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum;
1365af75078fSIntel 		rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum +
1366af75078fSIntel 					 fwd_streams[sm_id]->rx_bad_l4_csum);
1367013af9b6SIntel 		ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum =
1368013af9b6SIntel 							rx_bad_l4_csum;
1369af75078fSIntel 
1370af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
1371af75078fSIntel 		fwd_cycles = (uint64_t) (fwd_cycles +
1372af75078fSIntel 					 fwd_streams[sm_id]->core_cycles);
1373af75078fSIntel #endif
1374af75078fSIntel 	}
1375af75078fSIntel 	total_recv = 0;
1376af75078fSIntel 	total_xmit = 0;
1377af75078fSIntel 	total_rx_dropped = 0;
1378af75078fSIntel 	total_tx_dropped = 0;
1379af75078fSIntel 	total_rx_nombuf  = 0;
13807741e4cfSIntel 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
1381af75078fSIntel 		pt_id = fwd_ports_ids[i];
1382af75078fSIntel 
1383af75078fSIntel 		port = &ports[pt_id];
1384af75078fSIntel 		rte_eth_stats_get(pt_id, &stats);
1385af75078fSIntel 		stats.ipackets -= port->stats.ipackets;
1386af75078fSIntel 		port->stats.ipackets = 0;
1387af75078fSIntel 		stats.opackets -= port->stats.opackets;
1388af75078fSIntel 		port->stats.opackets = 0;
1389af75078fSIntel 		stats.ibytes   -= port->stats.ibytes;
1390af75078fSIntel 		port->stats.ibytes = 0;
1391af75078fSIntel 		stats.obytes   -= port->stats.obytes;
1392af75078fSIntel 		port->stats.obytes = 0;
139370bdb186SIvan Boule 		stats.imissed  -= port->stats.imissed;
139470bdb186SIvan Boule 		port->stats.imissed = 0;
1395af75078fSIntel 		stats.oerrors  -= port->stats.oerrors;
1396af75078fSIntel 		port->stats.oerrors = 0;
1397af75078fSIntel 		stats.rx_nombuf -= port->stats.rx_nombuf;
1398af75078fSIntel 		port->stats.rx_nombuf = 0;
1399af75078fSIntel 
1400af75078fSIntel 		total_recv += stats.ipackets;
1401af75078fSIntel 		total_xmit += stats.opackets;
140270bdb186SIvan Boule 		total_rx_dropped += stats.imissed;
1403af75078fSIntel 		total_tx_dropped += port->tx_dropped;
1404af75078fSIntel 		total_rx_nombuf  += stats.rx_nombuf;
1405af75078fSIntel 
1406af75078fSIntel 		fwd_port_stats_display(pt_id, &stats);
1407af75078fSIntel 	}
1408b7091f1dSJiayu Hu 
1409af75078fSIntel 	printf("\n  %s Accumulated forward statistics for all ports"
1410af75078fSIntel 	       "%s\n",
1411af75078fSIntel 	       acc_stats_border, acc_stats_border);
1412af75078fSIntel 	printf("  RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
1413af75078fSIntel 	       "%-"PRIu64"\n"
1414af75078fSIntel 	       "  TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
1415af75078fSIntel 	       "%-"PRIu64"\n",
1416af75078fSIntel 	       total_recv, total_rx_dropped, total_recv + total_rx_dropped,
1417af75078fSIntel 	       total_xmit, total_tx_dropped, total_xmit + total_tx_dropped);
1418af75078fSIntel 	if (total_rx_nombuf > 0)
1419af75078fSIntel 		printf("  RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf);
1420af75078fSIntel 	printf("  %s++++++++++++++++++++++++++++++++++++++++++++++"
1421af75078fSIntel 	       "%s\n",
1422af75078fSIntel 	       acc_stats_border, acc_stats_border);
1423af75078fSIntel #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
1424af75078fSIntel 	if (total_recv > 0)
1425af75078fSIntel 		printf("\n  CPU cycles/packet=%u (total cycles="
1426af75078fSIntel 		       "%"PRIu64" / total RX packets=%"PRIu64")\n",
1427af75078fSIntel 		       (unsigned int)(fwd_cycles / total_recv),
1428af75078fSIntel 		       fwd_cycles, total_recv);
1429af75078fSIntel #endif
1430af75078fSIntel 	printf("\nDone.\n");
1431af75078fSIntel 	test_done = 1;
1432af75078fSIntel }
1433af75078fSIntel 
1434cfae07fdSOuyang Changchun void
1435cfae07fdSOuyang Changchun dev_set_link_up(portid_t pid)
1436cfae07fdSOuyang Changchun {
1437492ab604SZhiyong Yang 	if (rte_eth_dev_set_link_up(pid) < 0)
1438cfae07fdSOuyang Changchun 		printf("\nSet link up fail.\n");
1439cfae07fdSOuyang Changchun }
1440cfae07fdSOuyang Changchun 
1441cfae07fdSOuyang Changchun void
1442cfae07fdSOuyang Changchun dev_set_link_down(portid_t pid)
1443cfae07fdSOuyang Changchun {
1444492ab604SZhiyong Yang 	if (rte_eth_dev_set_link_down(pid) < 0)
1445cfae07fdSOuyang Changchun 		printf("\nSet link down fail.\n");
1446cfae07fdSOuyang Changchun }
1447cfae07fdSOuyang Changchun 
1448ce8d5614SIntel static int
1449ce8d5614SIntel all_ports_started(void)
1450ce8d5614SIntel {
1451ce8d5614SIntel 	portid_t pi;
1452ce8d5614SIntel 	struct rte_port *port;
1453ce8d5614SIntel 
14547d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
1455ce8d5614SIntel 		port = &ports[pi];
1456ce8d5614SIntel 		/* Check if there is a port which is not started */
145741b05095SBernard Iremonger 		if ((port->port_status != RTE_PORT_STARTED) &&
145841b05095SBernard Iremonger 			(port->slave_flag == 0))
1459ce8d5614SIntel 			return 0;
1460ce8d5614SIntel 	}
1461ce8d5614SIntel 
1462ce8d5614SIntel 	/* No port is not started */
1463ce8d5614SIntel 	return 1;
1464ce8d5614SIntel }
1465ce8d5614SIntel 
1466148f963fSBruce Richardson int
14676018eb8cSShahaf Shuler port_is_stopped(portid_t port_id)
14686018eb8cSShahaf Shuler {
14696018eb8cSShahaf Shuler 	struct rte_port *port = &ports[port_id];
14706018eb8cSShahaf Shuler 
14716018eb8cSShahaf Shuler 	if ((port->port_status != RTE_PORT_STOPPED) &&
14726018eb8cSShahaf Shuler 	    (port->slave_flag == 0))
14736018eb8cSShahaf Shuler 		return 0;
14746018eb8cSShahaf Shuler 	return 1;
14756018eb8cSShahaf Shuler }
14766018eb8cSShahaf Shuler 
14776018eb8cSShahaf Shuler int
1478edab33b1STetsuya Mukawa all_ports_stopped(void)
1479edab33b1STetsuya Mukawa {
1480edab33b1STetsuya Mukawa 	portid_t pi;
1481edab33b1STetsuya Mukawa 
14827d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
14836018eb8cSShahaf Shuler 		if (!port_is_stopped(pi))
1484edab33b1STetsuya Mukawa 			return 0;
1485edab33b1STetsuya Mukawa 	}
1486edab33b1STetsuya Mukawa 
1487edab33b1STetsuya Mukawa 	return 1;
1488edab33b1STetsuya Mukawa }
1489edab33b1STetsuya Mukawa 
1490edab33b1STetsuya Mukawa int
1491edab33b1STetsuya Mukawa port_is_started(portid_t port_id)
1492edab33b1STetsuya Mukawa {
1493edab33b1STetsuya Mukawa 	if (port_id_is_invalid(port_id, ENABLED_WARN))
1494edab33b1STetsuya Mukawa 		return 0;
1495edab33b1STetsuya Mukawa 
1496edab33b1STetsuya Mukawa 	if (ports[port_id].port_status != RTE_PORT_STARTED)
1497edab33b1STetsuya Mukawa 		return 0;
1498edab33b1STetsuya Mukawa 
1499edab33b1STetsuya Mukawa 	return 1;
1500edab33b1STetsuya Mukawa }
1501edab33b1STetsuya Mukawa 
1502edab33b1STetsuya Mukawa static int
1503edab33b1STetsuya Mukawa port_is_closed(portid_t port_id)
1504edab33b1STetsuya Mukawa {
1505edab33b1STetsuya Mukawa 	if (port_id_is_invalid(port_id, ENABLED_WARN))
1506edab33b1STetsuya Mukawa 		return 0;
1507edab33b1STetsuya Mukawa 
1508edab33b1STetsuya Mukawa 	if (ports[port_id].port_status != RTE_PORT_CLOSED)
1509edab33b1STetsuya Mukawa 		return 0;
1510edab33b1STetsuya Mukawa 
1511edab33b1STetsuya Mukawa 	return 1;
1512edab33b1STetsuya Mukawa }
1513edab33b1STetsuya Mukawa 
1514edab33b1STetsuya Mukawa int
1515ce8d5614SIntel start_port(portid_t pid)
1516ce8d5614SIntel {
151792d2703eSMichael Qiu 	int diag, need_check_link_status = -1;
1518ce8d5614SIntel 	portid_t pi;
1519ce8d5614SIntel 	queueid_t qi;
1520ce8d5614SIntel 	struct rte_port *port;
15212950a769SDeclan Doherty 	struct ether_addr mac_addr;
152276ad4a2dSGaetan Rivet 	enum rte_eth_event_type event_type;
1523ce8d5614SIntel 
15244468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
15254468635fSMichael Qiu 		return 0;
15264468635fSMichael Qiu 
1527ce8d5614SIntel 	if(dcb_config)
1528ce8d5614SIntel 		dcb_test = 1;
15297d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
1530edab33b1STetsuya Mukawa 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
1531ce8d5614SIntel 			continue;
1532ce8d5614SIntel 
153392d2703eSMichael Qiu 		need_check_link_status = 0;
1534ce8d5614SIntel 		port = &ports[pi];
1535ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED,
1536ce8d5614SIntel 						 RTE_PORT_HANDLING) == 0) {
1537ce8d5614SIntel 			printf("Port %d is now not stopped\n", pi);
1538ce8d5614SIntel 			continue;
1539ce8d5614SIntel 		}
1540ce8d5614SIntel 
1541ce8d5614SIntel 		if (port->need_reconfig > 0) {
1542ce8d5614SIntel 			port->need_reconfig = 0;
1543ce8d5614SIntel 
15447ee3e944SVasily Philipov 			if (flow_isolate_all) {
15457ee3e944SVasily Philipov 				int ret = port_flow_isolate(pi, 1);
15467ee3e944SVasily Philipov 				if (ret) {
15477ee3e944SVasily Philipov 					printf("Failed to apply isolated"
15487ee3e944SVasily Philipov 					       " mode on port %d\n", pi);
15497ee3e944SVasily Philipov 					return -1;
15507ee3e944SVasily Philipov 				}
15517ee3e944SVasily Philipov 			}
15527ee3e944SVasily Philipov 
15535706de65SJulien Cretin 			printf("Configuring Port %d (socket %u)\n", pi,
155420a0286fSLiu Xiaofeng 					port->socket_id);
1555ce8d5614SIntel 			/* configure port */
1556ce8d5614SIntel 			diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq,
1557ce8d5614SIntel 						&(port->dev_conf));
1558ce8d5614SIntel 			if (diag != 0) {
1559ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
1560ce8d5614SIntel 				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
1561ce8d5614SIntel 					printf("Port %d can not be set back "
1562ce8d5614SIntel 							"to stopped\n", pi);
1563ce8d5614SIntel 				printf("Fail to configure port %d\n", pi);
1564ce8d5614SIntel 				/* try to reconfigure port next time */
1565ce8d5614SIntel 				port->need_reconfig = 1;
1566148f963fSBruce Richardson 				return -1;
1567ce8d5614SIntel 			}
1568ce8d5614SIntel 		}
1569ce8d5614SIntel 		if (port->need_reconfig_queues > 0) {
1570ce8d5614SIntel 			port->need_reconfig_queues = 0;
1571597f9fafSShahaf Shuler 			port->tx_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE;
1572597f9fafSShahaf Shuler 			/* Apply Tx offloads configuration */
1573597f9fafSShahaf Shuler 			port->tx_conf.offloads = port->dev_conf.txmode.offloads;
1574ce8d5614SIntel 			/* setup tx queues */
1575ce8d5614SIntel 			for (qi = 0; qi < nb_txq; qi++) {
1576b6ea6408SIntel 				if ((numa_support) &&
1577b6ea6408SIntel 					(txring_numa[pi] != NUMA_NO_CONFIG))
1578b6ea6408SIntel 					diag = rte_eth_tx_queue_setup(pi, qi,
1579b6ea6408SIntel 						nb_txd,txring_numa[pi],
1580b6ea6408SIntel 						&(port->tx_conf));
1581b6ea6408SIntel 				else
1582b6ea6408SIntel 					diag = rte_eth_tx_queue_setup(pi, qi,
1583b6ea6408SIntel 						nb_txd,port->socket_id,
1584b6ea6408SIntel 						&(port->tx_conf));
1585b6ea6408SIntel 
1586ce8d5614SIntel 				if (diag == 0)
1587ce8d5614SIntel 					continue;
1588ce8d5614SIntel 
1589ce8d5614SIntel 				/* Fail to setup tx queue, return */
1590ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
1591ce8d5614SIntel 							RTE_PORT_HANDLING,
1592ce8d5614SIntel 							RTE_PORT_STOPPED) == 0)
1593ce8d5614SIntel 					printf("Port %d can not be set back "
1594ce8d5614SIntel 							"to stopped\n", pi);
1595ce8d5614SIntel 				printf("Fail to configure port %d tx queues\n", pi);
1596ce8d5614SIntel 				/* try to reconfigure queues next time */
1597ce8d5614SIntel 				port->need_reconfig_queues = 1;
1598148f963fSBruce Richardson 				return -1;
1599ce8d5614SIntel 			}
16000074d02fSShahaf Shuler 			/* Apply Rx offloads configuration */
16010074d02fSShahaf Shuler 			port->rx_conf.offloads = port->dev_conf.rxmode.offloads;
1602ce8d5614SIntel 			/* setup rx queues */
1603ce8d5614SIntel 			for (qi = 0; qi < nb_rxq; qi++) {
1604b6ea6408SIntel 				if ((numa_support) &&
1605b6ea6408SIntel 					(rxring_numa[pi] != NUMA_NO_CONFIG)) {
1606b6ea6408SIntel 					struct rte_mempool * mp =
1607b6ea6408SIntel 						mbuf_pool_find(rxring_numa[pi]);
1608b6ea6408SIntel 					if (mp == NULL) {
1609b6ea6408SIntel 						printf("Failed to setup RX queue:"
1610b6ea6408SIntel 							"No mempool allocation"
1611b6ea6408SIntel 							" on the socket %d\n",
1612b6ea6408SIntel 							rxring_numa[pi]);
1613148f963fSBruce Richardson 						return -1;
1614b6ea6408SIntel 					}
1615b6ea6408SIntel 
1616b6ea6408SIntel 					diag = rte_eth_rx_queue_setup(pi, qi,
1617b6ea6408SIntel 					     nb_rxd,rxring_numa[pi],
1618b6ea6408SIntel 					     &(port->rx_conf),mp);
16191e1d6bddSBernard Iremonger 				} else {
16201e1d6bddSBernard Iremonger 					struct rte_mempool *mp =
16211e1d6bddSBernard Iremonger 						mbuf_pool_find(port->socket_id);
16221e1d6bddSBernard Iremonger 					if (mp == NULL) {
16231e1d6bddSBernard Iremonger 						printf("Failed to setup RX queue:"
16241e1d6bddSBernard Iremonger 							"No mempool allocation"
16251e1d6bddSBernard Iremonger 							" on the socket %d\n",
16261e1d6bddSBernard Iremonger 							port->socket_id);
16271e1d6bddSBernard Iremonger 						return -1;
1628b6ea6408SIntel 					}
1629b6ea6408SIntel 					diag = rte_eth_rx_queue_setup(pi, qi,
1630b6ea6408SIntel 					     nb_rxd,port->socket_id,
16311e1d6bddSBernard Iremonger 					     &(port->rx_conf), mp);
16321e1d6bddSBernard Iremonger 				}
1633ce8d5614SIntel 				if (diag == 0)
1634ce8d5614SIntel 					continue;
1635ce8d5614SIntel 
1636ce8d5614SIntel 				/* Fail to setup rx queue, return */
1637ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
1638ce8d5614SIntel 							RTE_PORT_HANDLING,
1639ce8d5614SIntel 							RTE_PORT_STOPPED) == 0)
1640ce8d5614SIntel 					printf("Port %d can not be set back "
1641ce8d5614SIntel 							"to stopped\n", pi);
1642ce8d5614SIntel 				printf("Fail to configure port %d rx queues\n", pi);
1643ce8d5614SIntel 				/* try to reconfigure queues next time */
1644ce8d5614SIntel 				port->need_reconfig_queues = 1;
1645148f963fSBruce Richardson 				return -1;
1646ce8d5614SIntel 			}
1647ce8d5614SIntel 		}
164876ad4a2dSGaetan Rivet 
1649ce8d5614SIntel 		/* start port */
1650ce8d5614SIntel 		if (rte_eth_dev_start(pi) < 0) {
1651ce8d5614SIntel 			printf("Fail to start port %d\n", pi);
1652ce8d5614SIntel 
1653ce8d5614SIntel 			/* Fail to setup rx queue, return */
1654ce8d5614SIntel 			if (rte_atomic16_cmpset(&(port->port_status),
1655ce8d5614SIntel 				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
1656ce8d5614SIntel 				printf("Port %d can not be set back to "
1657ce8d5614SIntel 							"stopped\n", pi);
1658ce8d5614SIntel 			continue;
1659ce8d5614SIntel 		}
1660ce8d5614SIntel 
1661ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
1662ce8d5614SIntel 			RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0)
1663ce8d5614SIntel 			printf("Port %d can not be set into started\n", pi);
1664ce8d5614SIntel 
16652950a769SDeclan Doherty 		rte_eth_macaddr_get(pi, &mac_addr);
1666d8c89163SZijie Pan 		printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi,
16672950a769SDeclan Doherty 				mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
16682950a769SDeclan Doherty 				mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
16692950a769SDeclan Doherty 				mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]);
1670d8c89163SZijie Pan 
1671ce8d5614SIntel 		/* at least one port started, need checking link status */
1672ce8d5614SIntel 		need_check_link_status = 1;
1673ce8d5614SIntel 	}
1674ce8d5614SIntel 
16754fb82244SMatan Azrad 	for (event_type = RTE_ETH_EVENT_UNKNOWN;
16764fb82244SMatan Azrad 	     event_type < RTE_ETH_EVENT_MAX;
16774fb82244SMatan Azrad 	     event_type++) {
16784fb82244SMatan Azrad 		diag = rte_eth_dev_callback_register(RTE_ETH_ALL,
16794fb82244SMatan Azrad 						event_type,
16804fb82244SMatan Azrad 						eth_event_callback,
16814fb82244SMatan Azrad 						NULL);
16824fb82244SMatan Azrad 		if (diag) {
16834fb82244SMatan Azrad 			printf("Failed to setup even callback for event %d\n",
16844fb82244SMatan Azrad 				event_type);
16854fb82244SMatan Azrad 			return -1;
16864fb82244SMatan Azrad 		}
16874fb82244SMatan Azrad 	}
16884fb82244SMatan Azrad 
168992d2703eSMichael Qiu 	if (need_check_link_status == 1 && !no_link_check)
1690edab33b1STetsuya Mukawa 		check_all_ports_link_status(RTE_PORT_ALL);
169192d2703eSMichael Qiu 	else if (need_check_link_status == 0)
1692ce8d5614SIntel 		printf("Please stop the ports first\n");
1693ce8d5614SIntel 
1694ce8d5614SIntel 	printf("Done\n");
1695148f963fSBruce Richardson 	return 0;
1696ce8d5614SIntel }
1697ce8d5614SIntel 
1698ce8d5614SIntel void
1699ce8d5614SIntel stop_port(portid_t pid)
1700ce8d5614SIntel {
1701ce8d5614SIntel 	portid_t pi;
1702ce8d5614SIntel 	struct rte_port *port;
1703ce8d5614SIntel 	int need_check_link_status = 0;
1704ce8d5614SIntel 
1705ce8d5614SIntel 	if (dcb_test) {
1706ce8d5614SIntel 		dcb_test = 0;
1707ce8d5614SIntel 		dcb_config = 0;
1708ce8d5614SIntel 	}
17094468635fSMichael Qiu 
17104468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
17114468635fSMichael Qiu 		return;
17124468635fSMichael Qiu 
1713ce8d5614SIntel 	printf("Stopping ports...\n");
1714ce8d5614SIntel 
17157d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
17164468635fSMichael Qiu 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
1717ce8d5614SIntel 			continue;
1718ce8d5614SIntel 
1719a8ef3e3aSBernard Iremonger 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
1720a8ef3e3aSBernard Iremonger 			printf("Please remove port %d from forwarding configuration.\n", pi);
1721a8ef3e3aSBernard Iremonger 			continue;
1722a8ef3e3aSBernard Iremonger 		}
1723a8ef3e3aSBernard Iremonger 
17240e545d30SBernard Iremonger 		if (port_is_bonding_slave(pi)) {
17250e545d30SBernard Iremonger 			printf("Please remove port %d from bonded device.\n", pi);
17260e545d30SBernard Iremonger 			continue;
17270e545d30SBernard Iremonger 		}
17280e545d30SBernard Iremonger 
1729ce8d5614SIntel 		port = &ports[pi];
1730ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED,
1731ce8d5614SIntel 						RTE_PORT_HANDLING) == 0)
1732ce8d5614SIntel 			continue;
1733ce8d5614SIntel 
1734ce8d5614SIntel 		rte_eth_dev_stop(pi);
1735ce8d5614SIntel 
1736ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
1737ce8d5614SIntel 			RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
1738ce8d5614SIntel 			printf("Port %d can not be set into stopped\n", pi);
1739ce8d5614SIntel 		need_check_link_status = 1;
1740ce8d5614SIntel 	}
1741bc202406SDavid Marchand 	if (need_check_link_status && !no_link_check)
1742edab33b1STetsuya Mukawa 		check_all_ports_link_status(RTE_PORT_ALL);
1743ce8d5614SIntel 
1744ce8d5614SIntel 	printf("Done\n");
1745ce8d5614SIntel }
1746ce8d5614SIntel 
1747ce8d5614SIntel void
1748ce8d5614SIntel close_port(portid_t pid)
1749ce8d5614SIntel {
1750ce8d5614SIntel 	portid_t pi;
1751ce8d5614SIntel 	struct rte_port *port;
1752ce8d5614SIntel 
17534468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
17544468635fSMichael Qiu 		return;
17554468635fSMichael Qiu 
1756ce8d5614SIntel 	printf("Closing ports...\n");
1757ce8d5614SIntel 
17587d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
17594468635fSMichael Qiu 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
1760ce8d5614SIntel 			continue;
1761ce8d5614SIntel 
1762a8ef3e3aSBernard Iremonger 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
1763a8ef3e3aSBernard Iremonger 			printf("Please remove port %d from forwarding configuration.\n", pi);
1764a8ef3e3aSBernard Iremonger 			continue;
1765a8ef3e3aSBernard Iremonger 		}
1766a8ef3e3aSBernard Iremonger 
17670e545d30SBernard Iremonger 		if (port_is_bonding_slave(pi)) {
17680e545d30SBernard Iremonger 			printf("Please remove port %d from bonded device.\n", pi);
17690e545d30SBernard Iremonger 			continue;
17700e545d30SBernard Iremonger 		}
17710e545d30SBernard Iremonger 
1772ce8d5614SIntel 		port = &ports[pi];
1773ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
1774d4e8ad64SMichael Qiu 			RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) {
1775d4e8ad64SMichael Qiu 			printf("Port %d is already closed\n", pi);
1776d4e8ad64SMichael Qiu 			continue;
1777d4e8ad64SMichael Qiu 		}
1778d4e8ad64SMichael Qiu 
1779d4e8ad64SMichael Qiu 		if (rte_atomic16_cmpset(&(port->port_status),
1780ce8d5614SIntel 			RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) {
1781ce8d5614SIntel 			printf("Port %d is now not stopped\n", pi);
1782ce8d5614SIntel 			continue;
1783ce8d5614SIntel 		}
1784ce8d5614SIntel 
1785938a184aSAdrien Mazarguil 		if (port->flow_list)
1786938a184aSAdrien Mazarguil 			port_flow_flush(pi);
1787ce8d5614SIntel 		rte_eth_dev_close(pi);
1788ce8d5614SIntel 
1789ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
1790ce8d5614SIntel 			RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0)
1791b38bb262SPablo de Lara 			printf("Port %d cannot be set to closed\n", pi);
1792ce8d5614SIntel 	}
1793ce8d5614SIntel 
1794ce8d5614SIntel 	printf("Done\n");
1795ce8d5614SIntel }
1796ce8d5614SIntel 
1797edab33b1STetsuya Mukawa void
179897f1e196SWei Dai reset_port(portid_t pid)
179997f1e196SWei Dai {
180097f1e196SWei Dai 	int diag;
180197f1e196SWei Dai 	portid_t pi;
180297f1e196SWei Dai 	struct rte_port *port;
180397f1e196SWei Dai 
180497f1e196SWei Dai 	if (port_id_is_invalid(pid, ENABLED_WARN))
180597f1e196SWei Dai 		return;
180697f1e196SWei Dai 
180797f1e196SWei Dai 	printf("Resetting ports...\n");
180897f1e196SWei Dai 
180997f1e196SWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
181097f1e196SWei Dai 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
181197f1e196SWei Dai 			continue;
181297f1e196SWei Dai 
181397f1e196SWei Dai 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
181497f1e196SWei Dai 			printf("Please remove port %d from forwarding "
181597f1e196SWei Dai 			       "configuration.\n", pi);
181697f1e196SWei Dai 			continue;
181797f1e196SWei Dai 		}
181897f1e196SWei Dai 
181997f1e196SWei Dai 		if (port_is_bonding_slave(pi)) {
182097f1e196SWei Dai 			printf("Please remove port %d from bonded device.\n",
182197f1e196SWei Dai 			       pi);
182297f1e196SWei Dai 			continue;
182397f1e196SWei Dai 		}
182497f1e196SWei Dai 
182597f1e196SWei Dai 		diag = rte_eth_dev_reset(pi);
182697f1e196SWei Dai 		if (diag == 0) {
182797f1e196SWei Dai 			port = &ports[pi];
182897f1e196SWei Dai 			port->need_reconfig = 1;
182997f1e196SWei Dai 			port->need_reconfig_queues = 1;
183097f1e196SWei Dai 		} else {
183197f1e196SWei Dai 			printf("Failed to reset port %d. diag=%d\n", pi, diag);
183297f1e196SWei Dai 		}
183397f1e196SWei Dai 	}
183497f1e196SWei Dai 
183597f1e196SWei Dai 	printf("Done\n");
183697f1e196SWei Dai }
183797f1e196SWei Dai 
183897f1e196SWei Dai void
1839edab33b1STetsuya Mukawa attach_port(char *identifier)
1840ce8d5614SIntel {
1841ebf5e9b7SBernard Iremonger 	portid_t pi = 0;
1842931126baSBernard Iremonger 	unsigned int socket_id;
1843ce8d5614SIntel 
1844edab33b1STetsuya Mukawa 	printf("Attaching a new port...\n");
1845edab33b1STetsuya Mukawa 
1846edab33b1STetsuya Mukawa 	if (identifier == NULL) {
1847edab33b1STetsuya Mukawa 		printf("Invalid parameters are specified\n");
1848edab33b1STetsuya Mukawa 		return;
1849ce8d5614SIntel 	}
1850ce8d5614SIntel 
1851edab33b1STetsuya Mukawa 	if (rte_eth_dev_attach(identifier, &pi))
1852edab33b1STetsuya Mukawa 		return;
1853edab33b1STetsuya Mukawa 
1854931126baSBernard Iremonger 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
1855931126baSBernard Iremonger 	/* if socket_id is invalid, set to 0 */
1856931126baSBernard Iremonger 	if (check_socket_id(socket_id) < 0)
1857931126baSBernard Iremonger 		socket_id = 0;
1858931126baSBernard Iremonger 	reconfig(pi, socket_id);
1859edab33b1STetsuya Mukawa 	rte_eth_promiscuous_enable(pi);
1860edab33b1STetsuya Mukawa 
1861edab33b1STetsuya Mukawa 	nb_ports = rte_eth_dev_count();
1862edab33b1STetsuya Mukawa 
1863edab33b1STetsuya Mukawa 	ports[pi].port_status = RTE_PORT_STOPPED;
1864edab33b1STetsuya Mukawa 
1865edab33b1STetsuya Mukawa 	printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
1866edab33b1STetsuya Mukawa 	printf("Done\n");
1867edab33b1STetsuya Mukawa }
1868edab33b1STetsuya Mukawa 
1869edab33b1STetsuya Mukawa void
187028caa76aSZhiyong Yang detach_port(portid_t port_id)
18715f4ec54fSChen Jing D(Mark) {
1872edab33b1STetsuya Mukawa 	char name[RTE_ETH_NAME_MAX_LEN];
18735f4ec54fSChen Jing D(Mark) 
1874edab33b1STetsuya Mukawa 	printf("Detaching a port...\n");
18755f4ec54fSChen Jing D(Mark) 
1876edab33b1STetsuya Mukawa 	if (!port_is_closed(port_id)) {
1877edab33b1STetsuya Mukawa 		printf("Please close port first\n");
1878edab33b1STetsuya Mukawa 		return;
1879edab33b1STetsuya Mukawa 	}
1880edab33b1STetsuya Mukawa 
1881938a184aSAdrien Mazarguil 	if (ports[port_id].flow_list)
1882938a184aSAdrien Mazarguil 		port_flow_flush(port_id);
1883938a184aSAdrien Mazarguil 
18843070419eSGaetan Rivet 	if (rte_eth_dev_detach(port_id, name)) {
1885285fd101SOlivier Matz 		TESTPMD_LOG(ERR, "Failed to detach port '%s'\n", name);
1886edab33b1STetsuya Mukawa 		return;
18873070419eSGaetan Rivet 	}
1888edab33b1STetsuya Mukawa 
1889edab33b1STetsuya Mukawa 	nb_ports = rte_eth_dev_count();
1890edab33b1STetsuya Mukawa 
1891edab33b1STetsuya Mukawa 	printf("Port '%s' is detached. Now total ports is %d\n",
1892edab33b1STetsuya Mukawa 			name, nb_ports);
1893edab33b1STetsuya Mukawa 	printf("Done\n");
1894edab33b1STetsuya Mukawa 	return;
18955f4ec54fSChen Jing D(Mark) }
18965f4ec54fSChen Jing D(Mark) 
1897af75078fSIntel void
1898af75078fSIntel pmd_test_exit(void)
1899af75078fSIntel {
1900af75078fSIntel 	portid_t pt_id;
1901af75078fSIntel 
19028210ec25SPablo de Lara 	if (test_done == 0)
19038210ec25SPablo de Lara 		stop_packet_forwarding();
19048210ec25SPablo de Lara 
1905d3a274ceSZhihong Wang 	if (ports != NULL) {
1906d3a274ceSZhihong Wang 		no_link_check = 1;
19077d89b261SGaetan Rivet 		RTE_ETH_FOREACH_DEV(pt_id) {
1908d3a274ceSZhihong Wang 			printf("\nShutting down port %d...\n", pt_id);
1909af75078fSIntel 			fflush(stdout);
1910d3a274ceSZhihong Wang 			stop_port(pt_id);
1911d3a274ceSZhihong Wang 			close_port(pt_id);
1912af75078fSIntel 		}
1913d3a274ceSZhihong Wang 	}
1914d3a274ceSZhihong Wang 	printf("\nBye...\n");
1915af75078fSIntel }
1916af75078fSIntel 
1917af75078fSIntel typedef void (*cmd_func_t)(void);
1918af75078fSIntel struct pmd_test_command {
1919af75078fSIntel 	const char *cmd_name;
1920af75078fSIntel 	cmd_func_t cmd_func;
1921af75078fSIntel };
1922af75078fSIntel 
1923af75078fSIntel #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0]))
1924af75078fSIntel 
1925ce8d5614SIntel /* Check the link status of all ports in up to 9s, and print them finally */
1926af75078fSIntel static void
1927edab33b1STetsuya Mukawa check_all_ports_link_status(uint32_t port_mask)
1928af75078fSIntel {
1929ce8d5614SIntel #define CHECK_INTERVAL 100 /* 100ms */
1930ce8d5614SIntel #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1931f8244c63SZhiyong Yang 	portid_t portid;
1932f8244c63SZhiyong Yang 	uint8_t count, all_ports_up, print_flag = 0;
1933ce8d5614SIntel 	struct rte_eth_link link;
1934ce8d5614SIntel 
1935ce8d5614SIntel 	printf("Checking link statuses...\n");
1936ce8d5614SIntel 	fflush(stdout);
1937ce8d5614SIntel 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
1938ce8d5614SIntel 		all_ports_up = 1;
19397d89b261SGaetan Rivet 		RTE_ETH_FOREACH_DEV(portid) {
1940ce8d5614SIntel 			if ((port_mask & (1 << portid)) == 0)
1941ce8d5614SIntel 				continue;
1942ce8d5614SIntel 			memset(&link, 0, sizeof(link));
1943ce8d5614SIntel 			rte_eth_link_get_nowait(portid, &link);
1944ce8d5614SIntel 			/* print link status if flag set */
1945ce8d5614SIntel 			if (print_flag == 1) {
1946ce8d5614SIntel 				if (link.link_status)
1947f8244c63SZhiyong Yang 					printf(
1948f8244c63SZhiyong Yang 					"Port%d Link Up. speed %u Mbps- %s\n",
1949f8244c63SZhiyong Yang 					portid, link.link_speed,
1950ce8d5614SIntel 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
1951ce8d5614SIntel 					("full-duplex") : ("half-duplex\n"));
1952ce8d5614SIntel 				else
1953f8244c63SZhiyong Yang 					printf("Port %d Link Down\n", portid);
1954ce8d5614SIntel 				continue;
1955ce8d5614SIntel 			}
1956ce8d5614SIntel 			/* clear all_ports_up flag if any link down */
195709419f23SThomas Monjalon 			if (link.link_status == ETH_LINK_DOWN) {
1958ce8d5614SIntel 				all_ports_up = 0;
1959ce8d5614SIntel 				break;
1960ce8d5614SIntel 			}
1961ce8d5614SIntel 		}
1962ce8d5614SIntel 		/* after finally printing all link status, get out */
1963ce8d5614SIntel 		if (print_flag == 1)
1964ce8d5614SIntel 			break;
1965ce8d5614SIntel 
1966ce8d5614SIntel 		if (all_ports_up == 0) {
1967ce8d5614SIntel 			fflush(stdout);
1968ce8d5614SIntel 			rte_delay_ms(CHECK_INTERVAL);
1969ce8d5614SIntel 		}
1970ce8d5614SIntel 
1971ce8d5614SIntel 		/* set the print_flag if all ports up or timeout */
1972ce8d5614SIntel 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1973ce8d5614SIntel 			print_flag = 1;
1974ce8d5614SIntel 		}
19758ea656f8SGaetan Rivet 
19768ea656f8SGaetan Rivet 		if (lsc_interrupt)
19778ea656f8SGaetan Rivet 			break;
1978ce8d5614SIntel 	}
1979af75078fSIntel }
1980af75078fSIntel 
1981284c908cSGaetan Rivet static void
1982284c908cSGaetan Rivet rmv_event_callback(void *arg)
1983284c908cSGaetan Rivet {
1984284c908cSGaetan Rivet 	struct rte_eth_dev *dev;
198528caa76aSZhiyong Yang 	portid_t port_id = (intptr_t)arg;
1986284c908cSGaetan Rivet 
1987284c908cSGaetan Rivet 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
1988284c908cSGaetan Rivet 	dev = &rte_eth_devices[port_id];
1989284c908cSGaetan Rivet 
1990284c908cSGaetan Rivet 	stop_port(port_id);
1991284c908cSGaetan Rivet 	close_port(port_id);
1992f3a1188cSGaetan Rivet 	printf("removing device %s\n", dev->device->name);
19933070419eSGaetan Rivet 	if (rte_eal_dev_detach(dev->device))
1994285fd101SOlivier Matz 		TESTPMD_LOG(ERR, "Failed to detach device %s\n",
19953070419eSGaetan Rivet 			dev->device->name);
1996284c908cSGaetan Rivet }
1997284c908cSGaetan Rivet 
199876ad4a2dSGaetan Rivet /* This function is used by the interrupt thread */
1999d6af1a13SBernard Iremonger static int
2000f8244c63SZhiyong Yang eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
2001d6af1a13SBernard Iremonger 		  void *ret_param)
200276ad4a2dSGaetan Rivet {
200376ad4a2dSGaetan Rivet 	static const char * const event_desc[] = {
200476ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_UNKNOWN] = "Unknown",
200576ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_INTR_LSC] = "LSC",
200676ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_QUEUE_STATE] = "Queue state",
200776ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_INTR_RESET] = "Interrupt reset",
200876ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_VF_MBOX] = "VF Mbox",
200976ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_MACSEC] = "MACsec",
201076ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_INTR_RMV] = "device removal",
20114fb82244SMatan Azrad 		[RTE_ETH_EVENT_NEW] = "device probed",
20124fb82244SMatan Azrad 		[RTE_ETH_EVENT_DESTROY] = "device released",
201376ad4a2dSGaetan Rivet 		[RTE_ETH_EVENT_MAX] = NULL,
201476ad4a2dSGaetan Rivet 	};
201576ad4a2dSGaetan Rivet 
201676ad4a2dSGaetan Rivet 	RTE_SET_USED(param);
2017d6af1a13SBernard Iremonger 	RTE_SET_USED(ret_param);
201876ad4a2dSGaetan Rivet 
201976ad4a2dSGaetan Rivet 	if (type >= RTE_ETH_EVENT_MAX) {
202076ad4a2dSGaetan Rivet 		fprintf(stderr, "\nPort %" PRIu8 ": %s called upon invalid event %d\n",
202176ad4a2dSGaetan Rivet 			port_id, __func__, type);
202276ad4a2dSGaetan Rivet 		fflush(stderr);
20233af72783SGaetan Rivet 	} else if (event_print_mask & (UINT32_C(1) << type)) {
202476ad4a2dSGaetan Rivet 		printf("\nPort %" PRIu8 ": %s event\n", port_id,
202576ad4a2dSGaetan Rivet 			event_desc[type]);
202676ad4a2dSGaetan Rivet 		fflush(stdout);
202776ad4a2dSGaetan Rivet 	}
2028284c908cSGaetan Rivet 
2029284c908cSGaetan Rivet 	switch (type) {
2030284c908cSGaetan Rivet 	case RTE_ETH_EVENT_INTR_RMV:
2031284c908cSGaetan Rivet 		if (rte_eal_alarm_set(100000,
2032284c908cSGaetan Rivet 				rmv_event_callback, (void *)(intptr_t)port_id))
2033284c908cSGaetan Rivet 			fprintf(stderr, "Could not set up deferred device removal\n");
2034284c908cSGaetan Rivet 		break;
2035284c908cSGaetan Rivet 	default:
2036284c908cSGaetan Rivet 		break;
2037284c908cSGaetan Rivet 	}
2038d6af1a13SBernard Iremonger 	return 0;
203976ad4a2dSGaetan Rivet }
204076ad4a2dSGaetan Rivet 
2041013af9b6SIntel static int
204228caa76aSZhiyong Yang set_tx_queue_stats_mapping_registers(portid_t port_id, struct rte_port *port)
2043af75078fSIntel {
2044013af9b6SIntel 	uint16_t i;
2045af75078fSIntel 	int diag;
2046013af9b6SIntel 	uint8_t mapping_found = 0;
2047af75078fSIntel 
2048013af9b6SIntel 	for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
2049013af9b6SIntel 		if ((tx_queue_stats_mappings[i].port_id == port_id) &&
2050013af9b6SIntel 				(tx_queue_stats_mappings[i].queue_id < nb_txq )) {
2051013af9b6SIntel 			diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id,
2052013af9b6SIntel 					tx_queue_stats_mappings[i].queue_id,
2053013af9b6SIntel 					tx_queue_stats_mappings[i].stats_counter_id);
2054013af9b6SIntel 			if (diag != 0)
2055013af9b6SIntel 				return diag;
2056013af9b6SIntel 			mapping_found = 1;
2057af75078fSIntel 		}
2058013af9b6SIntel 	}
2059013af9b6SIntel 	if (mapping_found)
2060013af9b6SIntel 		port->tx_queue_stats_mapping_enabled = 1;
2061013af9b6SIntel 	return 0;
2062013af9b6SIntel }
2063013af9b6SIntel 
2064013af9b6SIntel static int
206528caa76aSZhiyong Yang set_rx_queue_stats_mapping_registers(portid_t port_id, struct rte_port *port)
2066013af9b6SIntel {
2067013af9b6SIntel 	uint16_t i;
2068013af9b6SIntel 	int diag;
2069013af9b6SIntel 	uint8_t mapping_found = 0;
2070013af9b6SIntel 
2071013af9b6SIntel 	for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
2072013af9b6SIntel 		if ((rx_queue_stats_mappings[i].port_id == port_id) &&
2073013af9b6SIntel 				(rx_queue_stats_mappings[i].queue_id < nb_rxq )) {
2074013af9b6SIntel 			diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id,
2075013af9b6SIntel 					rx_queue_stats_mappings[i].queue_id,
2076013af9b6SIntel 					rx_queue_stats_mappings[i].stats_counter_id);
2077013af9b6SIntel 			if (diag != 0)
2078013af9b6SIntel 				return diag;
2079013af9b6SIntel 			mapping_found = 1;
2080013af9b6SIntel 		}
2081013af9b6SIntel 	}
2082013af9b6SIntel 	if (mapping_found)
2083013af9b6SIntel 		port->rx_queue_stats_mapping_enabled = 1;
2084013af9b6SIntel 	return 0;
2085013af9b6SIntel }
2086013af9b6SIntel 
2087013af9b6SIntel static void
208828caa76aSZhiyong Yang map_port_queue_stats_mapping_registers(portid_t pi, struct rte_port *port)
2089013af9b6SIntel {
2090013af9b6SIntel 	int diag = 0;
2091013af9b6SIntel 
2092013af9b6SIntel 	diag = set_tx_queue_stats_mapping_registers(pi, port);
2093af75078fSIntel 	if (diag != 0) {
2094013af9b6SIntel 		if (diag == -ENOTSUP) {
2095013af9b6SIntel 			port->tx_queue_stats_mapping_enabled = 0;
2096013af9b6SIntel 			printf("TX queue stats mapping not supported port id=%d\n", pi);
2097013af9b6SIntel 		}
2098013af9b6SIntel 		else
2099013af9b6SIntel 			rte_exit(EXIT_FAILURE,
2100013af9b6SIntel 					"set_tx_queue_stats_mapping_registers "
2101013af9b6SIntel 					"failed for port id=%d diag=%d\n",
2102af75078fSIntel 					pi, diag);
2103af75078fSIntel 	}
2104013af9b6SIntel 
2105013af9b6SIntel 	diag = set_rx_queue_stats_mapping_registers(pi, port);
2106af75078fSIntel 	if (diag != 0) {
2107013af9b6SIntel 		if (diag == -ENOTSUP) {
2108013af9b6SIntel 			port->rx_queue_stats_mapping_enabled = 0;
2109013af9b6SIntel 			printf("RX queue stats mapping not supported port id=%d\n", pi);
2110013af9b6SIntel 		}
2111013af9b6SIntel 		else
2112013af9b6SIntel 			rte_exit(EXIT_FAILURE,
2113013af9b6SIntel 					"set_rx_queue_stats_mapping_registers "
2114013af9b6SIntel 					"failed for port id=%d diag=%d\n",
2115af75078fSIntel 					pi, diag);
2116af75078fSIntel 	}
2117af75078fSIntel }
2118af75078fSIntel 
2119f2c5125aSPablo de Lara static void
2120f2c5125aSPablo de Lara rxtx_port_config(struct rte_port *port)
2121f2c5125aSPablo de Lara {
2122f2c5125aSPablo de Lara 	port->rx_conf = port->dev_info.default_rxconf;
2123f2c5125aSPablo de Lara 	port->tx_conf = port->dev_info.default_txconf;
2124f2c5125aSPablo de Lara 
2125f2c5125aSPablo de Lara 	/* Check if any RX/TX parameters have been passed */
2126f2c5125aSPablo de Lara 	if (rx_pthresh != RTE_PMD_PARAM_UNSET)
2127f2c5125aSPablo de Lara 		port->rx_conf.rx_thresh.pthresh = rx_pthresh;
2128f2c5125aSPablo de Lara 
2129f2c5125aSPablo de Lara 	if (rx_hthresh != RTE_PMD_PARAM_UNSET)
2130f2c5125aSPablo de Lara 		port->rx_conf.rx_thresh.hthresh = rx_hthresh;
2131f2c5125aSPablo de Lara 
2132f2c5125aSPablo de Lara 	if (rx_wthresh != RTE_PMD_PARAM_UNSET)
2133f2c5125aSPablo de Lara 		port->rx_conf.rx_thresh.wthresh = rx_wthresh;
2134f2c5125aSPablo de Lara 
2135f2c5125aSPablo de Lara 	if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
2136f2c5125aSPablo de Lara 		port->rx_conf.rx_free_thresh = rx_free_thresh;
2137f2c5125aSPablo de Lara 
2138f2c5125aSPablo de Lara 	if (rx_drop_en != RTE_PMD_PARAM_UNSET)
2139f2c5125aSPablo de Lara 		port->rx_conf.rx_drop_en = rx_drop_en;
2140f2c5125aSPablo de Lara 
2141f2c5125aSPablo de Lara 	if (tx_pthresh != RTE_PMD_PARAM_UNSET)
2142f2c5125aSPablo de Lara 		port->tx_conf.tx_thresh.pthresh = tx_pthresh;
2143f2c5125aSPablo de Lara 
2144f2c5125aSPablo de Lara 	if (tx_hthresh != RTE_PMD_PARAM_UNSET)
2145f2c5125aSPablo de Lara 		port->tx_conf.tx_thresh.hthresh = tx_hthresh;
2146f2c5125aSPablo de Lara 
2147f2c5125aSPablo de Lara 	if (tx_wthresh != RTE_PMD_PARAM_UNSET)
2148f2c5125aSPablo de Lara 		port->tx_conf.tx_thresh.wthresh = tx_wthresh;
2149f2c5125aSPablo de Lara 
2150f2c5125aSPablo de Lara 	if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
2151f2c5125aSPablo de Lara 		port->tx_conf.tx_rs_thresh = tx_rs_thresh;
2152f2c5125aSPablo de Lara 
2153f2c5125aSPablo de Lara 	if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
2154f2c5125aSPablo de Lara 		port->tx_conf.tx_free_thresh = tx_free_thresh;
2155f2c5125aSPablo de Lara }
2156f2c5125aSPablo de Lara 
2157013af9b6SIntel void
2158013af9b6SIntel init_port_config(void)
2159013af9b6SIntel {
2160013af9b6SIntel 	portid_t pid;
2161013af9b6SIntel 	struct rte_port *port;
2162013af9b6SIntel 
21637d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
2164013af9b6SIntel 		port = &ports[pid];
2165013af9b6SIntel 		port->dev_conf.fdir_conf = fdir_conf;
21663ce690d3SBruce Richardson 		if (nb_rxq > 1) {
2167013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
2168013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf;
2169af75078fSIntel 		} else {
2170013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
2171013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
2172af75078fSIntel 		}
21733ce690d3SBruce Richardson 
21745f592039SJingjing Wu 		if (port->dcb_flag == 0) {
21753ce690d3SBruce Richardson 			if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0)
21763ce690d3SBruce Richardson 				port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
21773ce690d3SBruce Richardson 			else
21783ce690d3SBruce Richardson 				port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
21793ce690d3SBruce Richardson 		}
21803ce690d3SBruce Richardson 
2181f2c5125aSPablo de Lara 		rxtx_port_config(port);
2182013af9b6SIntel 
2183013af9b6SIntel 		rte_eth_macaddr_get(pid, &port->eth_addr);
2184013af9b6SIntel 
2185013af9b6SIntel 		map_port_queue_stats_mapping_registers(pid, port);
218650c4440eSThomas Monjalon #if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
2187e261265eSRadu Nicolau 		rte_pmd_ixgbe_bypass_init(pid);
21887b7e5ba7SIntel #endif
21898ea656f8SGaetan Rivet 
21908ea656f8SGaetan Rivet 		if (lsc_interrupt &&
21918ea656f8SGaetan Rivet 		    (rte_eth_devices[pid].data->dev_flags &
21928ea656f8SGaetan Rivet 		     RTE_ETH_DEV_INTR_LSC))
21938ea656f8SGaetan Rivet 			port->dev_conf.intr_conf.lsc = 1;
2194284c908cSGaetan Rivet 		if (rmv_interrupt &&
2195284c908cSGaetan Rivet 		    (rte_eth_devices[pid].data->dev_flags &
2196284c908cSGaetan Rivet 		     RTE_ETH_DEV_INTR_RMV))
2197284c908cSGaetan Rivet 			port->dev_conf.intr_conf.rmv = 1;
21985b590fbeSJasvinder Singh 
21995b590fbeSJasvinder Singh #if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
22005b590fbeSJasvinder Singh 		/* Detect softnic port */
22015b590fbeSJasvinder Singh 		if (!strcmp(port->dev_info.driver_name, "net_softnic")) {
22025b590fbeSJasvinder Singh 			port->softnic_enable = 1;
22035b590fbeSJasvinder Singh 			memset(&port->softport, 0, sizeof(struct softnic_port));
22045b590fbeSJasvinder Singh 
22055b590fbeSJasvinder Singh 			if (!strcmp(cur_fwd_eng->fwd_mode_name, "tm"))
22065b590fbeSJasvinder Singh 				port->softport.tm_flag = 1;
22075b590fbeSJasvinder Singh 		}
22085b590fbeSJasvinder Singh #endif
2209013af9b6SIntel 	}
2210013af9b6SIntel }
2211013af9b6SIntel 
221241b05095SBernard Iremonger void set_port_slave_flag(portid_t slave_pid)
221341b05095SBernard Iremonger {
221441b05095SBernard Iremonger 	struct rte_port *port;
221541b05095SBernard Iremonger 
221641b05095SBernard Iremonger 	port = &ports[slave_pid];
221741b05095SBernard Iremonger 	port->slave_flag = 1;
221841b05095SBernard Iremonger }
221941b05095SBernard Iremonger 
222041b05095SBernard Iremonger void clear_port_slave_flag(portid_t slave_pid)
222141b05095SBernard Iremonger {
222241b05095SBernard Iremonger 	struct rte_port *port;
222341b05095SBernard Iremonger 
222441b05095SBernard Iremonger 	port = &ports[slave_pid];
222541b05095SBernard Iremonger 	port->slave_flag = 0;
222641b05095SBernard Iremonger }
222741b05095SBernard Iremonger 
22280e545d30SBernard Iremonger uint8_t port_is_bonding_slave(portid_t slave_pid)
22290e545d30SBernard Iremonger {
22300e545d30SBernard Iremonger 	struct rte_port *port;
22310e545d30SBernard Iremonger 
22320e545d30SBernard Iremonger 	port = &ports[slave_pid];
22330e545d30SBernard Iremonger 	return port->slave_flag;
22340e545d30SBernard Iremonger }
22350e545d30SBernard Iremonger 
2236013af9b6SIntel const uint16_t vlan_tags[] = {
2237013af9b6SIntel 		0,  1,  2,  3,  4,  5,  6,  7,
2238013af9b6SIntel 		8,  9, 10, 11,  12, 13, 14, 15,
2239013af9b6SIntel 		16, 17, 18, 19, 20, 21, 22, 23,
2240013af9b6SIntel 		24, 25, 26, 27, 28, 29, 30, 31
2241013af9b6SIntel };
2242013af9b6SIntel 
2243013af9b6SIntel static  int
22441a572499SJingjing Wu get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
22451a572499SJingjing Wu 		 enum dcb_mode_enable dcb_mode,
22461a572499SJingjing Wu 		 enum rte_eth_nb_tcs num_tcs,
22471a572499SJingjing Wu 		 uint8_t pfc_en)
2248013af9b6SIntel {
2249013af9b6SIntel 	uint8_t i;
2250af75078fSIntel 
2251af75078fSIntel 	/*
2252013af9b6SIntel 	 * Builds up the correct configuration for dcb+vt based on the vlan tags array
2253013af9b6SIntel 	 * given above, and the number of traffic classes available for use.
2254af75078fSIntel 	 */
22551a572499SJingjing Wu 	if (dcb_mode == DCB_VT_ENABLED) {
22561a572499SJingjing Wu 		struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
22571a572499SJingjing Wu 				&eth_conf->rx_adv_conf.vmdq_dcb_conf;
22581a572499SJingjing Wu 		struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
22591a572499SJingjing Wu 				&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf;
2260013af9b6SIntel 
2261547d946cSNirmoy Das 		/* VMDQ+DCB RX and TX configurations */
22621a572499SJingjing Wu 		vmdq_rx_conf->enable_default_pool = 0;
22631a572499SJingjing Wu 		vmdq_rx_conf->default_pool = 0;
22641a572499SJingjing Wu 		vmdq_rx_conf->nb_queue_pools =
22651a572499SJingjing Wu 			(num_tcs ==  ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
22661a572499SJingjing Wu 		vmdq_tx_conf->nb_queue_pools =
22671a572499SJingjing Wu 			(num_tcs ==  ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
2268013af9b6SIntel 
22691a572499SJingjing Wu 		vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
22701a572499SJingjing Wu 		for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
22711a572499SJingjing Wu 			vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i];
22721a572499SJingjing Wu 			vmdq_rx_conf->pool_map[i].pools =
22731a572499SJingjing Wu 				1 << (i % vmdq_rx_conf->nb_queue_pools);
2274af75078fSIntel 		}
2275013af9b6SIntel 		for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
2276f59908feSWei Dai 			vmdq_rx_conf->dcb_tc[i] = i % num_tcs;
2277f59908feSWei Dai 			vmdq_tx_conf->dcb_tc[i] = i % num_tcs;
2278013af9b6SIntel 		}
2279013af9b6SIntel 
2280013af9b6SIntel 		/* set DCB mode of RX and TX of multiple queues */
228132e7aa0bSIntel 		eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB;
228232e7aa0bSIntel 		eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB;
22831a572499SJingjing Wu 	} else {
22841a572499SJingjing Wu 		struct rte_eth_dcb_rx_conf *rx_conf =
22851a572499SJingjing Wu 				&eth_conf->rx_adv_conf.dcb_rx_conf;
22861a572499SJingjing Wu 		struct rte_eth_dcb_tx_conf *tx_conf =
22871a572499SJingjing Wu 				&eth_conf->tx_adv_conf.dcb_tx_conf;
2288013af9b6SIntel 
22891a572499SJingjing Wu 		rx_conf->nb_tcs = num_tcs;
22901a572499SJingjing Wu 		tx_conf->nb_tcs = num_tcs;
22911a572499SJingjing Wu 
2292bcd0e432SJingjing Wu 		for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
2293bcd0e432SJingjing Wu 			rx_conf->dcb_tc[i] = i % num_tcs;
2294bcd0e432SJingjing Wu 			tx_conf->dcb_tc[i] = i % num_tcs;
2295013af9b6SIntel 		}
22961a572499SJingjing Wu 		eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB_RSS;
22971a572499SJingjing Wu 		eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf;
229832e7aa0bSIntel 		eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
22991a572499SJingjing Wu 	}
23001a572499SJingjing Wu 
23011a572499SJingjing Wu 	if (pfc_en)
23021a572499SJingjing Wu 		eth_conf->dcb_capability_en =
23031a572499SJingjing Wu 				ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT;
2304013af9b6SIntel 	else
2305013af9b6SIntel 		eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
2306013af9b6SIntel 
2307013af9b6SIntel 	return 0;
2308013af9b6SIntel }
2309013af9b6SIntel 
2310013af9b6SIntel int
23111a572499SJingjing Wu init_port_dcb_config(portid_t pid,
23121a572499SJingjing Wu 		     enum dcb_mode_enable dcb_mode,
23131a572499SJingjing Wu 		     enum rte_eth_nb_tcs num_tcs,
23141a572499SJingjing Wu 		     uint8_t pfc_en)
2315013af9b6SIntel {
2316013af9b6SIntel 	struct rte_eth_conf port_conf;
2317013af9b6SIntel 	struct rte_port *rte_port;
2318013af9b6SIntel 	int retval;
2319013af9b6SIntel 	uint16_t i;
2320013af9b6SIntel 
23212a977b89SWenzhuo Lu 	rte_port = &ports[pid];
2322013af9b6SIntel 
2323013af9b6SIntel 	memset(&port_conf, 0, sizeof(struct rte_eth_conf));
2324013af9b6SIntel 	/* Enter DCB configuration status */
2325013af9b6SIntel 	dcb_config = 1;
2326013af9b6SIntel 
2327013af9b6SIntel 	/*set configuration of DCB in vt mode and DCB in non-vt mode*/
23281a572499SJingjing Wu 	retval = get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en);
2329013af9b6SIntel 	if (retval < 0)
2330013af9b6SIntel 		return retval;
23310074d02fSShahaf Shuler 	port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
2332013af9b6SIntel 
23332a977b89SWenzhuo Lu 	/**
23342a977b89SWenzhuo Lu 	 * Write the configuration into the device.
23352a977b89SWenzhuo Lu 	 * Set the numbers of RX & TX queues to 0, so
23362a977b89SWenzhuo Lu 	 * the RX & TX queues will not be setup.
23372a977b89SWenzhuo Lu 	 */
2338c947ef89SStephen Hemminger 	rte_eth_dev_configure(pid, 0, 0, &port_conf);
23392a977b89SWenzhuo Lu 
23402a977b89SWenzhuo Lu 	rte_eth_dev_info_get(pid, &rte_port->dev_info);
23412a977b89SWenzhuo Lu 
23422a977b89SWenzhuo Lu 	/* If dev_info.vmdq_pool_base is greater than 0,
23432a977b89SWenzhuo Lu 	 * the queue id of vmdq pools is started after pf queues.
23442a977b89SWenzhuo Lu 	 */
23452a977b89SWenzhuo Lu 	if (dcb_mode == DCB_VT_ENABLED &&
23462a977b89SWenzhuo Lu 	    rte_port->dev_info.vmdq_pool_base > 0) {
23472a977b89SWenzhuo Lu 		printf("VMDQ_DCB multi-queue mode is nonsensical"
23482a977b89SWenzhuo Lu 			" for port %d.", pid);
23492a977b89SWenzhuo Lu 		return -1;
23502a977b89SWenzhuo Lu 	}
23512a977b89SWenzhuo Lu 
23522a977b89SWenzhuo Lu 	/* Assume the ports in testpmd have the same dcb capability
23532a977b89SWenzhuo Lu 	 * and has the same number of rxq and txq in dcb mode
23542a977b89SWenzhuo Lu 	 */
23552a977b89SWenzhuo Lu 	if (dcb_mode == DCB_VT_ENABLED) {
235686ef65eeSBernard Iremonger 		if (rte_port->dev_info.max_vfs > 0) {
235786ef65eeSBernard Iremonger 			nb_rxq = rte_port->dev_info.nb_rx_queues;
235886ef65eeSBernard Iremonger 			nb_txq = rte_port->dev_info.nb_tx_queues;
235986ef65eeSBernard Iremonger 		} else {
23602a977b89SWenzhuo Lu 			nb_rxq = rte_port->dev_info.max_rx_queues;
23612a977b89SWenzhuo Lu 			nb_txq = rte_port->dev_info.max_tx_queues;
236286ef65eeSBernard Iremonger 		}
23632a977b89SWenzhuo Lu 	} else {
23642a977b89SWenzhuo Lu 		/*if vt is disabled, use all pf queues */
23652a977b89SWenzhuo Lu 		if (rte_port->dev_info.vmdq_pool_base == 0) {
23662a977b89SWenzhuo Lu 			nb_rxq = rte_port->dev_info.max_rx_queues;
23672a977b89SWenzhuo Lu 			nb_txq = rte_port->dev_info.max_tx_queues;
23682a977b89SWenzhuo Lu 		} else {
23692a977b89SWenzhuo Lu 			nb_rxq = (queueid_t)num_tcs;
23702a977b89SWenzhuo Lu 			nb_txq = (queueid_t)num_tcs;
23712a977b89SWenzhuo Lu 
23722a977b89SWenzhuo Lu 		}
23732a977b89SWenzhuo Lu 	}
23742a977b89SWenzhuo Lu 	rx_free_thresh = 64;
23752a977b89SWenzhuo Lu 
2376013af9b6SIntel 	memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
2377013af9b6SIntel 
2378f2c5125aSPablo de Lara 	rxtx_port_config(rte_port);
2379013af9b6SIntel 	/* VLAN filter */
23800074d02fSShahaf Shuler 	rte_port->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
23811a572499SJingjing Wu 	for (i = 0; i < RTE_DIM(vlan_tags); i++)
2382013af9b6SIntel 		rx_vft_set(pid, vlan_tags[i], 1);
2383013af9b6SIntel 
2384013af9b6SIntel 	rte_eth_macaddr_get(pid, &rte_port->eth_addr);
2385013af9b6SIntel 	map_port_queue_stats_mapping_registers(pid, rte_port);
2386013af9b6SIntel 
23877741e4cfSIntel 	rte_port->dcb_flag = 1;
23887741e4cfSIntel 
2389013af9b6SIntel 	return 0;
2390af75078fSIntel }
2391af75078fSIntel 
2392ffc468ffSTetsuya Mukawa static void
2393ffc468ffSTetsuya Mukawa init_port(void)
2394ffc468ffSTetsuya Mukawa {
2395ffc468ffSTetsuya Mukawa 	/* Configuration of Ethernet ports. */
2396ffc468ffSTetsuya Mukawa 	ports = rte_zmalloc("testpmd: ports",
2397ffc468ffSTetsuya Mukawa 			    sizeof(struct rte_port) * RTE_MAX_ETHPORTS,
2398ffc468ffSTetsuya Mukawa 			    RTE_CACHE_LINE_SIZE);
2399ffc468ffSTetsuya Mukawa 	if (ports == NULL) {
2400ffc468ffSTetsuya Mukawa 		rte_exit(EXIT_FAILURE,
2401ffc468ffSTetsuya Mukawa 				"rte_zmalloc(%d struct rte_port) failed\n",
2402ffc468ffSTetsuya Mukawa 				RTE_MAX_ETHPORTS);
2403ffc468ffSTetsuya Mukawa 	}
2404ffc468ffSTetsuya Mukawa }
2405ffc468ffSTetsuya Mukawa 
2406d3a274ceSZhihong Wang static void
2407d3a274ceSZhihong Wang force_quit(void)
2408d3a274ceSZhihong Wang {
2409d3a274ceSZhihong Wang 	pmd_test_exit();
2410d3a274ceSZhihong Wang 	prompt_exit();
2411d3a274ceSZhihong Wang }
2412d3a274ceSZhihong Wang 
2413d3a274ceSZhihong Wang static void
2414cfea1f30SPablo de Lara print_stats(void)
2415cfea1f30SPablo de Lara {
2416cfea1f30SPablo de Lara 	uint8_t i;
2417cfea1f30SPablo de Lara 	const char clr[] = { 27, '[', '2', 'J', '\0' };
2418cfea1f30SPablo de Lara 	const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' };
2419cfea1f30SPablo de Lara 
2420cfea1f30SPablo de Lara 	/* Clear screen and move to top left */
2421cfea1f30SPablo de Lara 	printf("%s%s", clr, top_left);
2422cfea1f30SPablo de Lara 
2423cfea1f30SPablo de Lara 	printf("\nPort statistics ====================================");
2424cfea1f30SPablo de Lara 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
2425cfea1f30SPablo de Lara 		nic_stats_display(fwd_ports_ids[i]);
2426cfea1f30SPablo de Lara }
2427cfea1f30SPablo de Lara 
2428cfea1f30SPablo de Lara static void
2429d3a274ceSZhihong Wang signal_handler(int signum)
2430d3a274ceSZhihong Wang {
2431d3a274ceSZhihong Wang 	if (signum == SIGINT || signum == SIGTERM) {
2432d3a274ceSZhihong Wang 		printf("\nSignal %d received, preparing to exit...\n",
2433d3a274ceSZhihong Wang 				signum);
2434102b7329SReshma Pattan #ifdef RTE_LIBRTE_PDUMP
2435102b7329SReshma Pattan 		/* uninitialize packet capture framework */
2436102b7329SReshma Pattan 		rte_pdump_uninit();
2437102b7329SReshma Pattan #endif
243862d3216dSReshma Pattan #ifdef RTE_LIBRTE_LATENCY_STATS
243962d3216dSReshma Pattan 		rte_latencystats_uninit();
244062d3216dSReshma Pattan #endif
2441d3a274ceSZhihong Wang 		force_quit();
2442d9a191a0SPhil Yang 		/* Set flag to indicate the force termination. */
2443d9a191a0SPhil Yang 		f_quit = 1;
2444d3a274ceSZhihong Wang 		/* exit with the expected status */
2445d3a274ceSZhihong Wang 		signal(signum, SIG_DFL);
2446d3a274ceSZhihong Wang 		kill(getpid(), signum);
2447d3a274ceSZhihong Wang 	}
2448d3a274ceSZhihong Wang }
2449d3a274ceSZhihong Wang 
2450af75078fSIntel int
2451af75078fSIntel main(int argc, char** argv)
2452af75078fSIntel {
2453af75078fSIntel 	int  diag;
2454f8244c63SZhiyong Yang 	portid_t port_id;
2455af75078fSIntel 
2456d3a274ceSZhihong Wang 	signal(SIGINT, signal_handler);
2457d3a274ceSZhihong Wang 	signal(SIGTERM, signal_handler);
2458d3a274ceSZhihong Wang 
2459af75078fSIntel 	diag = rte_eal_init(argc, argv);
2460af75078fSIntel 	if (diag < 0)
2461af75078fSIntel 		rte_panic("Cannot init EAL\n");
2462af75078fSIntel 
2463285fd101SOlivier Matz 	testpmd_logtype = rte_log_register("testpmd");
2464285fd101SOlivier Matz 	if (testpmd_logtype < 0)
2465285fd101SOlivier Matz 		rte_panic("Cannot register log type");
2466285fd101SOlivier Matz 	rte_log_set_level(testpmd_logtype, RTE_LOG_DEBUG);
2467285fd101SOlivier Matz 
24681c036b16SEelco Chaudron 	if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
2469285fd101SOlivier Matz 		TESTPMD_LOG(NOTICE, "mlockall() failed with error \"%s\"\n",
24701c036b16SEelco Chaudron 			strerror(errno));
24711c036b16SEelco Chaudron 	}
24721c036b16SEelco Chaudron 
2473102b7329SReshma Pattan #ifdef RTE_LIBRTE_PDUMP
2474102b7329SReshma Pattan 	/* initialize packet capture framework */
2475102b7329SReshma Pattan 	rte_pdump_init(NULL);
2476102b7329SReshma Pattan #endif
2477102b7329SReshma Pattan 
2478af75078fSIntel 	nb_ports = (portid_t) rte_eth_dev_count();
2479af75078fSIntel 	if (nb_ports == 0)
2480285fd101SOlivier Matz 		TESTPMD_LOG(WARNING, "No probed ethernet devices\n");
2481af75078fSIntel 
2482ffc468ffSTetsuya Mukawa 	/* allocate port structures, and init them */
2483ffc468ffSTetsuya Mukawa 	init_port();
2484ffc468ffSTetsuya Mukawa 
2485af75078fSIntel 	set_def_fwd_config();
2486af75078fSIntel 	if (nb_lcores == 0)
2487af75078fSIntel 		rte_panic("Empty set of forwarding logical cores - check the "
2488af75078fSIntel 			  "core mask supplied in the command parameters\n");
2489af75078fSIntel 
249065eb1e54SPablo de Lara 	/* Bitrate/latency stats disabled by default */
249130bcc68cSPablo de Lara #ifdef RTE_LIBRTE_BITRATE
2492e25e6c70SRemy Horton 	bitrate_enabled = 0;
249330bcc68cSPablo de Lara #endif
249465eb1e54SPablo de Lara #ifdef RTE_LIBRTE_LATENCY_STATS
249565eb1e54SPablo de Lara 	latencystats_enabled = 0;
249665eb1e54SPablo de Lara #endif
2497e25e6c70SRemy Horton 
2498af75078fSIntel 	argc -= diag;
2499af75078fSIntel 	argv += diag;
2500af75078fSIntel 	if (argc > 1)
2501af75078fSIntel 		launch_args_parse(argc, argv);
2502af75078fSIntel 
250399cabef0SPablo de Lara 	if (tx_first && interactive)
250499cabef0SPablo de Lara 		rte_exit(EXIT_FAILURE, "--tx-first cannot be used on "
250599cabef0SPablo de Lara 				"interactive mode.\n");
25068820cba4SDavid Hunt 
25078820cba4SDavid Hunt 	if (tx_first && lsc_interrupt) {
25088820cba4SDavid Hunt 		printf("Warning: lsc_interrupt needs to be off when "
25098820cba4SDavid Hunt 				" using tx_first. Disabling.\n");
25108820cba4SDavid Hunt 		lsc_interrupt = 0;
25118820cba4SDavid Hunt 	}
25128820cba4SDavid Hunt 
25135a8fb55cSReshma Pattan 	if (!nb_rxq && !nb_txq)
25145a8fb55cSReshma Pattan 		printf("Warning: Either rx or tx queues should be non-zero\n");
25155a8fb55cSReshma Pattan 
25165a8fb55cSReshma Pattan 	if (nb_rxq > 1 && nb_rxq > nb_txq)
2517af75078fSIntel 		printf("Warning: nb_rxq=%d enables RSS configuration, "
2518af75078fSIntel 		       "but nb_txq=%d will prevent to fully test it.\n",
2519af75078fSIntel 		       nb_rxq, nb_txq);
2520af75078fSIntel 
2521af75078fSIntel 	init_config();
2522148f963fSBruce Richardson 	if (start_port(RTE_PORT_ALL) != 0)
2523148f963fSBruce Richardson 		rte_exit(EXIT_FAILURE, "Start ports failed\n");
2524af75078fSIntel 
2525ce8d5614SIntel 	/* set all ports to promiscuous mode by default */
25267d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(port_id)
2527ce8d5614SIntel 		rte_eth_promiscuous_enable(port_id);
2528af75078fSIntel 
25297e4441c8SRemy Horton 	/* Init metrics library */
25307e4441c8SRemy Horton 	rte_metrics_init(rte_socket_id());
25317e4441c8SRemy Horton 
253262d3216dSReshma Pattan #ifdef RTE_LIBRTE_LATENCY_STATS
253362d3216dSReshma Pattan 	if (latencystats_enabled != 0) {
253462d3216dSReshma Pattan 		int ret = rte_latencystats_init(1, NULL);
253562d3216dSReshma Pattan 		if (ret)
253662d3216dSReshma Pattan 			printf("Warning: latencystats init()"
253762d3216dSReshma Pattan 				" returned error %d\n",	ret);
253862d3216dSReshma Pattan 		printf("Latencystats running on lcore %d\n",
253962d3216dSReshma Pattan 			latencystats_lcore_id);
254062d3216dSReshma Pattan 	}
254162d3216dSReshma Pattan #endif
254262d3216dSReshma Pattan 
25437e4441c8SRemy Horton 	/* Setup bitrate stats */
25447e4441c8SRemy Horton #ifdef RTE_LIBRTE_BITRATE
2545e25e6c70SRemy Horton 	if (bitrate_enabled != 0) {
25467e4441c8SRemy Horton 		bitrate_data = rte_stats_bitrate_create();
25477e4441c8SRemy Horton 		if (bitrate_data == NULL)
2548e25e6c70SRemy Horton 			rte_exit(EXIT_FAILURE,
2549e25e6c70SRemy Horton 				"Could not allocate bitrate data.\n");
25507e4441c8SRemy Horton 		rte_stats_bitrate_reg(bitrate_data);
2551e25e6c70SRemy Horton 	}
25527e4441c8SRemy Horton #endif
25537e4441c8SRemy Horton 
25540d56cb81SThomas Monjalon #ifdef RTE_LIBRTE_CMDLINE
255581ef862bSAllain Legacy 	if (strlen(cmdline_filename) != 0)
255681ef862bSAllain Legacy 		cmdline_read_from_file(cmdline_filename);
255781ef862bSAllain Legacy 
2558ca7feb22SCyril Chemparathy 	if (interactive == 1) {
2559ca7feb22SCyril Chemparathy 		if (auto_start) {
2560ca7feb22SCyril Chemparathy 			printf("Start automatic packet forwarding\n");
2561ca7feb22SCyril Chemparathy 			start_packet_forwarding(0);
2562ca7feb22SCyril Chemparathy 		}
2563af75078fSIntel 		prompt();
25640de738cfSJiayu Hu 		pmd_test_exit();
2565ca7feb22SCyril Chemparathy 	} else
25660d56cb81SThomas Monjalon #endif
25670d56cb81SThomas Monjalon 	{
2568af75078fSIntel 		char c;
2569af75078fSIntel 		int rc;
2570af75078fSIntel 
2571d9a191a0SPhil Yang 		f_quit = 0;
2572d9a191a0SPhil Yang 
2573af75078fSIntel 		printf("No commandline core given, start packet forwarding\n");
257499cabef0SPablo de Lara 		start_packet_forwarding(tx_first);
2575cfea1f30SPablo de Lara 		if (stats_period != 0) {
2576cfea1f30SPablo de Lara 			uint64_t prev_time = 0, cur_time, diff_time = 0;
2577cfea1f30SPablo de Lara 			uint64_t timer_period;
2578cfea1f30SPablo de Lara 
2579cfea1f30SPablo de Lara 			/* Convert to number of cycles */
2580cfea1f30SPablo de Lara 			timer_period = stats_period * rte_get_timer_hz();
2581cfea1f30SPablo de Lara 
2582d9a191a0SPhil Yang 			while (f_quit == 0) {
2583cfea1f30SPablo de Lara 				cur_time = rte_get_timer_cycles();
2584cfea1f30SPablo de Lara 				diff_time += cur_time - prev_time;
2585cfea1f30SPablo de Lara 
2586cfea1f30SPablo de Lara 				if (diff_time >= timer_period) {
2587cfea1f30SPablo de Lara 					print_stats();
2588cfea1f30SPablo de Lara 					/* Reset the timer */
2589cfea1f30SPablo de Lara 					diff_time = 0;
2590cfea1f30SPablo de Lara 				}
2591cfea1f30SPablo de Lara 				/* Sleep to avoid unnecessary checks */
2592cfea1f30SPablo de Lara 				prev_time = cur_time;
2593cfea1f30SPablo de Lara 				sleep(1);
2594cfea1f30SPablo de Lara 			}
2595cfea1f30SPablo de Lara 		}
2596cfea1f30SPablo de Lara 
2597af75078fSIntel 		printf("Press enter to exit\n");
2598af75078fSIntel 		rc = read(0, &c, 1);
2599d3a274ceSZhihong Wang 		pmd_test_exit();
2600af75078fSIntel 		if (rc < 0)
2601af75078fSIntel 			return 1;
2602af75078fSIntel 	}
2603af75078fSIntel 
2604af75078fSIntel 	return 0;
2605af75078fSIntel }
2606