xref: /dpdk/app/test-pmd/testpmd.c (revision 08dcd187068666c96e8a16604a1c96160ed310e9)
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>
15fb73e096SJeff Guo #include <stdbool.h>
16af75078fSIntel 
17af75078fSIntel #include <sys/queue.h>
18af75078fSIntel #include <sys/stat.h>
19af75078fSIntel 
20af75078fSIntel #include <stdint.h>
21af75078fSIntel #include <unistd.h>
22af75078fSIntel #include <inttypes.h>
23af75078fSIntel 
24af75078fSIntel #include <rte_common.h>
25d1eb542eSOlivier Matz #include <rte_errno.h>
26af75078fSIntel #include <rte_byteorder.h>
27af75078fSIntel #include <rte_log.h>
28af75078fSIntel #include <rte_debug.h>
29af75078fSIntel #include <rte_cycles.h>
30af75078fSIntel #include <rte_memory.h>
31af75078fSIntel #include <rte_memcpy.h>
32af75078fSIntel #include <rte_launch.h>
33af75078fSIntel #include <rte_eal.h>
34284c908cSGaetan Rivet #include <rte_alarm.h>
35af75078fSIntel #include <rte_per_lcore.h>
36af75078fSIntel #include <rte_lcore.h>
37af75078fSIntel #include <rte_atomic.h>
38af75078fSIntel #include <rte_branch_prediction.h>
39af75078fSIntel #include <rte_mempool.h>
40af75078fSIntel #include <rte_malloc.h>
41af75078fSIntel #include <rte_mbuf.h>
420e798567SPavan Nikhilesh #include <rte_mbuf_pool_ops.h>
43af75078fSIntel #include <rte_interrupts.h>
44af75078fSIntel #include <rte_pci.h>
45af75078fSIntel #include <rte_ether.h>
46af75078fSIntel #include <rte_ethdev.h>
47edab33b1STetsuya Mukawa #include <rte_dev.h>
48af75078fSIntel #include <rte_string_fns.h>
49a8d0d473SBruce Richardson #ifdef RTE_NET_IXGBE
50e261265eSRadu Nicolau #include <rte_pmd_ixgbe.h>
51e261265eSRadu Nicolau #endif
52a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
53102b7329SReshma Pattan #include <rte_pdump.h>
54102b7329SReshma Pattan #endif
55938a184aSAdrien Mazarguil #include <rte_flow.h>
567e4441c8SRemy Horton #include <rte_metrics.h>
57a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
587e4441c8SRemy Horton #include <rte_bitrate.h>
597e4441c8SRemy Horton #endif
60a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
6162d3216dSReshma Pattan #include <rte_latencystats.h>
6262d3216dSReshma Pattan #endif
63af75078fSIntel 
64af75078fSIntel #include "testpmd.h"
65af75078fSIntel 
66c7f5dba7SAnatoly Burakov #ifndef MAP_HUGETLB
67c7f5dba7SAnatoly Burakov /* FreeBSD may not have MAP_HUGETLB (in fact, it probably doesn't) */
68c7f5dba7SAnatoly Burakov #define HUGE_FLAG (0x40000)
69c7f5dba7SAnatoly Burakov #else
70c7f5dba7SAnatoly Burakov #define HUGE_FLAG MAP_HUGETLB
71c7f5dba7SAnatoly Burakov #endif
72c7f5dba7SAnatoly Burakov 
73c7f5dba7SAnatoly Burakov #ifndef MAP_HUGE_SHIFT
74c7f5dba7SAnatoly Burakov /* older kernels (or FreeBSD) will not have this define */
75c7f5dba7SAnatoly Burakov #define HUGE_SHIFT (26)
76c7f5dba7SAnatoly Burakov #else
77c7f5dba7SAnatoly Burakov #define HUGE_SHIFT MAP_HUGE_SHIFT
78c7f5dba7SAnatoly Burakov #endif
79c7f5dba7SAnatoly Burakov 
80c7f5dba7SAnatoly Burakov #define EXTMEM_HEAP_NAME "extmem"
8172512e18SViacheslav Ovsiienko #define EXTBUF_ZONE_SIZE RTE_PGSIZE_2M
82c7f5dba7SAnatoly Burakov 
83af75078fSIntel uint16_t verbose_level = 0; /**< Silent by default. */
84285fd101SOlivier Matz int testpmd_logtype; /**< Log type for testpmd logs */
85af75078fSIntel 
86cb056611SStephen Hemminger /* use main core for command line ? */
87af75078fSIntel uint8_t interactive = 0;
88ca7feb22SCyril Chemparathy uint8_t auto_start = 0;
8999cabef0SPablo de Lara uint8_t tx_first;
9081ef862bSAllain Legacy char cmdline_filename[PATH_MAX] = {0};
91af75078fSIntel 
92af75078fSIntel /*
93af75078fSIntel  * NUMA support configuration.
94af75078fSIntel  * When set, the NUMA support attempts to dispatch the allocation of the
95af75078fSIntel  * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the
96af75078fSIntel  * probed ports among the CPU sockets 0 and 1.
97af75078fSIntel  * Otherwise, all memory is allocated from CPU socket 0.
98af75078fSIntel  */
99999b2ee0SBruce Richardson uint8_t numa_support = 1; /**< numa enabled by default */
100af75078fSIntel 
101af75078fSIntel /*
102b6ea6408SIntel  * In UMA mode,all memory is allocated from socket 0 if --socket-num is
103b6ea6408SIntel  * not configured.
104b6ea6408SIntel  */
105b6ea6408SIntel uint8_t socket_num = UMA_NO_CONFIG;
106b6ea6408SIntel 
107b6ea6408SIntel /*
108c7f5dba7SAnatoly Burakov  * Select mempool allocation type:
109c7f5dba7SAnatoly Burakov  * - native: use regular DPDK memory
110c7f5dba7SAnatoly Burakov  * - anon: use regular DPDK memory to create mempool, but populate using
111c7f5dba7SAnatoly Burakov  *         anonymous memory (may not be IOVA-contiguous)
112c7f5dba7SAnatoly Burakov  * - xmem: use externally allocated hugepage memory
113148f963fSBruce Richardson  */
114c7f5dba7SAnatoly Burakov uint8_t mp_alloc_type = MP_ALLOC_NATIVE;
115148f963fSBruce Richardson 
116148f963fSBruce Richardson /*
11763531389SGeorgios Katsikas  * Store specified sockets on which memory pool to be used by ports
11863531389SGeorgios Katsikas  * is allocated.
11963531389SGeorgios Katsikas  */
12063531389SGeorgios Katsikas uint8_t port_numa[RTE_MAX_ETHPORTS];
12163531389SGeorgios Katsikas 
12263531389SGeorgios Katsikas /*
12363531389SGeorgios Katsikas  * Store specified sockets on which RX ring to be used by ports
12463531389SGeorgios Katsikas  * is allocated.
12563531389SGeorgios Katsikas  */
12663531389SGeorgios Katsikas uint8_t rxring_numa[RTE_MAX_ETHPORTS];
12763531389SGeorgios Katsikas 
12863531389SGeorgios Katsikas /*
12963531389SGeorgios Katsikas  * Store specified sockets on which TX ring to be used by ports
13063531389SGeorgios Katsikas  * is allocated.
13163531389SGeorgios Katsikas  */
13263531389SGeorgios Katsikas uint8_t txring_numa[RTE_MAX_ETHPORTS];
13363531389SGeorgios Katsikas 
13463531389SGeorgios Katsikas /*
135af75078fSIntel  * Record the Ethernet address of peer target ports to which packets are
136af75078fSIntel  * forwarded.
137547d946cSNirmoy Das  * Must be instantiated with the ethernet addresses of peer traffic generator
138af75078fSIntel  * ports.
139af75078fSIntel  */
1406d13ea8eSOlivier Matz struct rte_ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
141af75078fSIntel portid_t nb_peer_eth_addrs = 0;
142af75078fSIntel 
143af75078fSIntel /*
144af75078fSIntel  * Probed Target Environment.
145af75078fSIntel  */
146af75078fSIntel struct rte_port *ports;	       /**< For all probed ethernet ports. */
147af75078fSIntel portid_t nb_ports;             /**< Number of probed ethernet ports. */
148af75078fSIntel struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */
149af75078fSIntel lcoreid_t nb_lcores;           /**< Number of probed logical cores. */
150af75078fSIntel 
1514918a357SXiaoyun Li portid_t ports_ids[RTE_MAX_ETHPORTS]; /**< Store all port ids. */
1524918a357SXiaoyun Li 
153af75078fSIntel /*
154af75078fSIntel  * Test Forwarding Configuration.
155af75078fSIntel  *    nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
156af75078fSIntel  *    nb_fwd_ports  <= nb_cfg_ports  <= nb_ports
157af75078fSIntel  */
158af75078fSIntel lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
159af75078fSIntel lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
160af75078fSIntel portid_t  nb_cfg_ports;  /**< Number of configured ports. */
161af75078fSIntel portid_t  nb_fwd_ports;  /**< Number of forwarding ports. */
162af75078fSIntel 
163af75078fSIntel unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */
164af75078fSIntel portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];      /**< Port ids configuration. */
165af75078fSIntel 
166af75078fSIntel struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
167af75078fSIntel streamid_t nb_fwd_streams;       /**< Is equal to (nb_ports * nb_rxq). */
168af75078fSIntel 
169af75078fSIntel /*
170af75078fSIntel  * Forwarding engines.
171af75078fSIntel  */
172af75078fSIntel struct fwd_engine * fwd_engines[] = {
173af75078fSIntel 	&io_fwd_engine,
174af75078fSIntel 	&mac_fwd_engine,
175d47388f1SCyril Chemparathy 	&mac_swap_engine,
176e9e23a61SCyril Chemparathy 	&flow_gen_engine,
177af75078fSIntel 	&rx_only_engine,
178af75078fSIntel 	&tx_only_engine,
179af75078fSIntel 	&csum_fwd_engine,
180168dfa61SIvan Boule 	&icmp_echo_engine,
1813c156061SJens Freimann 	&noisy_vnf_engine,
1822564abdaSShiri Kuzin 	&five_tuple_swap_fwd_engine,
183af75078fSIntel #ifdef RTE_LIBRTE_IEEE1588
184af75078fSIntel 	&ieee1588_fwd_engine,
185af75078fSIntel #endif
186af75078fSIntel 	NULL,
187af75078fSIntel };
188af75078fSIntel 
18926cbb419SViacheslav Ovsiienko struct rte_mempool *mempools[RTE_MAX_NUMA_NODES * MAX_SEGS_BUFFER_SPLIT];
19059fcf854SShahaf Shuler uint16_t mempool_flags;
191401b744dSShahaf Shuler 
192af75078fSIntel struct fwd_config cur_fwd_config;
193af75078fSIntel struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */
194bf56fce1SZhihong Wang uint32_t retry_enabled;
195bf56fce1SZhihong Wang uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;
196bf56fce1SZhihong Wang uint32_t burst_tx_retry_num = BURST_TX_RETRIES;
197af75078fSIntel 
19826cbb419SViacheslav Ovsiienko uint32_t mbuf_data_size_n = 1; /* Number of specified mbuf sizes. */
19926cbb419SViacheslav Ovsiienko uint16_t mbuf_data_size[MAX_SEGS_BUFFER_SPLIT] = {
20026cbb419SViacheslav Ovsiienko 	DEFAULT_MBUF_DATA_SIZE
20126cbb419SViacheslav Ovsiienko }; /**< Mbuf data space size. */
202c8798818SIntel uint32_t param_total_num_mbufs = 0;  /**< number of mbufs in all pools - if
203c8798818SIntel                                       * specified on command-line. */
204cfea1f30SPablo de Lara uint16_t stats_period; /**< Period to show statistics (disabled by default) */
205d9a191a0SPhil Yang 
206d9a191a0SPhil Yang /*
207d9a191a0SPhil Yang  * In container, it cannot terminate the process which running with 'stats-period'
208d9a191a0SPhil Yang  * option. Set flag to exit stats period loop after received SIGINT/SIGTERM.
209d9a191a0SPhil Yang  */
210d9a191a0SPhil Yang uint8_t f_quit;
211d9a191a0SPhil Yang 
212af75078fSIntel /*
2130f2096d7SViacheslav Ovsiienko  * Configuration of packet segments used to scatter received packets
2140f2096d7SViacheslav Ovsiienko  * if some of split features is configured.
2150f2096d7SViacheslav Ovsiienko  */
2160f2096d7SViacheslav Ovsiienko uint16_t rx_pkt_seg_lengths[MAX_SEGS_BUFFER_SPLIT];
2170f2096d7SViacheslav Ovsiienko uint8_t  rx_pkt_nb_segs; /**< Number of segments to split */
21891c78e09SViacheslav Ovsiienko uint16_t rx_pkt_seg_offsets[MAX_SEGS_BUFFER_SPLIT];
21991c78e09SViacheslav Ovsiienko uint8_t  rx_pkt_nb_offs; /**< Number of specified offsets */
2200f2096d7SViacheslav Ovsiienko 
2210f2096d7SViacheslav Ovsiienko /*
222af75078fSIntel  * Configuration of packet segments used by the "txonly" processing engine.
223af75078fSIntel  */
224af75078fSIntel uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */
225af75078fSIntel uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
226af75078fSIntel 	TXONLY_DEF_PACKET_LEN,
227af75078fSIntel };
228af75078fSIntel uint8_t  tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */
229af75078fSIntel 
23079bec05bSKonstantin Ananyev enum tx_pkt_split tx_pkt_split = TX_PKT_SPLIT_OFF;
23179bec05bSKonstantin Ananyev /**< Split policy for packets to TX. */
23279bec05bSKonstantin Ananyev 
23382010ef5SYongseok Koh uint8_t txonly_multi_flow;
23482010ef5SYongseok Koh /**< Whether multiple flows are generated in TXONLY mode. */
23582010ef5SYongseok Koh 
2364940344dSViacheslav Ovsiienko uint32_t tx_pkt_times_inter;
2374940344dSViacheslav Ovsiienko /**< Timings for send scheduling in TXONLY mode, time between bursts. */
2384940344dSViacheslav Ovsiienko 
2394940344dSViacheslav Ovsiienko uint32_t tx_pkt_times_intra;
2404940344dSViacheslav Ovsiienko /**< Timings for send scheduling in TXONLY mode, time between packets. */
2414940344dSViacheslav Ovsiienko 
242af75078fSIntel uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */
243e9378bbcSCunming Liang uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */
244af75078fSIntel 
245900550deSIntel /* current configuration is in DCB or not,0 means it is not in DCB mode */
246900550deSIntel uint8_t dcb_config = 0;
247900550deSIntel 
248900550deSIntel /* Whether the dcb is in testing status */
249900550deSIntel uint8_t dcb_test = 0;
250900550deSIntel 
251af75078fSIntel /*
252af75078fSIntel  * Configurable number of RX/TX queues.
253af75078fSIntel  */
2541c69df45SOri Kam queueid_t nb_hairpinq; /**< Number of hairpin queues per port. */
255af75078fSIntel queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
256af75078fSIntel queueid_t nb_txq = 1; /**< Number of TX queues per port. */
257af75078fSIntel 
258af75078fSIntel /*
259af75078fSIntel  * Configurable number of RX/TX ring descriptors.
2608599ed31SRemy Horton  * Defaults are supplied by drivers via ethdev.
261af75078fSIntel  */
2628599ed31SRemy Horton #define RTE_TEST_RX_DESC_DEFAULT 0
2638599ed31SRemy Horton #define RTE_TEST_TX_DESC_DEFAULT 0
264af75078fSIntel uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
265af75078fSIntel uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
266af75078fSIntel 
267f2c5125aSPablo de Lara #define RTE_PMD_PARAM_UNSET -1
268af75078fSIntel /*
269af75078fSIntel  * Configurable values of RX and TX ring threshold registers.
270af75078fSIntel  */
271af75078fSIntel 
272f2c5125aSPablo de Lara int8_t rx_pthresh = RTE_PMD_PARAM_UNSET;
273f2c5125aSPablo de Lara int8_t rx_hthresh = RTE_PMD_PARAM_UNSET;
274f2c5125aSPablo de Lara int8_t rx_wthresh = RTE_PMD_PARAM_UNSET;
275af75078fSIntel 
276f2c5125aSPablo de Lara int8_t tx_pthresh = RTE_PMD_PARAM_UNSET;
277f2c5125aSPablo de Lara int8_t tx_hthresh = RTE_PMD_PARAM_UNSET;
278f2c5125aSPablo de Lara int8_t tx_wthresh = RTE_PMD_PARAM_UNSET;
279af75078fSIntel 
280af75078fSIntel /*
281af75078fSIntel  * Configurable value of RX free threshold.
282af75078fSIntel  */
283f2c5125aSPablo de Lara int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET;
284af75078fSIntel 
285af75078fSIntel /*
286ce8d5614SIntel  * Configurable value of RX drop enable.
287ce8d5614SIntel  */
288f2c5125aSPablo de Lara int8_t rx_drop_en = RTE_PMD_PARAM_UNSET;
289ce8d5614SIntel 
290ce8d5614SIntel /*
291af75078fSIntel  * Configurable value of TX free threshold.
292af75078fSIntel  */
293f2c5125aSPablo de Lara int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
294af75078fSIntel 
295af75078fSIntel /*
296af75078fSIntel  * Configurable value of TX RS bit threshold.
297af75078fSIntel  */
298f2c5125aSPablo de Lara int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
299af75078fSIntel 
300af75078fSIntel /*
3013c156061SJens Freimann  * Configurable value of buffered packets before sending.
3023c156061SJens Freimann  */
3033c156061SJens Freimann uint16_t noisy_tx_sw_bufsz;
3043c156061SJens Freimann 
3053c156061SJens Freimann /*
3063c156061SJens Freimann  * Configurable value of packet buffer timeout.
3073c156061SJens Freimann  */
3083c156061SJens Freimann uint16_t noisy_tx_sw_buf_flush_time;
3093c156061SJens Freimann 
3103c156061SJens Freimann /*
3113c156061SJens Freimann  * Configurable value for size of VNF internal memory area
3123c156061SJens Freimann  * used for simulating noisy neighbour behaviour
3133c156061SJens Freimann  */
3143c156061SJens Freimann uint64_t noisy_lkup_mem_sz;
3153c156061SJens Freimann 
3163c156061SJens Freimann /*
3173c156061SJens Freimann  * Configurable value of number of random writes done in
3183c156061SJens Freimann  * VNF simulation memory area.
3193c156061SJens Freimann  */
3203c156061SJens Freimann uint64_t noisy_lkup_num_writes;
3213c156061SJens Freimann 
3223c156061SJens Freimann /*
3233c156061SJens Freimann  * Configurable value of number of random reads done in
3243c156061SJens Freimann  * VNF simulation memory area.
3253c156061SJens Freimann  */
3263c156061SJens Freimann uint64_t noisy_lkup_num_reads;
3273c156061SJens Freimann 
3283c156061SJens Freimann /*
3293c156061SJens Freimann  * Configurable value of number of random reads/writes done in
3303c156061SJens Freimann  * VNF simulation memory area.
3313c156061SJens Freimann  */
3323c156061SJens Freimann uint64_t noisy_lkup_num_reads_writes;
3333c156061SJens Freimann 
3343c156061SJens Freimann /*
335af75078fSIntel  * Receive Side Scaling (RSS) configuration.
336af75078fSIntel  */
3378a387fa8SHelin Zhang uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */
338af75078fSIntel 
339af75078fSIntel /*
340af75078fSIntel  * Port topology configuration
341af75078fSIntel  */
342af75078fSIntel uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */
343af75078fSIntel 
3447741e4cfSIntel /*
3457741e4cfSIntel  * Avoids to flush all the RX streams before starts forwarding.
3467741e4cfSIntel  */
3477741e4cfSIntel uint8_t no_flush_rx = 0; /* flush by default */
3487741e4cfSIntel 
349af75078fSIntel /*
3507ee3e944SVasily Philipov  * Flow API isolated mode.
3517ee3e944SVasily Philipov  */
3527ee3e944SVasily Philipov uint8_t flow_isolate_all;
3537ee3e944SVasily Philipov 
3547ee3e944SVasily Philipov /*
355bc202406SDavid Marchand  * Avoids to check link status when starting/stopping a port.
356bc202406SDavid Marchand  */
357bc202406SDavid Marchand uint8_t no_link_check = 0; /* check by default */
358bc202406SDavid Marchand 
359bc202406SDavid Marchand /*
3606937d210SStephen Hemminger  * Don't automatically start all ports in interactive mode.
3616937d210SStephen Hemminger  */
3626937d210SStephen Hemminger uint8_t no_device_start = 0;
3636937d210SStephen Hemminger 
3646937d210SStephen Hemminger /*
3658ea656f8SGaetan Rivet  * Enable link status change notification
3668ea656f8SGaetan Rivet  */
3678ea656f8SGaetan Rivet uint8_t lsc_interrupt = 1; /* enabled by default */
3688ea656f8SGaetan Rivet 
3698ea656f8SGaetan Rivet /*
370284c908cSGaetan Rivet  * Enable device removal notification.
371284c908cSGaetan Rivet  */
372284c908cSGaetan Rivet uint8_t rmv_interrupt = 1; /* enabled by default */
373284c908cSGaetan Rivet 
374fb73e096SJeff Guo uint8_t hot_plug = 0; /**< hotplug disabled by default. */
375fb73e096SJeff Guo 
3764f1ed78eSThomas Monjalon /* After attach, port setup is called on event or by iterator */
3774f1ed78eSThomas Monjalon bool setup_on_probe_event = true;
3784f1ed78eSThomas Monjalon 
379b0a9354aSPavan Nikhilesh /* Clear ptypes on port initialization. */
380b0a9354aSPavan Nikhilesh uint8_t clear_ptypes = true;
381b0a9354aSPavan Nikhilesh 
38201817b10SBing Zhao /* Hairpin ports configuration mode. */
38301817b10SBing Zhao uint16_t hairpin_mode;
38401817b10SBing Zhao 
38597b5d8b5SThomas Monjalon /* Pretty printing of ethdev events */
38697b5d8b5SThomas Monjalon static const char * const eth_event_desc[] = {
38797b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_UNKNOWN] = "unknown",
38897b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_INTR_LSC] = "link state change",
38997b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_QUEUE_STATE] = "queue state",
39097b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_INTR_RESET] = "reset",
39197b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_VF_MBOX] = "VF mbox",
39297b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_IPSEC] = "IPsec",
39397b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_MACSEC] = "MACsec",
39497b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_INTR_RMV] = "device removal",
39597b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_NEW] = "device probed",
39697b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_DESTROY] = "device released",
3970e459ffaSDong Zhou 	[RTE_ETH_EVENT_FLOW_AGED] = "flow aged",
39897b5d8b5SThomas Monjalon 	[RTE_ETH_EVENT_MAX] = NULL,
39997b5d8b5SThomas Monjalon };
40097b5d8b5SThomas Monjalon 
401284c908cSGaetan Rivet /*
4023af72783SGaetan Rivet  * Display or mask ether events
4033af72783SGaetan Rivet  * Default to all events except VF_MBOX
4043af72783SGaetan Rivet  */
4053af72783SGaetan Rivet uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) |
4063af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) |
4073af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) |
4083af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) |
409badb87c1SAnoob Joseph 			    (UINT32_C(1) << RTE_ETH_EVENT_IPSEC) |
4103af72783SGaetan Rivet 			    (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) |
4110e459ffaSDong Zhou 			    (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV) |
4120e459ffaSDong Zhou 			    (UINT32_C(1) << RTE_ETH_EVENT_FLOW_AGED);
413e505d84cSAnatoly Burakov /*
414e505d84cSAnatoly Burakov  * Decide if all memory are locked for performance.
415e505d84cSAnatoly Burakov  */
416e505d84cSAnatoly Burakov int do_mlockall = 0;
4173af72783SGaetan Rivet 
4183af72783SGaetan Rivet /*
4197b7e5ba7SIntel  * NIC bypass mode configuration options.
4207b7e5ba7SIntel  */
4217b7e5ba7SIntel 
422a8d0d473SBruce Richardson #if defined RTE_NET_IXGBE && defined RTE_LIBRTE_IXGBE_BYPASS
4237b7e5ba7SIntel /* The NIC bypass watchdog timeout. */
424e261265eSRadu Nicolau uint32_t bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
4257b7e5ba7SIntel #endif
4267b7e5ba7SIntel 
427e261265eSRadu Nicolau 
428a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
42962d3216dSReshma Pattan 
43062d3216dSReshma Pattan /*
43162d3216dSReshma Pattan  * Set when latency stats is enabled in the commandline
43262d3216dSReshma Pattan  */
43362d3216dSReshma Pattan uint8_t latencystats_enabled;
43462d3216dSReshma Pattan 
43562d3216dSReshma Pattan /*
43662d3216dSReshma Pattan  * Lcore ID to serive latency statistics.
43762d3216dSReshma Pattan  */
43862d3216dSReshma Pattan lcoreid_t latencystats_lcore_id = -1;
43962d3216dSReshma Pattan 
44062d3216dSReshma Pattan #endif
44162d3216dSReshma Pattan 
4427b7e5ba7SIntel /*
443af75078fSIntel  * Ethernet device configuration.
444af75078fSIntel  */
445af75078fSIntel struct rte_eth_rxmode rx_mode = {
44635b2d13fSOlivier Matz 	.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
44735b2d13fSOlivier Matz 		/**< Default maximum frame length. */
448af75078fSIntel };
449af75078fSIntel 
45007e5f7bdSShahaf Shuler struct rte_eth_txmode tx_mode = {
45107e5f7bdSShahaf Shuler 	.offloads = DEV_TX_OFFLOAD_MBUF_FAST_FREE,
45207e5f7bdSShahaf Shuler };
453fd8c20aaSShahaf Shuler 
454af75078fSIntel struct rte_fdir_conf fdir_conf = {
455af75078fSIntel 	.mode = RTE_FDIR_MODE_NONE,
456af75078fSIntel 	.pballoc = RTE_FDIR_PBALLOC_64K,
457af75078fSIntel 	.status = RTE_FDIR_REPORT_STATUS,
458d9d5e6f2SJingjing Wu 	.mask = {
45926f579aaSWei Zhao 		.vlan_tci_mask = 0xFFEF,
460d9d5e6f2SJingjing Wu 		.ipv4_mask     = {
461d9d5e6f2SJingjing Wu 			.src_ip = 0xFFFFFFFF,
462d9d5e6f2SJingjing Wu 			.dst_ip = 0xFFFFFFFF,
463d9d5e6f2SJingjing Wu 		},
464d9d5e6f2SJingjing Wu 		.ipv6_mask     = {
465d9d5e6f2SJingjing Wu 			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
466d9d5e6f2SJingjing Wu 			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
467d9d5e6f2SJingjing Wu 		},
468d9d5e6f2SJingjing Wu 		.src_port_mask = 0xFFFF,
469d9d5e6f2SJingjing Wu 		.dst_port_mask = 0xFFFF,
47047b3ac6bSWenzhuo Lu 		.mac_addr_byte_mask = 0xFF,
47147b3ac6bSWenzhuo Lu 		.tunnel_type_mask = 1,
47247b3ac6bSWenzhuo Lu 		.tunnel_id_mask = 0xFFFFFFFF,
473d9d5e6f2SJingjing Wu 	},
474af75078fSIntel 	.drop_queue = 127,
475af75078fSIntel };
476af75078fSIntel 
4772950a769SDeclan Doherty volatile int test_done = 1; /* stop packet forwarding when set to 1. */
478af75078fSIntel 
479a4fd5eeeSElza Mathew /*
480a4fd5eeeSElza Mathew  * Display zero values by default for xstats
481a4fd5eeeSElza Mathew  */
482a4fd5eeeSElza Mathew uint8_t xstats_hide_zero;
483a4fd5eeeSElza Mathew 
484bc700b67SDharmik Thakkar /*
485bc700b67SDharmik Thakkar  * Measure of CPU cycles disabled by default
486bc700b67SDharmik Thakkar  */
487bc700b67SDharmik Thakkar uint8_t record_core_cycles;
488bc700b67SDharmik Thakkar 
4890e4b1963SDharmik Thakkar /*
4900e4b1963SDharmik Thakkar  * Display of RX and TX bursts disabled by default
4910e4b1963SDharmik Thakkar  */
4920e4b1963SDharmik Thakkar uint8_t record_burst_stats;
4930e4b1963SDharmik Thakkar 
494c9cafcc8SShahaf Shuler unsigned int num_sockets = 0;
495c9cafcc8SShahaf Shuler unsigned int socket_ids[RTE_MAX_NUMA_NODES];
4967acf894dSStephen Hurd 
497a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
4987e4441c8SRemy Horton /* Bitrate statistics */
4997e4441c8SRemy Horton struct rte_stats_bitrates *bitrate_data;
500e25e6c70SRemy Horton lcoreid_t bitrate_lcore_id;
501e25e6c70SRemy Horton uint8_t bitrate_enabled;
502e25e6c70SRemy Horton #endif
5037e4441c8SRemy Horton 
504b40f8d78SJiayu Hu struct gro_status gro_ports[RTE_MAX_ETHPORTS];
505b7091f1dSJiayu Hu uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES;
506b40f8d78SJiayu Hu 
507f9295aa2SXiaoyu Min /*
508f9295aa2SXiaoyu Min  * hexadecimal bitmask of RX mq mode can be enabled.
509f9295aa2SXiaoyu Min  */
510f9295aa2SXiaoyu Min enum rte_eth_rx_mq_mode rx_mq_mode = ETH_MQ_RX_VMDQ_DCB_RSS;
511f9295aa2SXiaoyu Min 
512ed30d9b6SIntel /* Forward function declarations */
513c9cce428SThomas Monjalon static void setup_attached_port(portid_t pi);
514edab33b1STetsuya Mukawa static void check_all_ports_link_status(uint32_t port_mask);
515f8244c63SZhiyong Yang static int eth_event_callback(portid_t port_id,
51676ad4a2dSGaetan Rivet 			      enum rte_eth_event_type type,
517d6af1a13SBernard Iremonger 			      void *param, void *ret_param);
518cc1bf307SJeff Guo static void dev_event_callback(const char *device_name,
519fb73e096SJeff Guo 				enum rte_dev_event_type type,
520fb73e096SJeff Guo 				void *param);
521ce8d5614SIntel 
522ce8d5614SIntel /*
523ce8d5614SIntel  * Check if all the ports are started.
524ce8d5614SIntel  * If yes, return positive value. If not, return zero.
525ce8d5614SIntel  */
526ce8d5614SIntel static int all_ports_started(void);
527ed30d9b6SIntel 
52852f38a20SJiayu Hu struct gso_status gso_ports[RTE_MAX_ETHPORTS];
52935b2d13fSOlivier Matz uint16_t gso_max_segment_size = RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN;
53052f38a20SJiayu Hu 
531b57b66a9SOri Kam /* Holds the registered mbuf dynamic flags names. */
532b57b66a9SOri Kam char dynf_names[64][RTE_MBUF_DYN_NAMESIZE];
533b57b66a9SOri Kam 
534af75078fSIntel /*
53598a7ea33SJerin Jacob  * Helper function to check if socket is already discovered.
536c9cafcc8SShahaf Shuler  * If yes, return positive value. If not, return zero.
537c9cafcc8SShahaf Shuler  */
538c9cafcc8SShahaf Shuler int
539c9cafcc8SShahaf Shuler new_socket_id(unsigned int socket_id)
540c9cafcc8SShahaf Shuler {
541c9cafcc8SShahaf Shuler 	unsigned int i;
542c9cafcc8SShahaf Shuler 
543c9cafcc8SShahaf Shuler 	for (i = 0; i < num_sockets; i++) {
544c9cafcc8SShahaf Shuler 		if (socket_ids[i] == socket_id)
545c9cafcc8SShahaf Shuler 			return 0;
546c9cafcc8SShahaf Shuler 	}
547c9cafcc8SShahaf Shuler 	return 1;
548c9cafcc8SShahaf Shuler }
549c9cafcc8SShahaf Shuler 
550c9cafcc8SShahaf Shuler /*
551af75078fSIntel  * Setup default configuration.
552af75078fSIntel  */
553af75078fSIntel static void
554af75078fSIntel set_default_fwd_lcores_config(void)
555af75078fSIntel {
556af75078fSIntel 	unsigned int i;
557af75078fSIntel 	unsigned int nb_lc;
5587acf894dSStephen Hurd 	unsigned int sock_num;
559af75078fSIntel 
560af75078fSIntel 	nb_lc = 0;
561af75078fSIntel 	for (i = 0; i < RTE_MAX_LCORE; i++) {
562dbfb8ec7SPhil Yang 		if (!rte_lcore_is_enabled(i))
563dbfb8ec7SPhil Yang 			continue;
564c9cafcc8SShahaf Shuler 		sock_num = rte_lcore_to_socket_id(i);
565c9cafcc8SShahaf Shuler 		if (new_socket_id(sock_num)) {
566c9cafcc8SShahaf Shuler 			if (num_sockets >= RTE_MAX_NUMA_NODES) {
567c9cafcc8SShahaf Shuler 				rte_exit(EXIT_FAILURE,
568c9cafcc8SShahaf Shuler 					 "Total sockets greater than %u\n",
569c9cafcc8SShahaf Shuler 					 RTE_MAX_NUMA_NODES);
570c9cafcc8SShahaf Shuler 			}
571c9cafcc8SShahaf Shuler 			socket_ids[num_sockets++] = sock_num;
5727acf894dSStephen Hurd 		}
573cb056611SStephen Hemminger 		if (i == rte_get_main_lcore())
574f54fe5eeSStephen Hurd 			continue;
575f54fe5eeSStephen Hurd 		fwd_lcores_cpuids[nb_lc++] = i;
576af75078fSIntel 	}
577af75078fSIntel 	nb_lcores = (lcoreid_t) nb_lc;
578af75078fSIntel 	nb_cfg_lcores = nb_lcores;
579af75078fSIntel 	nb_fwd_lcores = 1;
580af75078fSIntel }
581af75078fSIntel 
582af75078fSIntel static void
583af75078fSIntel set_def_peer_eth_addrs(void)
584af75078fSIntel {
585af75078fSIntel 	portid_t i;
586af75078fSIntel 
587af75078fSIntel 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
58835b2d13fSOlivier Matz 		peer_eth_addrs[i].addr_bytes[0] = RTE_ETHER_LOCAL_ADMIN_ADDR;
589af75078fSIntel 		peer_eth_addrs[i].addr_bytes[5] = i;
590af75078fSIntel 	}
591af75078fSIntel }
592af75078fSIntel 
593af75078fSIntel static void
594af75078fSIntel set_default_fwd_ports_config(void)
595af75078fSIntel {
596af75078fSIntel 	portid_t pt_id;
59765a7360cSMatan Azrad 	int i = 0;
598af75078fSIntel 
599effdb8bbSPhil Yang 	RTE_ETH_FOREACH_DEV(pt_id) {
60065a7360cSMatan Azrad 		fwd_ports_ids[i++] = pt_id;
601af75078fSIntel 
602effdb8bbSPhil Yang 		/* Update sockets info according to the attached device */
603effdb8bbSPhil Yang 		int socket_id = rte_eth_dev_socket_id(pt_id);
604effdb8bbSPhil Yang 		if (socket_id >= 0 && new_socket_id(socket_id)) {
605effdb8bbSPhil Yang 			if (num_sockets >= RTE_MAX_NUMA_NODES) {
606effdb8bbSPhil Yang 				rte_exit(EXIT_FAILURE,
607effdb8bbSPhil Yang 					 "Total sockets greater than %u\n",
608effdb8bbSPhil Yang 					 RTE_MAX_NUMA_NODES);
609effdb8bbSPhil Yang 			}
610effdb8bbSPhil Yang 			socket_ids[num_sockets++] = socket_id;
611effdb8bbSPhil Yang 		}
612effdb8bbSPhil Yang 	}
613effdb8bbSPhil Yang 
614af75078fSIntel 	nb_cfg_ports = nb_ports;
615af75078fSIntel 	nb_fwd_ports = nb_ports;
616af75078fSIntel }
617af75078fSIntel 
618af75078fSIntel void
619af75078fSIntel set_def_fwd_config(void)
620af75078fSIntel {
621af75078fSIntel 	set_default_fwd_lcores_config();
622af75078fSIntel 	set_def_peer_eth_addrs();
623af75078fSIntel 	set_default_fwd_ports_config();
624af75078fSIntel }
625af75078fSIntel 
626c7f5dba7SAnatoly Burakov /* extremely pessimistic estimation of memory required to create a mempool */
627c7f5dba7SAnatoly Burakov static int
628c7f5dba7SAnatoly Burakov calc_mem_size(uint32_t nb_mbufs, uint32_t mbuf_sz, size_t pgsz, size_t *out)
629c7f5dba7SAnatoly Burakov {
630c7f5dba7SAnatoly Burakov 	unsigned int n_pages, mbuf_per_pg, leftover;
631c7f5dba7SAnatoly Burakov 	uint64_t total_mem, mbuf_mem, obj_sz;
632c7f5dba7SAnatoly Burakov 
633c7f5dba7SAnatoly Burakov 	/* there is no good way to predict how much space the mempool will
634c7f5dba7SAnatoly Burakov 	 * occupy because it will allocate chunks on the fly, and some of those
635c7f5dba7SAnatoly Burakov 	 * will come from default DPDK memory while some will come from our
636c7f5dba7SAnatoly Burakov 	 * external memory, so just assume 128MB will be enough for everyone.
637c7f5dba7SAnatoly Burakov 	 */
638c7f5dba7SAnatoly Burakov 	uint64_t hdr_mem = 128 << 20;
639c7f5dba7SAnatoly Burakov 
640c7f5dba7SAnatoly Burakov 	/* account for possible non-contiguousness */
641c7f5dba7SAnatoly Burakov 	obj_sz = rte_mempool_calc_obj_size(mbuf_sz, 0, NULL);
642c7f5dba7SAnatoly Burakov 	if (obj_sz > pgsz) {
643c7f5dba7SAnatoly Burakov 		TESTPMD_LOG(ERR, "Object size is bigger than page size\n");
644c7f5dba7SAnatoly Burakov 		return -1;
645c7f5dba7SAnatoly Burakov 	}
646c7f5dba7SAnatoly Burakov 
647c7f5dba7SAnatoly Burakov 	mbuf_per_pg = pgsz / obj_sz;
648c7f5dba7SAnatoly Burakov 	leftover = (nb_mbufs % mbuf_per_pg) > 0;
649c7f5dba7SAnatoly Burakov 	n_pages = (nb_mbufs / mbuf_per_pg) + leftover;
650c7f5dba7SAnatoly Burakov 
651c7f5dba7SAnatoly Burakov 	mbuf_mem = n_pages * pgsz;
652c7f5dba7SAnatoly Burakov 
653c7f5dba7SAnatoly Burakov 	total_mem = RTE_ALIGN(hdr_mem + mbuf_mem, pgsz);
654c7f5dba7SAnatoly Burakov 
655c7f5dba7SAnatoly Burakov 	if (total_mem > SIZE_MAX) {
656c7f5dba7SAnatoly Burakov 		TESTPMD_LOG(ERR, "Memory size too big\n");
657c7f5dba7SAnatoly Burakov 		return -1;
658c7f5dba7SAnatoly Burakov 	}
659c7f5dba7SAnatoly Burakov 	*out = (size_t)total_mem;
660c7f5dba7SAnatoly Burakov 
661c7f5dba7SAnatoly Burakov 	return 0;
662c7f5dba7SAnatoly Burakov }
663c7f5dba7SAnatoly Burakov 
664c7f5dba7SAnatoly Burakov static int
665c7f5dba7SAnatoly Burakov pagesz_flags(uint64_t page_sz)
666c7f5dba7SAnatoly Burakov {
667c7f5dba7SAnatoly Burakov 	/* as per mmap() manpage, all page sizes are log2 of page size
668c7f5dba7SAnatoly Burakov 	 * shifted by MAP_HUGE_SHIFT
669c7f5dba7SAnatoly Burakov 	 */
6709d650537SAnatoly Burakov 	int log2 = rte_log2_u64(page_sz);
671c7f5dba7SAnatoly Burakov 
672c7f5dba7SAnatoly Burakov 	return (log2 << HUGE_SHIFT);
673c7f5dba7SAnatoly Burakov }
674c7f5dba7SAnatoly Burakov 
675c7f5dba7SAnatoly Burakov static void *
676c7f5dba7SAnatoly Burakov alloc_mem(size_t memsz, size_t pgsz, bool huge)
677c7f5dba7SAnatoly Burakov {
678c7f5dba7SAnatoly Burakov 	void *addr;
679c7f5dba7SAnatoly Burakov 	int flags;
680c7f5dba7SAnatoly Burakov 
681c7f5dba7SAnatoly Burakov 	/* allocate anonymous hugepages */
682c7f5dba7SAnatoly Burakov 	flags = MAP_ANONYMOUS | MAP_PRIVATE;
683c7f5dba7SAnatoly Burakov 	if (huge)
684c7f5dba7SAnatoly Burakov 		flags |= HUGE_FLAG | pagesz_flags(pgsz);
685c7f5dba7SAnatoly Burakov 
686c7f5dba7SAnatoly Burakov 	addr = mmap(NULL, memsz, PROT_READ | PROT_WRITE, flags, -1, 0);
687c7f5dba7SAnatoly Burakov 	if (addr == MAP_FAILED)
688c7f5dba7SAnatoly Burakov 		return NULL;
689c7f5dba7SAnatoly Burakov 
690c7f5dba7SAnatoly Burakov 	return addr;
691c7f5dba7SAnatoly Burakov }
692c7f5dba7SAnatoly Burakov 
693c7f5dba7SAnatoly Burakov struct extmem_param {
694c7f5dba7SAnatoly Burakov 	void *addr;
695c7f5dba7SAnatoly Burakov 	size_t len;
696c7f5dba7SAnatoly Burakov 	size_t pgsz;
697c7f5dba7SAnatoly Burakov 	rte_iova_t *iova_table;
698c7f5dba7SAnatoly Burakov 	unsigned int iova_table_len;
699c7f5dba7SAnatoly Burakov };
700c7f5dba7SAnatoly Burakov 
701c7f5dba7SAnatoly Burakov static int
702c7f5dba7SAnatoly Burakov create_extmem(uint32_t nb_mbufs, uint32_t mbuf_sz, struct extmem_param *param,
703c7f5dba7SAnatoly Burakov 		bool huge)
704c7f5dba7SAnatoly Burakov {
705c7f5dba7SAnatoly Burakov 	uint64_t pgsizes[] = {RTE_PGSIZE_2M, RTE_PGSIZE_1G, /* x86_64, ARM */
706c7f5dba7SAnatoly Burakov 			RTE_PGSIZE_16M, RTE_PGSIZE_16G};    /* POWER */
707c7f5dba7SAnatoly Burakov 	unsigned int cur_page, n_pages, pgsz_idx;
708c7f5dba7SAnatoly Burakov 	size_t mem_sz, cur_pgsz;
709c7f5dba7SAnatoly Burakov 	rte_iova_t *iovas = NULL;
710c7f5dba7SAnatoly Burakov 	void *addr;
711c7f5dba7SAnatoly Burakov 	int ret;
712c7f5dba7SAnatoly Burakov 
713c7f5dba7SAnatoly Burakov 	for (pgsz_idx = 0; pgsz_idx < RTE_DIM(pgsizes); pgsz_idx++) {
714c7f5dba7SAnatoly Burakov 		/* skip anything that is too big */
715c7f5dba7SAnatoly Burakov 		if (pgsizes[pgsz_idx] > SIZE_MAX)
716c7f5dba7SAnatoly Burakov 			continue;
717c7f5dba7SAnatoly Burakov 
718c7f5dba7SAnatoly Burakov 		cur_pgsz = pgsizes[pgsz_idx];
719c7f5dba7SAnatoly Burakov 
720c7f5dba7SAnatoly Burakov 		/* if we were told not to allocate hugepages, override */
721c7f5dba7SAnatoly Burakov 		if (!huge)
722c7f5dba7SAnatoly Burakov 			cur_pgsz = sysconf(_SC_PAGESIZE);
723c7f5dba7SAnatoly Burakov 
724c7f5dba7SAnatoly Burakov 		ret = calc_mem_size(nb_mbufs, mbuf_sz, cur_pgsz, &mem_sz);
725c7f5dba7SAnatoly Burakov 		if (ret < 0) {
726c7f5dba7SAnatoly Burakov 			TESTPMD_LOG(ERR, "Cannot calculate memory size\n");
727c7f5dba7SAnatoly Burakov 			return -1;
728c7f5dba7SAnatoly Burakov 		}
729c7f5dba7SAnatoly Burakov 
730c7f5dba7SAnatoly Burakov 		/* allocate our memory */
731c7f5dba7SAnatoly Burakov 		addr = alloc_mem(mem_sz, cur_pgsz, huge);
732c7f5dba7SAnatoly Burakov 
733c7f5dba7SAnatoly Burakov 		/* if we couldn't allocate memory with a specified page size,
734c7f5dba7SAnatoly Burakov 		 * that doesn't mean we can't do it with other page sizes, so
735c7f5dba7SAnatoly Burakov 		 * try another one.
736c7f5dba7SAnatoly Burakov 		 */
737c7f5dba7SAnatoly Burakov 		if (addr == NULL)
738c7f5dba7SAnatoly Burakov 			continue;
739c7f5dba7SAnatoly Burakov 
740c7f5dba7SAnatoly Burakov 		/* store IOVA addresses for every page in this memory area */
741c7f5dba7SAnatoly Burakov 		n_pages = mem_sz / cur_pgsz;
742c7f5dba7SAnatoly Burakov 
743c7f5dba7SAnatoly Burakov 		iovas = malloc(sizeof(*iovas) * n_pages);
744c7f5dba7SAnatoly Burakov 
745c7f5dba7SAnatoly Burakov 		if (iovas == NULL) {
746c7f5dba7SAnatoly Burakov 			TESTPMD_LOG(ERR, "Cannot allocate memory for iova addresses\n");
747c7f5dba7SAnatoly Burakov 			goto fail;
748c7f5dba7SAnatoly Burakov 		}
749c7f5dba7SAnatoly Burakov 		/* lock memory if it's not huge pages */
750c7f5dba7SAnatoly Burakov 		if (!huge)
751c7f5dba7SAnatoly Burakov 			mlock(addr, mem_sz);
752c7f5dba7SAnatoly Burakov 
753c7f5dba7SAnatoly Burakov 		/* populate IOVA addresses */
754c7f5dba7SAnatoly Burakov 		for (cur_page = 0; cur_page < n_pages; cur_page++) {
755c7f5dba7SAnatoly Burakov 			rte_iova_t iova;
756c7f5dba7SAnatoly Burakov 			size_t offset;
757c7f5dba7SAnatoly Burakov 			void *cur;
758c7f5dba7SAnatoly Burakov 
759c7f5dba7SAnatoly Burakov 			offset = cur_pgsz * cur_page;
760c7f5dba7SAnatoly Burakov 			cur = RTE_PTR_ADD(addr, offset);
761c7f5dba7SAnatoly Burakov 
762c7f5dba7SAnatoly Burakov 			/* touch the page before getting its IOVA */
763c7f5dba7SAnatoly Burakov 			*(volatile char *)cur = 0;
764c7f5dba7SAnatoly Burakov 
765c7f5dba7SAnatoly Burakov 			iova = rte_mem_virt2iova(cur);
766c7f5dba7SAnatoly Burakov 
767c7f5dba7SAnatoly Burakov 			iovas[cur_page] = iova;
768c7f5dba7SAnatoly Burakov 		}
769c7f5dba7SAnatoly Burakov 
770c7f5dba7SAnatoly Burakov 		break;
771c7f5dba7SAnatoly Burakov 	}
772c7f5dba7SAnatoly Burakov 	/* if we couldn't allocate anything */
773c7f5dba7SAnatoly Burakov 	if (iovas == NULL)
774c7f5dba7SAnatoly Burakov 		return -1;
775c7f5dba7SAnatoly Burakov 
776c7f5dba7SAnatoly Burakov 	param->addr = addr;
777c7f5dba7SAnatoly Burakov 	param->len = mem_sz;
778c7f5dba7SAnatoly Burakov 	param->pgsz = cur_pgsz;
779c7f5dba7SAnatoly Burakov 	param->iova_table = iovas;
780c7f5dba7SAnatoly Burakov 	param->iova_table_len = n_pages;
781c7f5dba7SAnatoly Burakov 
782c7f5dba7SAnatoly Burakov 	return 0;
783c7f5dba7SAnatoly Burakov fail:
784c7f5dba7SAnatoly Burakov 	if (iovas)
785c7f5dba7SAnatoly Burakov 		free(iovas);
786c7f5dba7SAnatoly Burakov 	if (addr)
787c7f5dba7SAnatoly Burakov 		munmap(addr, mem_sz);
788c7f5dba7SAnatoly Burakov 
789c7f5dba7SAnatoly Burakov 	return -1;
790c7f5dba7SAnatoly Burakov }
791c7f5dba7SAnatoly Burakov 
792c7f5dba7SAnatoly Burakov static int
793c7f5dba7SAnatoly Burakov setup_extmem(uint32_t nb_mbufs, uint32_t mbuf_sz, bool huge)
794c7f5dba7SAnatoly Burakov {
795c7f5dba7SAnatoly Burakov 	struct extmem_param param;
796c7f5dba7SAnatoly Burakov 	int socket_id, ret;
797c7f5dba7SAnatoly Burakov 
798c7f5dba7SAnatoly Burakov 	memset(&param, 0, sizeof(param));
799c7f5dba7SAnatoly Burakov 
800c7f5dba7SAnatoly Burakov 	/* check if our heap exists */
801c7f5dba7SAnatoly Burakov 	socket_id = rte_malloc_heap_get_socket(EXTMEM_HEAP_NAME);
802c7f5dba7SAnatoly Burakov 	if (socket_id < 0) {
803c7f5dba7SAnatoly Burakov 		/* create our heap */
804c7f5dba7SAnatoly Burakov 		ret = rte_malloc_heap_create(EXTMEM_HEAP_NAME);
805c7f5dba7SAnatoly Burakov 		if (ret < 0) {
806c7f5dba7SAnatoly Burakov 			TESTPMD_LOG(ERR, "Cannot create heap\n");
807c7f5dba7SAnatoly Burakov 			return -1;
808c7f5dba7SAnatoly Burakov 		}
809c7f5dba7SAnatoly Burakov 	}
810c7f5dba7SAnatoly Burakov 
811c7f5dba7SAnatoly Burakov 	ret = create_extmem(nb_mbufs, mbuf_sz, &param, huge);
812c7f5dba7SAnatoly Burakov 	if (ret < 0) {
813c7f5dba7SAnatoly Burakov 		TESTPMD_LOG(ERR, "Cannot create memory area\n");
814c7f5dba7SAnatoly Burakov 		return -1;
815c7f5dba7SAnatoly Burakov 	}
816c7f5dba7SAnatoly Burakov 
817c7f5dba7SAnatoly Burakov 	/* we now have a valid memory area, so add it to heap */
818c7f5dba7SAnatoly Burakov 	ret = rte_malloc_heap_memory_add(EXTMEM_HEAP_NAME,
819c7f5dba7SAnatoly Burakov 			param.addr, param.len, param.iova_table,
820c7f5dba7SAnatoly Burakov 			param.iova_table_len, param.pgsz);
821c7f5dba7SAnatoly Burakov 
822c7f5dba7SAnatoly Burakov 	/* when using VFIO, memory is automatically mapped for DMA by EAL */
823c7f5dba7SAnatoly Burakov 
824c7f5dba7SAnatoly Burakov 	/* not needed any more */
825c7f5dba7SAnatoly Burakov 	free(param.iova_table);
826c7f5dba7SAnatoly Burakov 
827c7f5dba7SAnatoly Burakov 	if (ret < 0) {
828c7f5dba7SAnatoly Burakov 		TESTPMD_LOG(ERR, "Cannot add memory to heap\n");
829c7f5dba7SAnatoly Burakov 		munmap(param.addr, param.len);
830c7f5dba7SAnatoly Burakov 		return -1;
831c7f5dba7SAnatoly Burakov 	}
832c7f5dba7SAnatoly Burakov 
833c7f5dba7SAnatoly Burakov 	/* success */
834c7f5dba7SAnatoly Burakov 
835c7f5dba7SAnatoly Burakov 	TESTPMD_LOG(DEBUG, "Allocated %zuMB of external memory\n",
836c7f5dba7SAnatoly Burakov 			param.len >> 20);
837c7f5dba7SAnatoly Burakov 
838c7f5dba7SAnatoly Burakov 	return 0;
839c7f5dba7SAnatoly Burakov }
8403a0968c8SShahaf Shuler static void
8413a0968c8SShahaf Shuler dma_unmap_cb(struct rte_mempool *mp __rte_unused, void *opaque __rte_unused,
8423a0968c8SShahaf Shuler 	     struct rte_mempool_memhdr *memhdr, unsigned mem_idx __rte_unused)
8433a0968c8SShahaf Shuler {
8443a0968c8SShahaf Shuler 	uint16_t pid = 0;
8453a0968c8SShahaf Shuler 	int ret;
8463a0968c8SShahaf Shuler 
8473a0968c8SShahaf Shuler 	RTE_ETH_FOREACH_DEV(pid) {
8483a0968c8SShahaf Shuler 		struct rte_eth_dev *dev =
8493a0968c8SShahaf Shuler 			&rte_eth_devices[pid];
8503a0968c8SShahaf Shuler 
8513a0968c8SShahaf Shuler 		ret = rte_dev_dma_unmap(dev->device, memhdr->addr, 0,
8523a0968c8SShahaf Shuler 					memhdr->len);
8533a0968c8SShahaf Shuler 		if (ret) {
8543a0968c8SShahaf Shuler 			TESTPMD_LOG(DEBUG,
8553a0968c8SShahaf Shuler 				    "unable to DMA unmap addr 0x%p "
8563a0968c8SShahaf Shuler 				    "for device %s\n",
8573a0968c8SShahaf Shuler 				    memhdr->addr, dev->data->name);
8583a0968c8SShahaf Shuler 		}
8593a0968c8SShahaf Shuler 	}
8603a0968c8SShahaf Shuler 	ret = rte_extmem_unregister(memhdr->addr, memhdr->len);
8613a0968c8SShahaf Shuler 	if (ret) {
8623a0968c8SShahaf Shuler 		TESTPMD_LOG(DEBUG,
8633a0968c8SShahaf Shuler 			    "unable to un-register addr 0x%p\n", memhdr->addr);
8643a0968c8SShahaf Shuler 	}
8653a0968c8SShahaf Shuler }
8663a0968c8SShahaf Shuler 
8673a0968c8SShahaf Shuler static void
8683a0968c8SShahaf Shuler dma_map_cb(struct rte_mempool *mp __rte_unused, void *opaque __rte_unused,
8693a0968c8SShahaf Shuler 	   struct rte_mempool_memhdr *memhdr, unsigned mem_idx __rte_unused)
8703a0968c8SShahaf Shuler {
8713a0968c8SShahaf Shuler 	uint16_t pid = 0;
8723a0968c8SShahaf Shuler 	size_t page_size = sysconf(_SC_PAGESIZE);
8733a0968c8SShahaf Shuler 	int ret;
8743a0968c8SShahaf Shuler 
8753a0968c8SShahaf Shuler 	ret = rte_extmem_register(memhdr->addr, memhdr->len, NULL, 0,
8763a0968c8SShahaf Shuler 				  page_size);
8773a0968c8SShahaf Shuler 	if (ret) {
8783a0968c8SShahaf Shuler 		TESTPMD_LOG(DEBUG,
8793a0968c8SShahaf Shuler 			    "unable to register addr 0x%p\n", memhdr->addr);
8803a0968c8SShahaf Shuler 		return;
8813a0968c8SShahaf Shuler 	}
8823a0968c8SShahaf Shuler 	RTE_ETH_FOREACH_DEV(pid) {
8833a0968c8SShahaf Shuler 		struct rte_eth_dev *dev =
8843a0968c8SShahaf Shuler 			&rte_eth_devices[pid];
8853a0968c8SShahaf Shuler 
8863a0968c8SShahaf Shuler 		ret = rte_dev_dma_map(dev->device, memhdr->addr, 0,
8873a0968c8SShahaf Shuler 				      memhdr->len);
8883a0968c8SShahaf Shuler 		if (ret) {
8893a0968c8SShahaf Shuler 			TESTPMD_LOG(DEBUG,
8903a0968c8SShahaf Shuler 				    "unable to DMA map addr 0x%p "
8913a0968c8SShahaf Shuler 				    "for device %s\n",
8923a0968c8SShahaf Shuler 				    memhdr->addr, dev->data->name);
8933a0968c8SShahaf Shuler 		}
8943a0968c8SShahaf Shuler 	}
8953a0968c8SShahaf Shuler }
896c7f5dba7SAnatoly Burakov 
89772512e18SViacheslav Ovsiienko static unsigned int
89872512e18SViacheslav Ovsiienko setup_extbuf(uint32_t nb_mbufs, uint16_t mbuf_sz, unsigned int socket_id,
89972512e18SViacheslav Ovsiienko 	    char *pool_name, struct rte_pktmbuf_extmem **ext_mem)
90072512e18SViacheslav Ovsiienko {
90172512e18SViacheslav Ovsiienko 	struct rte_pktmbuf_extmem *xmem;
90272512e18SViacheslav Ovsiienko 	unsigned int ext_num, zone_num, elt_num;
90372512e18SViacheslav Ovsiienko 	uint16_t elt_size;
90472512e18SViacheslav Ovsiienko 
90572512e18SViacheslav Ovsiienko 	elt_size = RTE_ALIGN_CEIL(mbuf_sz, RTE_CACHE_LINE_SIZE);
90672512e18SViacheslav Ovsiienko 	elt_num = EXTBUF_ZONE_SIZE / elt_size;
90772512e18SViacheslav Ovsiienko 	zone_num = (nb_mbufs + elt_num - 1) / elt_num;
90872512e18SViacheslav Ovsiienko 
90972512e18SViacheslav Ovsiienko 	xmem = malloc(sizeof(struct rte_pktmbuf_extmem) * zone_num);
91072512e18SViacheslav Ovsiienko 	if (xmem == NULL) {
91172512e18SViacheslav Ovsiienko 		TESTPMD_LOG(ERR, "Cannot allocate memory for "
91272512e18SViacheslav Ovsiienko 				 "external buffer descriptors\n");
91372512e18SViacheslav Ovsiienko 		*ext_mem = NULL;
91472512e18SViacheslav Ovsiienko 		return 0;
91572512e18SViacheslav Ovsiienko 	}
91672512e18SViacheslav Ovsiienko 	for (ext_num = 0; ext_num < zone_num; ext_num++) {
91772512e18SViacheslav Ovsiienko 		struct rte_pktmbuf_extmem *xseg = xmem + ext_num;
91872512e18SViacheslav Ovsiienko 		const struct rte_memzone *mz;
91972512e18SViacheslav Ovsiienko 		char mz_name[RTE_MEMZONE_NAMESIZE];
92072512e18SViacheslav Ovsiienko 		int ret;
92172512e18SViacheslav Ovsiienko 
92272512e18SViacheslav Ovsiienko 		ret = snprintf(mz_name, sizeof(mz_name),
92372512e18SViacheslav Ovsiienko 			RTE_MEMPOOL_MZ_FORMAT "_xb_%u", pool_name, ext_num);
92472512e18SViacheslav Ovsiienko 		if (ret < 0 || ret >= (int)sizeof(mz_name)) {
92572512e18SViacheslav Ovsiienko 			errno = ENAMETOOLONG;
92672512e18SViacheslav Ovsiienko 			ext_num = 0;
92772512e18SViacheslav Ovsiienko 			break;
92872512e18SViacheslav Ovsiienko 		}
92972512e18SViacheslav Ovsiienko 		mz = rte_memzone_reserve_aligned(mz_name, EXTBUF_ZONE_SIZE,
93072512e18SViacheslav Ovsiienko 						 socket_id,
93172512e18SViacheslav Ovsiienko 						 RTE_MEMZONE_IOVA_CONTIG |
93272512e18SViacheslav Ovsiienko 						 RTE_MEMZONE_1GB |
93372512e18SViacheslav Ovsiienko 						 RTE_MEMZONE_SIZE_HINT_ONLY,
93472512e18SViacheslav Ovsiienko 						 EXTBUF_ZONE_SIZE);
93572512e18SViacheslav Ovsiienko 		if (mz == NULL) {
93672512e18SViacheslav Ovsiienko 			/*
93772512e18SViacheslav Ovsiienko 			 * The caller exits on external buffer creation
93872512e18SViacheslav Ovsiienko 			 * error, so there is no need to free memzones.
93972512e18SViacheslav Ovsiienko 			 */
94072512e18SViacheslav Ovsiienko 			errno = ENOMEM;
94172512e18SViacheslav Ovsiienko 			ext_num = 0;
94272512e18SViacheslav Ovsiienko 			break;
94372512e18SViacheslav Ovsiienko 		}
94472512e18SViacheslav Ovsiienko 		xseg->buf_ptr = mz->addr;
94572512e18SViacheslav Ovsiienko 		xseg->buf_iova = mz->iova;
94672512e18SViacheslav Ovsiienko 		xseg->buf_len = EXTBUF_ZONE_SIZE;
94772512e18SViacheslav Ovsiienko 		xseg->elt_size = elt_size;
94872512e18SViacheslav Ovsiienko 	}
94972512e18SViacheslav Ovsiienko 	if (ext_num == 0 && xmem != NULL) {
95072512e18SViacheslav Ovsiienko 		free(xmem);
95172512e18SViacheslav Ovsiienko 		xmem = NULL;
95272512e18SViacheslav Ovsiienko 	}
95372512e18SViacheslav Ovsiienko 	*ext_mem = xmem;
95472512e18SViacheslav Ovsiienko 	return ext_num;
95572512e18SViacheslav Ovsiienko }
95672512e18SViacheslav Ovsiienko 
957af75078fSIntel /*
958af75078fSIntel  * Configuration initialisation done once at init time.
959af75078fSIntel  */
960401b744dSShahaf Shuler static struct rte_mempool *
961af75078fSIntel mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
96226cbb419SViacheslav Ovsiienko 		 unsigned int socket_id, uint16_t size_idx)
963af75078fSIntel {
964af75078fSIntel 	char pool_name[RTE_MEMPOOL_NAMESIZE];
965bece7b6cSChristian Ehrhardt 	struct rte_mempool *rte_mp = NULL;
966af75078fSIntel 	uint32_t mb_size;
967af75078fSIntel 
968dfb03bbeSOlivier Matz 	mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size;
96926cbb419SViacheslav Ovsiienko 	mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name), size_idx);
970148f963fSBruce Richardson 
971285fd101SOlivier Matz 	TESTPMD_LOG(INFO,
972d1eb542eSOlivier Matz 		"create a new mbuf pool <%s>: n=%u, size=%u, socket=%u\n",
973d1eb542eSOlivier Matz 		pool_name, nb_mbuf, mbuf_seg_size, socket_id);
974d1eb542eSOlivier Matz 
975c7f5dba7SAnatoly Burakov 	switch (mp_alloc_type) {
976c7f5dba7SAnatoly Burakov 	case MP_ALLOC_NATIVE:
977c7f5dba7SAnatoly Burakov 		{
978c7f5dba7SAnatoly Burakov 			/* wrapper to rte_mempool_create() */
979c7f5dba7SAnatoly Burakov 			TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
980c7f5dba7SAnatoly Burakov 					rte_mbuf_best_mempool_ops());
981c7f5dba7SAnatoly Burakov 			rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
982c7f5dba7SAnatoly Burakov 				mb_mempool_cache, 0, mbuf_seg_size, socket_id);
983c7f5dba7SAnatoly Burakov 			break;
984c7f5dba7SAnatoly Burakov 		}
985c7f5dba7SAnatoly Burakov 	case MP_ALLOC_ANON:
986c7f5dba7SAnatoly Burakov 		{
987b19a0c75SOlivier Matz 			rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf,
988c7f5dba7SAnatoly Burakov 				mb_size, (unsigned int) mb_mempool_cache,
989148f963fSBruce Richardson 				sizeof(struct rte_pktmbuf_pool_private),
99059fcf854SShahaf Shuler 				socket_id, mempool_flags);
99124427bb9SOlivier Matz 			if (rte_mp == NULL)
99224427bb9SOlivier Matz 				goto err;
993b19a0c75SOlivier Matz 
994b19a0c75SOlivier Matz 			if (rte_mempool_populate_anon(rte_mp) == 0) {
995b19a0c75SOlivier Matz 				rte_mempool_free(rte_mp);
996b19a0c75SOlivier Matz 				rte_mp = NULL;
99724427bb9SOlivier Matz 				goto err;
998b19a0c75SOlivier Matz 			}
999b19a0c75SOlivier Matz 			rte_pktmbuf_pool_init(rte_mp, NULL);
1000b19a0c75SOlivier Matz 			rte_mempool_obj_iter(rte_mp, rte_pktmbuf_init, NULL);
10013a0968c8SShahaf Shuler 			rte_mempool_mem_iter(rte_mp, dma_map_cb, NULL);
1002c7f5dba7SAnatoly Burakov 			break;
1003c7f5dba7SAnatoly Burakov 		}
1004c7f5dba7SAnatoly Burakov 	case MP_ALLOC_XMEM:
1005c7f5dba7SAnatoly Burakov 	case MP_ALLOC_XMEM_HUGE:
1006c7f5dba7SAnatoly Burakov 		{
1007c7f5dba7SAnatoly Burakov 			int heap_socket;
1008c7f5dba7SAnatoly Burakov 			bool huge = mp_alloc_type == MP_ALLOC_XMEM_HUGE;
1009c7f5dba7SAnatoly Burakov 
1010c7f5dba7SAnatoly Burakov 			if (setup_extmem(nb_mbuf, mbuf_seg_size, huge) < 0)
1011c7f5dba7SAnatoly Burakov 				rte_exit(EXIT_FAILURE, "Could not create external memory\n");
1012c7f5dba7SAnatoly Burakov 
1013c7f5dba7SAnatoly Burakov 			heap_socket =
1014c7f5dba7SAnatoly Burakov 				rte_malloc_heap_get_socket(EXTMEM_HEAP_NAME);
1015c7f5dba7SAnatoly Burakov 			if (heap_socket < 0)
1016c7f5dba7SAnatoly Burakov 				rte_exit(EXIT_FAILURE, "Could not get external memory socket ID\n");
1017c7f5dba7SAnatoly Burakov 
10180e798567SPavan Nikhilesh 			TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
10190e798567SPavan Nikhilesh 					rte_mbuf_best_mempool_ops());
1020ea0c20eaSOlivier Matz 			rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
1021c7f5dba7SAnatoly Burakov 					mb_mempool_cache, 0, mbuf_seg_size,
1022c7f5dba7SAnatoly Burakov 					heap_socket);
1023c7f5dba7SAnatoly Burakov 			break;
1024c7f5dba7SAnatoly Burakov 		}
102572512e18SViacheslav Ovsiienko 	case MP_ALLOC_XBUF:
102672512e18SViacheslav Ovsiienko 		{
102772512e18SViacheslav Ovsiienko 			struct rte_pktmbuf_extmem *ext_mem;
102872512e18SViacheslav Ovsiienko 			unsigned int ext_num;
102972512e18SViacheslav Ovsiienko 
103072512e18SViacheslav Ovsiienko 			ext_num = setup_extbuf(nb_mbuf,	mbuf_seg_size,
103172512e18SViacheslav Ovsiienko 					       socket_id, pool_name, &ext_mem);
103272512e18SViacheslav Ovsiienko 			if (ext_num == 0)
103372512e18SViacheslav Ovsiienko 				rte_exit(EXIT_FAILURE,
103472512e18SViacheslav Ovsiienko 					 "Can't create pinned data buffers\n");
103572512e18SViacheslav Ovsiienko 
103672512e18SViacheslav Ovsiienko 			TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
103772512e18SViacheslav Ovsiienko 					rte_mbuf_best_mempool_ops());
103872512e18SViacheslav Ovsiienko 			rte_mp = rte_pktmbuf_pool_create_extbuf
103972512e18SViacheslav Ovsiienko 					(pool_name, nb_mbuf, mb_mempool_cache,
104072512e18SViacheslav Ovsiienko 					 0, mbuf_seg_size, socket_id,
104172512e18SViacheslav Ovsiienko 					 ext_mem, ext_num);
104272512e18SViacheslav Ovsiienko 			free(ext_mem);
104372512e18SViacheslav Ovsiienko 			break;
104472512e18SViacheslav Ovsiienko 		}
1045c7f5dba7SAnatoly Burakov 	default:
1046c7f5dba7SAnatoly Burakov 		{
1047c7f5dba7SAnatoly Burakov 			rte_exit(EXIT_FAILURE, "Invalid mempool creation mode\n");
1048c7f5dba7SAnatoly Burakov 		}
1049bece7b6cSChristian Ehrhardt 	}
1050148f963fSBruce Richardson 
105124427bb9SOlivier Matz err:
1052af75078fSIntel 	if (rte_mp == NULL) {
1053d1eb542eSOlivier Matz 		rte_exit(EXIT_FAILURE,
1054d1eb542eSOlivier Matz 			"Creation of mbuf pool for socket %u failed: %s\n",
1055d1eb542eSOlivier Matz 			socket_id, rte_strerror(rte_errno));
1056148f963fSBruce Richardson 	} else if (verbose_level > 0) {
1057591a9d79SStephen Hemminger 		rte_mempool_dump(stdout, rte_mp);
1058af75078fSIntel 	}
1059401b744dSShahaf Shuler 	return rte_mp;
1060af75078fSIntel }
1061af75078fSIntel 
106220a0286fSLiu Xiaofeng /*
106320a0286fSLiu Xiaofeng  * Check given socket id is valid or not with NUMA mode,
106420a0286fSLiu Xiaofeng  * if valid, return 0, else return -1
106520a0286fSLiu Xiaofeng  */
106620a0286fSLiu Xiaofeng static int
106720a0286fSLiu Xiaofeng check_socket_id(const unsigned int socket_id)
106820a0286fSLiu Xiaofeng {
106920a0286fSLiu Xiaofeng 	static int warning_once = 0;
107020a0286fSLiu Xiaofeng 
1071c9cafcc8SShahaf Shuler 	if (new_socket_id(socket_id)) {
107220a0286fSLiu Xiaofeng 		if (!warning_once && numa_support)
107320a0286fSLiu Xiaofeng 			printf("Warning: NUMA should be configured manually by"
107420a0286fSLiu Xiaofeng 			       " using --port-numa-config and"
107520a0286fSLiu Xiaofeng 			       " --ring-numa-config parameters along with"
107620a0286fSLiu Xiaofeng 			       " --numa.\n");
107720a0286fSLiu Xiaofeng 		warning_once = 1;
107820a0286fSLiu Xiaofeng 		return -1;
107920a0286fSLiu Xiaofeng 	}
108020a0286fSLiu Xiaofeng 	return 0;
108120a0286fSLiu Xiaofeng }
108220a0286fSLiu Xiaofeng 
10833f7311baSWei Dai /*
10843f7311baSWei Dai  * Get the allowed maximum number of RX queues.
10853f7311baSWei Dai  * *pid return the port id which has minimal value of
10863f7311baSWei Dai  * max_rx_queues in all ports.
10873f7311baSWei Dai  */
10883f7311baSWei Dai queueid_t
10893f7311baSWei Dai get_allowed_max_nb_rxq(portid_t *pid)
10903f7311baSWei Dai {
10919e6b36c3SDavid Marchand 	queueid_t allowed_max_rxq = RTE_MAX_QUEUES_PER_PORT;
10926f51deb9SIvan Ilchenko 	bool max_rxq_valid = false;
10933f7311baSWei Dai 	portid_t pi;
10943f7311baSWei Dai 	struct rte_eth_dev_info dev_info;
10953f7311baSWei Dai 
10963f7311baSWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
10976f51deb9SIvan Ilchenko 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
10986f51deb9SIvan Ilchenko 			continue;
10996f51deb9SIvan Ilchenko 
11006f51deb9SIvan Ilchenko 		max_rxq_valid = true;
11013f7311baSWei Dai 		if (dev_info.max_rx_queues < allowed_max_rxq) {
11023f7311baSWei Dai 			allowed_max_rxq = dev_info.max_rx_queues;
11033f7311baSWei Dai 			*pid = pi;
11043f7311baSWei Dai 		}
11053f7311baSWei Dai 	}
11066f51deb9SIvan Ilchenko 	return max_rxq_valid ? allowed_max_rxq : 0;
11073f7311baSWei Dai }
11083f7311baSWei Dai 
11093f7311baSWei Dai /*
11103f7311baSWei Dai  * Check input rxq is valid or not.
11113f7311baSWei Dai  * If input rxq is not greater than any of maximum number
11123f7311baSWei Dai  * of RX queues of all ports, it is valid.
11133f7311baSWei Dai  * if valid, return 0, else return -1
11143f7311baSWei Dai  */
11153f7311baSWei Dai int
11163f7311baSWei Dai check_nb_rxq(queueid_t rxq)
11173f7311baSWei Dai {
11183f7311baSWei Dai 	queueid_t allowed_max_rxq;
11193f7311baSWei Dai 	portid_t pid = 0;
11203f7311baSWei Dai 
11213f7311baSWei Dai 	allowed_max_rxq = get_allowed_max_nb_rxq(&pid);
11223f7311baSWei Dai 	if (rxq > allowed_max_rxq) {
11233f7311baSWei Dai 		printf("Fail: input rxq (%u) can't be greater "
11243f7311baSWei Dai 		       "than max_rx_queues (%u) of port %u\n",
11253f7311baSWei Dai 		       rxq,
11263f7311baSWei Dai 		       allowed_max_rxq,
11273f7311baSWei Dai 		       pid);
11283f7311baSWei Dai 		return -1;
11293f7311baSWei Dai 	}
11303f7311baSWei Dai 	return 0;
11313f7311baSWei Dai }
11323f7311baSWei Dai 
113336db4f6cSWei Dai /*
113436db4f6cSWei Dai  * Get the allowed maximum number of TX queues.
113536db4f6cSWei Dai  * *pid return the port id which has minimal value of
113636db4f6cSWei Dai  * max_tx_queues in all ports.
113736db4f6cSWei Dai  */
113836db4f6cSWei Dai queueid_t
113936db4f6cSWei Dai get_allowed_max_nb_txq(portid_t *pid)
114036db4f6cSWei Dai {
11419e6b36c3SDavid Marchand 	queueid_t allowed_max_txq = RTE_MAX_QUEUES_PER_PORT;
11426f51deb9SIvan Ilchenko 	bool max_txq_valid = false;
114336db4f6cSWei Dai 	portid_t pi;
114436db4f6cSWei Dai 	struct rte_eth_dev_info dev_info;
114536db4f6cSWei Dai 
114636db4f6cSWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
11476f51deb9SIvan Ilchenko 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
11486f51deb9SIvan Ilchenko 			continue;
11496f51deb9SIvan Ilchenko 
11506f51deb9SIvan Ilchenko 		max_txq_valid = true;
115136db4f6cSWei Dai 		if (dev_info.max_tx_queues < allowed_max_txq) {
115236db4f6cSWei Dai 			allowed_max_txq = dev_info.max_tx_queues;
115336db4f6cSWei Dai 			*pid = pi;
115436db4f6cSWei Dai 		}
115536db4f6cSWei Dai 	}
11566f51deb9SIvan Ilchenko 	return max_txq_valid ? allowed_max_txq : 0;
115736db4f6cSWei Dai }
115836db4f6cSWei Dai 
115936db4f6cSWei Dai /*
116036db4f6cSWei Dai  * Check input txq is valid or not.
116136db4f6cSWei Dai  * If input txq is not greater than any of maximum number
116236db4f6cSWei Dai  * of TX queues of all ports, it is valid.
116336db4f6cSWei Dai  * if valid, return 0, else return -1
116436db4f6cSWei Dai  */
116536db4f6cSWei Dai int
116636db4f6cSWei Dai check_nb_txq(queueid_t txq)
116736db4f6cSWei Dai {
116836db4f6cSWei Dai 	queueid_t allowed_max_txq;
116936db4f6cSWei Dai 	portid_t pid = 0;
117036db4f6cSWei Dai 
117136db4f6cSWei Dai 	allowed_max_txq = get_allowed_max_nb_txq(&pid);
117236db4f6cSWei Dai 	if (txq > allowed_max_txq) {
117336db4f6cSWei Dai 		printf("Fail: input txq (%u) can't be greater "
117436db4f6cSWei Dai 		       "than max_tx_queues (%u) of port %u\n",
117536db4f6cSWei Dai 		       txq,
117636db4f6cSWei Dai 		       allowed_max_txq,
117736db4f6cSWei Dai 		       pid);
117836db4f6cSWei Dai 		return -1;
117936db4f6cSWei Dai 	}
118036db4f6cSWei Dai 	return 0;
118136db4f6cSWei Dai }
118236db4f6cSWei Dai 
11831c69df45SOri Kam /*
118499e040d3SLijun Ou  * Get the allowed maximum number of RXDs of every rx queue.
118599e040d3SLijun Ou  * *pid return the port id which has minimal value of
118699e040d3SLijun Ou  * max_rxd in all queues of all ports.
118799e040d3SLijun Ou  */
118899e040d3SLijun Ou static uint16_t
118999e040d3SLijun Ou get_allowed_max_nb_rxd(portid_t *pid)
119099e040d3SLijun Ou {
119199e040d3SLijun Ou 	uint16_t allowed_max_rxd = UINT16_MAX;
119299e040d3SLijun Ou 	portid_t pi;
119399e040d3SLijun Ou 	struct rte_eth_dev_info dev_info;
119499e040d3SLijun Ou 
119599e040d3SLijun Ou 	RTE_ETH_FOREACH_DEV(pi) {
119699e040d3SLijun Ou 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
119799e040d3SLijun Ou 			continue;
119899e040d3SLijun Ou 
119999e040d3SLijun Ou 		if (dev_info.rx_desc_lim.nb_max < allowed_max_rxd) {
120099e040d3SLijun Ou 			allowed_max_rxd = dev_info.rx_desc_lim.nb_max;
120199e040d3SLijun Ou 			*pid = pi;
120299e040d3SLijun Ou 		}
120399e040d3SLijun Ou 	}
120499e040d3SLijun Ou 	return allowed_max_rxd;
120599e040d3SLijun Ou }
120699e040d3SLijun Ou 
120799e040d3SLijun Ou /*
120899e040d3SLijun Ou  * Get the allowed minimal number of RXDs of every rx queue.
120999e040d3SLijun Ou  * *pid return the port id which has minimal value of
121099e040d3SLijun Ou  * min_rxd in all queues of all ports.
121199e040d3SLijun Ou  */
121299e040d3SLijun Ou static uint16_t
121399e040d3SLijun Ou get_allowed_min_nb_rxd(portid_t *pid)
121499e040d3SLijun Ou {
121599e040d3SLijun Ou 	uint16_t allowed_min_rxd = 0;
121699e040d3SLijun Ou 	portid_t pi;
121799e040d3SLijun Ou 	struct rte_eth_dev_info dev_info;
121899e040d3SLijun Ou 
121999e040d3SLijun Ou 	RTE_ETH_FOREACH_DEV(pi) {
122099e040d3SLijun Ou 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
122199e040d3SLijun Ou 			continue;
122299e040d3SLijun Ou 
122399e040d3SLijun Ou 		if (dev_info.rx_desc_lim.nb_min > allowed_min_rxd) {
122499e040d3SLijun Ou 			allowed_min_rxd = dev_info.rx_desc_lim.nb_min;
122599e040d3SLijun Ou 			*pid = pi;
122699e040d3SLijun Ou 		}
122799e040d3SLijun Ou 	}
122899e040d3SLijun Ou 
122999e040d3SLijun Ou 	return allowed_min_rxd;
123099e040d3SLijun Ou }
123199e040d3SLijun Ou 
123299e040d3SLijun Ou /*
123399e040d3SLijun Ou  * Check input rxd is valid or not.
123499e040d3SLijun Ou  * If input rxd is not greater than any of maximum number
123599e040d3SLijun Ou  * of RXDs of every Rx queues and is not less than any of
123699e040d3SLijun Ou  * minimal number of RXDs of every Rx queues, it is valid.
123799e040d3SLijun Ou  * if valid, return 0, else return -1
123899e040d3SLijun Ou  */
123999e040d3SLijun Ou int
124099e040d3SLijun Ou check_nb_rxd(queueid_t rxd)
124199e040d3SLijun Ou {
124299e040d3SLijun Ou 	uint16_t allowed_max_rxd;
124399e040d3SLijun Ou 	uint16_t allowed_min_rxd;
124499e040d3SLijun Ou 	portid_t pid = 0;
124599e040d3SLijun Ou 
124699e040d3SLijun Ou 	allowed_max_rxd = get_allowed_max_nb_rxd(&pid);
124799e040d3SLijun Ou 	if (rxd > allowed_max_rxd) {
124899e040d3SLijun Ou 		printf("Fail: input rxd (%u) can't be greater "
124999e040d3SLijun Ou 		       "than max_rxds (%u) of port %u\n",
125099e040d3SLijun Ou 		       rxd,
125199e040d3SLijun Ou 		       allowed_max_rxd,
125299e040d3SLijun Ou 		       pid);
125399e040d3SLijun Ou 		return -1;
125499e040d3SLijun Ou 	}
125599e040d3SLijun Ou 
125699e040d3SLijun Ou 	allowed_min_rxd = get_allowed_min_nb_rxd(&pid);
125799e040d3SLijun Ou 	if (rxd < allowed_min_rxd) {
125899e040d3SLijun Ou 		printf("Fail: input rxd (%u) can't be less "
125999e040d3SLijun Ou 		       "than min_rxds (%u) of port %u\n",
126099e040d3SLijun Ou 		       rxd,
126199e040d3SLijun Ou 		       allowed_min_rxd,
126299e040d3SLijun Ou 		       pid);
126399e040d3SLijun Ou 		return -1;
126499e040d3SLijun Ou 	}
126599e040d3SLijun Ou 
126699e040d3SLijun Ou 	return 0;
126799e040d3SLijun Ou }
126899e040d3SLijun Ou 
126999e040d3SLijun Ou /*
127099e040d3SLijun Ou  * Get the allowed maximum number of TXDs of every rx queues.
127199e040d3SLijun Ou  * *pid return the port id which has minimal value of
127299e040d3SLijun Ou  * max_txd in every tx queue.
127399e040d3SLijun Ou  */
127499e040d3SLijun Ou static uint16_t
127599e040d3SLijun Ou get_allowed_max_nb_txd(portid_t *pid)
127699e040d3SLijun Ou {
127799e040d3SLijun Ou 	uint16_t allowed_max_txd = UINT16_MAX;
127899e040d3SLijun Ou 	portid_t pi;
127999e040d3SLijun Ou 	struct rte_eth_dev_info dev_info;
128099e040d3SLijun Ou 
128199e040d3SLijun Ou 	RTE_ETH_FOREACH_DEV(pi) {
128299e040d3SLijun Ou 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
128399e040d3SLijun Ou 			continue;
128499e040d3SLijun Ou 
128599e040d3SLijun Ou 		if (dev_info.tx_desc_lim.nb_max < allowed_max_txd) {
128699e040d3SLijun Ou 			allowed_max_txd = dev_info.tx_desc_lim.nb_max;
128799e040d3SLijun Ou 			*pid = pi;
128899e040d3SLijun Ou 		}
128999e040d3SLijun Ou 	}
129099e040d3SLijun Ou 	return allowed_max_txd;
129199e040d3SLijun Ou }
129299e040d3SLijun Ou 
129399e040d3SLijun Ou /*
129499e040d3SLijun Ou  * Get the allowed maximum number of TXDs of every tx queues.
129599e040d3SLijun Ou  * *pid return the port id which has minimal value of
129699e040d3SLijun Ou  * min_txd in every tx queue.
129799e040d3SLijun Ou  */
129899e040d3SLijun Ou static uint16_t
129999e040d3SLijun Ou get_allowed_min_nb_txd(portid_t *pid)
130099e040d3SLijun Ou {
130199e040d3SLijun Ou 	uint16_t allowed_min_txd = 0;
130299e040d3SLijun Ou 	portid_t pi;
130399e040d3SLijun Ou 	struct rte_eth_dev_info dev_info;
130499e040d3SLijun Ou 
130599e040d3SLijun Ou 	RTE_ETH_FOREACH_DEV(pi) {
130699e040d3SLijun Ou 		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
130799e040d3SLijun Ou 			continue;
130899e040d3SLijun Ou 
130999e040d3SLijun Ou 		if (dev_info.tx_desc_lim.nb_min > allowed_min_txd) {
131099e040d3SLijun Ou 			allowed_min_txd = dev_info.tx_desc_lim.nb_min;
131199e040d3SLijun Ou 			*pid = pi;
131299e040d3SLijun Ou 		}
131399e040d3SLijun Ou 	}
131499e040d3SLijun Ou 
131599e040d3SLijun Ou 	return allowed_min_txd;
131699e040d3SLijun Ou }
131799e040d3SLijun Ou 
131899e040d3SLijun Ou /*
131999e040d3SLijun Ou  * Check input txd is valid or not.
132099e040d3SLijun Ou  * If input txd is not greater than any of maximum number
132199e040d3SLijun Ou  * of TXDs of every Rx queues, it is valid.
132299e040d3SLijun Ou  * if valid, return 0, else return -1
132399e040d3SLijun Ou  */
132499e040d3SLijun Ou int
132599e040d3SLijun Ou check_nb_txd(queueid_t txd)
132699e040d3SLijun Ou {
132799e040d3SLijun Ou 	uint16_t allowed_max_txd;
132899e040d3SLijun Ou 	uint16_t allowed_min_txd;
132999e040d3SLijun Ou 	portid_t pid = 0;
133099e040d3SLijun Ou 
133199e040d3SLijun Ou 	allowed_max_txd = get_allowed_max_nb_txd(&pid);
133299e040d3SLijun Ou 	if (txd > allowed_max_txd) {
133399e040d3SLijun Ou 		printf("Fail: input txd (%u) can't be greater "
133499e040d3SLijun Ou 		       "than max_txds (%u) of port %u\n",
133599e040d3SLijun Ou 		       txd,
133699e040d3SLijun Ou 		       allowed_max_txd,
133799e040d3SLijun Ou 		       pid);
133899e040d3SLijun Ou 		return -1;
133999e040d3SLijun Ou 	}
134099e040d3SLijun Ou 
134199e040d3SLijun Ou 	allowed_min_txd = get_allowed_min_nb_txd(&pid);
134299e040d3SLijun Ou 	if (txd < allowed_min_txd) {
134399e040d3SLijun Ou 		printf("Fail: input txd (%u) can't be less "
134499e040d3SLijun Ou 		       "than min_txds (%u) of port %u\n",
134599e040d3SLijun Ou 		       txd,
134699e040d3SLijun Ou 		       allowed_min_txd,
134799e040d3SLijun Ou 		       pid);
134899e040d3SLijun Ou 		return -1;
134999e040d3SLijun Ou 	}
135099e040d3SLijun Ou 	return 0;
135199e040d3SLijun Ou }
135299e040d3SLijun Ou 
135399e040d3SLijun Ou 
135499e040d3SLijun Ou /*
13551c69df45SOri Kam  * Get the allowed maximum number of hairpin queues.
13561c69df45SOri Kam  * *pid return the port id which has minimal value of
13571c69df45SOri Kam  * max_hairpin_queues in all ports.
13581c69df45SOri Kam  */
13591c69df45SOri Kam queueid_t
13601c69df45SOri Kam get_allowed_max_nb_hairpinq(portid_t *pid)
13611c69df45SOri Kam {
13629e6b36c3SDavid Marchand 	queueid_t allowed_max_hairpinq = RTE_MAX_QUEUES_PER_PORT;
13631c69df45SOri Kam 	portid_t pi;
13641c69df45SOri Kam 	struct rte_eth_hairpin_cap cap;
13651c69df45SOri Kam 
13661c69df45SOri Kam 	RTE_ETH_FOREACH_DEV(pi) {
13671c69df45SOri Kam 		if (rte_eth_dev_hairpin_capability_get(pi, &cap) != 0) {
13681c69df45SOri Kam 			*pid = pi;
13691c69df45SOri Kam 			return 0;
13701c69df45SOri Kam 		}
13711c69df45SOri Kam 		if (cap.max_nb_queues < allowed_max_hairpinq) {
13721c69df45SOri Kam 			allowed_max_hairpinq = cap.max_nb_queues;
13731c69df45SOri Kam 			*pid = pi;
13741c69df45SOri Kam 		}
13751c69df45SOri Kam 	}
13761c69df45SOri Kam 	return allowed_max_hairpinq;
13771c69df45SOri Kam }
13781c69df45SOri Kam 
13791c69df45SOri Kam /*
13801c69df45SOri Kam  * Check input hairpin is valid or not.
13811c69df45SOri Kam  * If input hairpin is not greater than any of maximum number
13821c69df45SOri Kam  * of hairpin queues of all ports, it is valid.
13831c69df45SOri Kam  * if valid, return 0, else return -1
13841c69df45SOri Kam  */
13851c69df45SOri Kam int
13861c69df45SOri Kam check_nb_hairpinq(queueid_t hairpinq)
13871c69df45SOri Kam {
13881c69df45SOri Kam 	queueid_t allowed_max_hairpinq;
13891c69df45SOri Kam 	portid_t pid = 0;
13901c69df45SOri Kam 
13911c69df45SOri Kam 	allowed_max_hairpinq = get_allowed_max_nb_hairpinq(&pid);
13921c69df45SOri Kam 	if (hairpinq > allowed_max_hairpinq) {
13931c69df45SOri Kam 		printf("Fail: input hairpin (%u) can't be greater "
13941c69df45SOri Kam 		       "than max_hairpin_queues (%u) of port %u\n",
13951c69df45SOri Kam 		       hairpinq, allowed_max_hairpinq, pid);
13961c69df45SOri Kam 		return -1;
13971c69df45SOri Kam 	}
13981c69df45SOri Kam 	return 0;
13991c69df45SOri Kam }
14001c69df45SOri Kam 
1401af75078fSIntel static void
1402af75078fSIntel init_config(void)
1403af75078fSIntel {
1404ce8d5614SIntel 	portid_t pid;
1405af75078fSIntel 	struct rte_port *port;
1406af75078fSIntel 	struct rte_mempool *mbp;
1407af75078fSIntel 	unsigned int nb_mbuf_per_pool;
1408af75078fSIntel 	lcoreid_t  lc_id;
14097acf894dSStephen Hurd 	uint8_t port_per_socket[RTE_MAX_NUMA_NODES];
1410b7091f1dSJiayu Hu 	struct rte_gro_param gro_param;
141152f38a20SJiayu Hu 	uint32_t gso_types;
141233f9630fSSunil Kumar Kori 	uint16_t data_size;
141333f9630fSSunil Kumar Kori 	bool warning = 0;
1414c73a9071SWei Dai 	int k;
14156f51deb9SIvan Ilchenko 	int ret;
1416af75078fSIntel 
14177acf894dSStephen Hurd 	memset(port_per_socket,0,RTE_MAX_NUMA_NODES);
1418487f9a59SYulong Pei 
1419af75078fSIntel 	/* Configuration of logical cores. */
1420af75078fSIntel 	fwd_lcores = rte_zmalloc("testpmd: fwd_lcores",
1421af75078fSIntel 				sizeof(struct fwd_lcore *) * nb_lcores,
1422fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
1423af75078fSIntel 	if (fwd_lcores == NULL) {
1424ce8d5614SIntel 		rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) "
1425ce8d5614SIntel 							"failed\n", nb_lcores);
1426af75078fSIntel 	}
1427af75078fSIntel 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
1428af75078fSIntel 		fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore",
1429af75078fSIntel 					       sizeof(struct fwd_lcore),
1430fdf20fa7SSergio Gonzalez Monroy 					       RTE_CACHE_LINE_SIZE);
1431af75078fSIntel 		if (fwd_lcores[lc_id] == NULL) {
1432ce8d5614SIntel 			rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) "
1433ce8d5614SIntel 								"failed\n");
1434af75078fSIntel 		}
1435af75078fSIntel 		fwd_lcores[lc_id]->cpuid_idx = lc_id;
1436af75078fSIntel 	}
1437af75078fSIntel 
14387d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
1439ce8d5614SIntel 		port = &ports[pid];
14408b9bd0efSMoti Haimovsky 		/* Apply default TxRx configuration for all ports */
1441fd8c20aaSShahaf Shuler 		port->dev_conf.txmode = tx_mode;
1442384161e0SShahaf Shuler 		port->dev_conf.rxmode = rx_mode;
14436f51deb9SIvan Ilchenko 
14446f51deb9SIvan Ilchenko 		ret = eth_dev_info_get_print_err(pid, &port->dev_info);
14456f51deb9SIvan Ilchenko 		if (ret != 0)
14466f51deb9SIvan Ilchenko 			rte_exit(EXIT_FAILURE,
14476f51deb9SIvan Ilchenko 				 "rte_eth_dev_info_get() failed\n");
14487c45f6c0SFerruh Yigit 
144907e5f7bdSShahaf Shuler 		if (!(port->dev_info.tx_offload_capa &
145007e5f7bdSShahaf Shuler 		      DEV_TX_OFFLOAD_MBUF_FAST_FREE))
145107e5f7bdSShahaf Shuler 			port->dev_conf.txmode.offloads &=
145207e5f7bdSShahaf Shuler 				~DEV_TX_OFFLOAD_MBUF_FAST_FREE;
1453b6ea6408SIntel 		if (numa_support) {
1454b6ea6408SIntel 			if (port_numa[pid] != NUMA_NO_CONFIG)
1455b6ea6408SIntel 				port_per_socket[port_numa[pid]]++;
1456b6ea6408SIntel 			else {
1457b6ea6408SIntel 				uint32_t socket_id = rte_eth_dev_socket_id(pid);
145820a0286fSLiu Xiaofeng 
145929841336SPhil Yang 				/*
146029841336SPhil Yang 				 * if socket_id is invalid,
146129841336SPhil Yang 				 * set to the first available socket.
146229841336SPhil Yang 				 */
146320a0286fSLiu Xiaofeng 				if (check_socket_id(socket_id) < 0)
146429841336SPhil Yang 					socket_id = socket_ids[0];
1465b6ea6408SIntel 				port_per_socket[socket_id]++;
1466b6ea6408SIntel 			}
1467b6ea6408SIntel 		}
1468b6ea6408SIntel 
1469c73a9071SWei Dai 		/* Apply Rx offloads configuration */
1470c73a9071SWei Dai 		for (k = 0; k < port->dev_info.max_rx_queues; k++)
1471c73a9071SWei Dai 			port->rx_conf[k].offloads =
1472c73a9071SWei Dai 				port->dev_conf.rxmode.offloads;
1473c73a9071SWei Dai 		/* Apply Tx offloads configuration */
1474c73a9071SWei Dai 		for (k = 0; k < port->dev_info.max_tx_queues; k++)
1475c73a9071SWei Dai 			port->tx_conf[k].offloads =
1476c73a9071SWei Dai 				port->dev_conf.txmode.offloads;
1477c73a9071SWei Dai 
1478ce8d5614SIntel 		/* set flag to initialize port/queue */
1479ce8d5614SIntel 		port->need_reconfig = 1;
1480ce8d5614SIntel 		port->need_reconfig_queues = 1;
1481c18feafaSDekel Peled 		port->tx_metadata = 0;
148233f9630fSSunil Kumar Kori 
148333f9630fSSunil Kumar Kori 		/* Check for maximum number of segments per MTU. Accordingly
148433f9630fSSunil Kumar Kori 		 * update the mbuf data size.
148533f9630fSSunil Kumar Kori 		 */
1486163fbaafSFerruh Yigit 		if (port->dev_info.rx_desc_lim.nb_mtu_seg_max != UINT16_MAX &&
1487163fbaafSFerruh Yigit 				port->dev_info.rx_desc_lim.nb_mtu_seg_max != 0) {
148833f9630fSSunil Kumar Kori 			data_size = rx_mode.max_rx_pkt_len /
148933f9630fSSunil Kumar Kori 				port->dev_info.rx_desc_lim.nb_mtu_seg_max;
149033f9630fSSunil Kumar Kori 
149133f9630fSSunil Kumar Kori 			if ((data_size + RTE_PKTMBUF_HEADROOM) >
149226cbb419SViacheslav Ovsiienko 							mbuf_data_size[0]) {
149326cbb419SViacheslav Ovsiienko 				mbuf_data_size[0] = data_size +
149433f9630fSSunil Kumar Kori 						 RTE_PKTMBUF_HEADROOM;
149533f9630fSSunil Kumar Kori 				warning = 1;
1496ce8d5614SIntel 			}
149733f9630fSSunil Kumar Kori 		}
149833f9630fSSunil Kumar Kori 	}
149933f9630fSSunil Kumar Kori 
150033f9630fSSunil Kumar Kori 	if (warning)
150126cbb419SViacheslav Ovsiienko 		TESTPMD_LOG(WARNING,
150226cbb419SViacheslav Ovsiienko 			    "Configured mbuf size of the first segment %hu\n",
150326cbb419SViacheslav Ovsiienko 			    mbuf_data_size[0]);
15043ab64341SOlivier Matz 	/*
15053ab64341SOlivier Matz 	 * Create pools of mbuf.
15063ab64341SOlivier Matz 	 * If NUMA support is disabled, create a single pool of mbuf in
15073ab64341SOlivier Matz 	 * socket 0 memory by default.
15083ab64341SOlivier Matz 	 * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1.
15093ab64341SOlivier Matz 	 *
15103ab64341SOlivier Matz 	 * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and
15113ab64341SOlivier Matz 	 * nb_txd can be configured at run time.
15123ab64341SOlivier Matz 	 */
15133ab64341SOlivier Matz 	if (param_total_num_mbufs)
15143ab64341SOlivier Matz 		nb_mbuf_per_pool = param_total_num_mbufs;
15153ab64341SOlivier Matz 	else {
15163ab64341SOlivier Matz 		nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX +
15173ab64341SOlivier Matz 			(nb_lcores * mb_mempool_cache) +
15183ab64341SOlivier Matz 			RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
15193ab64341SOlivier Matz 		nb_mbuf_per_pool *= RTE_MAX_ETHPORTS;
15203ab64341SOlivier Matz 	}
15213ab64341SOlivier Matz 
1522b6ea6408SIntel 	if (numa_support) {
152326cbb419SViacheslav Ovsiienko 		uint8_t i, j;
1524ce8d5614SIntel 
1525c9cafcc8SShahaf Shuler 		for (i = 0; i < num_sockets; i++)
152626cbb419SViacheslav Ovsiienko 			for (j = 0; j < mbuf_data_size_n; j++)
152726cbb419SViacheslav Ovsiienko 				mempools[i * MAX_SEGS_BUFFER_SPLIT + j] =
152826cbb419SViacheslav Ovsiienko 					mbuf_pool_create(mbuf_data_size[j],
1529401b744dSShahaf Shuler 							  nb_mbuf_per_pool,
153026cbb419SViacheslav Ovsiienko 							  socket_ids[i], j);
15313ab64341SOlivier Matz 	} else {
153226cbb419SViacheslav Ovsiienko 		uint8_t i;
153326cbb419SViacheslav Ovsiienko 
153426cbb419SViacheslav Ovsiienko 		for (i = 0; i < mbuf_data_size_n; i++)
153526cbb419SViacheslav Ovsiienko 			mempools[i] = mbuf_pool_create
153626cbb419SViacheslav Ovsiienko 					(mbuf_data_size[i],
1537401b744dSShahaf Shuler 					 nb_mbuf_per_pool,
153826cbb419SViacheslav Ovsiienko 					 socket_num == UMA_NO_CONFIG ?
153926cbb419SViacheslav Ovsiienko 					 0 : socket_num, i);
15403ab64341SOlivier Matz 	}
1541b6ea6408SIntel 
1542b6ea6408SIntel 	init_port_config();
15435886ae07SAdrien Mazarguil 
154452f38a20SJiayu Hu 	gso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
1545aaacd052SJiayu Hu 		DEV_TX_OFFLOAD_GRE_TNL_TSO | DEV_TX_OFFLOAD_UDP_TSO;
15465886ae07SAdrien Mazarguil 	/*
15475886ae07SAdrien Mazarguil 	 * Records which Mbuf pool to use by each logical core, if needed.
15485886ae07SAdrien Mazarguil 	 */
15495886ae07SAdrien Mazarguil 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
15508fd8bebcSAdrien Mazarguil 		mbp = mbuf_pool_find(
155126cbb419SViacheslav Ovsiienko 			rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]), 0);
15528fd8bebcSAdrien Mazarguil 
15535886ae07SAdrien Mazarguil 		if (mbp == NULL)
155426cbb419SViacheslav Ovsiienko 			mbp = mbuf_pool_find(0, 0);
15555886ae07SAdrien Mazarguil 		fwd_lcores[lc_id]->mbp = mbp;
155652f38a20SJiayu Hu 		/* initialize GSO context */
155752f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.direct_pool = mbp;
155852f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.indirect_pool = mbp;
155952f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.gso_types = gso_types;
156035b2d13fSOlivier Matz 		fwd_lcores[lc_id]->gso_ctx.gso_size = RTE_ETHER_MAX_LEN -
156135b2d13fSOlivier Matz 			RTE_ETHER_CRC_LEN;
156252f38a20SJiayu Hu 		fwd_lcores[lc_id]->gso_ctx.flag = 0;
15635886ae07SAdrien Mazarguil 	}
15645886ae07SAdrien Mazarguil 
1565ce8d5614SIntel 	/* Configuration of packet forwarding streams. */
1566ce8d5614SIntel 	if (init_fwd_streams() < 0)
1567ce8d5614SIntel 		rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n");
15680c0db76fSBernard Iremonger 
15690c0db76fSBernard Iremonger 	fwd_config_setup();
1570b7091f1dSJiayu Hu 
1571b7091f1dSJiayu Hu 	/* create a gro context for each lcore */
1572b7091f1dSJiayu Hu 	gro_param.gro_types = RTE_GRO_TCP_IPV4;
1573b7091f1dSJiayu Hu 	gro_param.max_flow_num = GRO_MAX_FLUSH_CYCLES;
1574b7091f1dSJiayu Hu 	gro_param.max_item_per_flow = MAX_PKT_BURST;
1575b7091f1dSJiayu Hu 	for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
1576b7091f1dSJiayu Hu 		gro_param.socket_id = rte_lcore_to_socket_id(
1577b7091f1dSJiayu Hu 				fwd_lcores_cpuids[lc_id]);
1578b7091f1dSJiayu Hu 		fwd_lcores[lc_id]->gro_ctx = rte_gro_ctx_create(&gro_param);
1579b7091f1dSJiayu Hu 		if (fwd_lcores[lc_id]->gro_ctx == NULL) {
1580b7091f1dSJiayu Hu 			rte_exit(EXIT_FAILURE,
1581b7091f1dSJiayu Hu 					"rte_gro_ctx_create() failed\n");
1582b7091f1dSJiayu Hu 		}
1583b7091f1dSJiayu Hu 	}
1584ce8d5614SIntel }
1585ce8d5614SIntel 
15862950a769SDeclan Doherty 
15872950a769SDeclan Doherty void
1588a21d5a4bSDeclan Doherty reconfig(portid_t new_port_id, unsigned socket_id)
15892950a769SDeclan Doherty {
15902950a769SDeclan Doherty 	struct rte_port *port;
15916f51deb9SIvan Ilchenko 	int ret;
15922950a769SDeclan Doherty 
15932950a769SDeclan Doherty 	/* Reconfiguration of Ethernet ports. */
15942950a769SDeclan Doherty 	port = &ports[new_port_id];
15956f51deb9SIvan Ilchenko 
15966f51deb9SIvan Ilchenko 	ret = eth_dev_info_get_print_err(new_port_id, &port->dev_info);
15976f51deb9SIvan Ilchenko 	if (ret != 0)
15986f51deb9SIvan Ilchenko 		return;
15992950a769SDeclan Doherty 
16002950a769SDeclan Doherty 	/* set flag to initialize port/queue */
16012950a769SDeclan Doherty 	port->need_reconfig = 1;
16022950a769SDeclan Doherty 	port->need_reconfig_queues = 1;
1603a21d5a4bSDeclan Doherty 	port->socket_id = socket_id;
16042950a769SDeclan Doherty 
16052950a769SDeclan Doherty 	init_port_config();
16062950a769SDeclan Doherty }
16072950a769SDeclan Doherty 
16082950a769SDeclan Doherty 
1609ce8d5614SIntel int
1610ce8d5614SIntel init_fwd_streams(void)
1611ce8d5614SIntel {
1612ce8d5614SIntel 	portid_t pid;
1613ce8d5614SIntel 	struct rte_port *port;
1614ce8d5614SIntel 	streamid_t sm_id, nb_fwd_streams_new;
16155a8fb55cSReshma Pattan 	queueid_t q;
1616ce8d5614SIntel 
1617ce8d5614SIntel 	/* set socket id according to numa or not */
16187d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
1619ce8d5614SIntel 		port = &ports[pid];
1620ce8d5614SIntel 		if (nb_rxq > port->dev_info.max_rx_queues) {
1621ce8d5614SIntel 			printf("Fail: nb_rxq(%d) is greater than "
1622ce8d5614SIntel 				"max_rx_queues(%d)\n", nb_rxq,
1623ce8d5614SIntel 				port->dev_info.max_rx_queues);
1624ce8d5614SIntel 			return -1;
1625ce8d5614SIntel 		}
1626ce8d5614SIntel 		if (nb_txq > port->dev_info.max_tx_queues) {
1627ce8d5614SIntel 			printf("Fail: nb_txq(%d) is greater than "
1628ce8d5614SIntel 				"max_tx_queues(%d)\n", nb_txq,
1629ce8d5614SIntel 				port->dev_info.max_tx_queues);
1630ce8d5614SIntel 			return -1;
1631ce8d5614SIntel 		}
163220a0286fSLiu Xiaofeng 		if (numa_support) {
163320a0286fSLiu Xiaofeng 			if (port_numa[pid] != NUMA_NO_CONFIG)
163420a0286fSLiu Xiaofeng 				port->socket_id = port_numa[pid];
163520a0286fSLiu Xiaofeng 			else {
1636b6ea6408SIntel 				port->socket_id = rte_eth_dev_socket_id(pid);
163720a0286fSLiu Xiaofeng 
163829841336SPhil Yang 				/*
163929841336SPhil Yang 				 * if socket_id is invalid,
164029841336SPhil Yang 				 * set to the first available socket.
164129841336SPhil Yang 				 */
164220a0286fSLiu Xiaofeng 				if (check_socket_id(port->socket_id) < 0)
164329841336SPhil Yang 					port->socket_id = socket_ids[0];
164420a0286fSLiu Xiaofeng 			}
164520a0286fSLiu Xiaofeng 		}
1646b6ea6408SIntel 		else {
1647b6ea6408SIntel 			if (socket_num == UMA_NO_CONFIG)
1648af75078fSIntel 				port->socket_id = 0;
1649b6ea6408SIntel 			else
1650b6ea6408SIntel 				port->socket_id = socket_num;
1651b6ea6408SIntel 		}
1652af75078fSIntel 	}
1653af75078fSIntel 
16545a8fb55cSReshma Pattan 	q = RTE_MAX(nb_rxq, nb_txq);
16555a8fb55cSReshma Pattan 	if (q == 0) {
16565a8fb55cSReshma Pattan 		printf("Fail: Cannot allocate fwd streams as number of queues is 0\n");
16575a8fb55cSReshma Pattan 		return -1;
16585a8fb55cSReshma Pattan 	}
16595a8fb55cSReshma Pattan 	nb_fwd_streams_new = (streamid_t)(nb_ports * q);
1660ce8d5614SIntel 	if (nb_fwd_streams_new == nb_fwd_streams)
1661ce8d5614SIntel 		return 0;
1662ce8d5614SIntel 	/* clear the old */
1663ce8d5614SIntel 	if (fwd_streams != NULL) {
1664ce8d5614SIntel 		for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
1665ce8d5614SIntel 			if (fwd_streams[sm_id] == NULL)
1666ce8d5614SIntel 				continue;
1667ce8d5614SIntel 			rte_free(fwd_streams[sm_id]);
1668ce8d5614SIntel 			fwd_streams[sm_id] = NULL;
1669af75078fSIntel 		}
1670ce8d5614SIntel 		rte_free(fwd_streams);
1671ce8d5614SIntel 		fwd_streams = NULL;
1672ce8d5614SIntel 	}
1673ce8d5614SIntel 
1674ce8d5614SIntel 	/* init new */
1675ce8d5614SIntel 	nb_fwd_streams = nb_fwd_streams_new;
16761f84c469SMatan Azrad 	if (nb_fwd_streams) {
1677ce8d5614SIntel 		fwd_streams = rte_zmalloc("testpmd: fwd_streams",
16781f84c469SMatan Azrad 			sizeof(struct fwd_stream *) * nb_fwd_streams,
16791f84c469SMatan Azrad 			RTE_CACHE_LINE_SIZE);
1680ce8d5614SIntel 		if (fwd_streams == NULL)
16811f84c469SMatan Azrad 			rte_exit(EXIT_FAILURE, "rte_zmalloc(%d"
16821f84c469SMatan Azrad 				 " (struct fwd_stream *)) failed\n",
16831f84c469SMatan Azrad 				 nb_fwd_streams);
1684ce8d5614SIntel 
1685af75078fSIntel 		for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
16861f84c469SMatan Azrad 			fwd_streams[sm_id] = rte_zmalloc("testpmd:"
16871f84c469SMatan Azrad 				" struct fwd_stream", sizeof(struct fwd_stream),
16881f84c469SMatan Azrad 				RTE_CACHE_LINE_SIZE);
1689ce8d5614SIntel 			if (fwd_streams[sm_id] == NULL)
16901f84c469SMatan Azrad 				rte_exit(EXIT_FAILURE, "rte_zmalloc"
16911f84c469SMatan Azrad 					 "(struct fwd_stream) failed\n");
16921f84c469SMatan Azrad 		}
1693af75078fSIntel 	}
1694ce8d5614SIntel 
1695ce8d5614SIntel 	return 0;
1696af75078fSIntel }
1697af75078fSIntel 
1698af75078fSIntel static void
1699af75078fSIntel pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
1700af75078fSIntel {
17017569b8c1SHonnappa Nagarahalli 	uint64_t total_burst, sburst;
170285de481aSHonnappa Nagarahalli 	uint64_t nb_burst;
17037569b8c1SHonnappa Nagarahalli 	uint64_t burst_stats[4];
17047569b8c1SHonnappa Nagarahalli 	uint16_t pktnb_stats[4];
1705af75078fSIntel 	uint16_t nb_pkt;
17067569b8c1SHonnappa Nagarahalli 	int burst_percent[4], sburstp;
17077569b8c1SHonnappa Nagarahalli 	int i;
1708af75078fSIntel 
1709af75078fSIntel 	/*
1710af75078fSIntel 	 * First compute the total number of packet bursts and the
1711af75078fSIntel 	 * two highest numbers of bursts of the same number of packets.
1712af75078fSIntel 	 */
17137569b8c1SHonnappa Nagarahalli 	memset(&burst_stats, 0x0, sizeof(burst_stats));
17147569b8c1SHonnappa Nagarahalli 	memset(&pktnb_stats, 0x0, sizeof(pktnb_stats));
17157569b8c1SHonnappa Nagarahalli 
17167569b8c1SHonnappa Nagarahalli 	/* Show stats for 0 burst size always */
17177569b8c1SHonnappa Nagarahalli 	total_burst = pbs->pkt_burst_spread[0];
17187569b8c1SHonnappa Nagarahalli 	burst_stats[0] = pbs->pkt_burst_spread[0];
17197569b8c1SHonnappa Nagarahalli 	pktnb_stats[0] = 0;
17207569b8c1SHonnappa Nagarahalli 
17217569b8c1SHonnappa Nagarahalli 	/* Find the next 2 burst sizes with highest occurrences. */
17227569b8c1SHonnappa Nagarahalli 	for (nb_pkt = 1; nb_pkt < MAX_PKT_BURST; nb_pkt++) {
1723af75078fSIntel 		nb_burst = pbs->pkt_burst_spread[nb_pkt];
17247569b8c1SHonnappa Nagarahalli 
1725af75078fSIntel 		if (nb_burst == 0)
1726af75078fSIntel 			continue;
17277569b8c1SHonnappa Nagarahalli 
1728af75078fSIntel 		total_burst += nb_burst;
17297569b8c1SHonnappa Nagarahalli 
17307569b8c1SHonnappa Nagarahalli 		if (nb_burst > burst_stats[1]) {
17317569b8c1SHonnappa Nagarahalli 			burst_stats[2] = burst_stats[1];
17327569b8c1SHonnappa Nagarahalli 			pktnb_stats[2] = pktnb_stats[1];
1733fe613657SDaniel Shelepov 			burst_stats[1] = nb_burst;
1734fe613657SDaniel Shelepov 			pktnb_stats[1] = nb_pkt;
17357569b8c1SHonnappa Nagarahalli 		} else if (nb_burst > burst_stats[2]) {
17367569b8c1SHonnappa Nagarahalli 			burst_stats[2] = nb_burst;
17377569b8c1SHonnappa Nagarahalli 			pktnb_stats[2] = nb_pkt;
1738af75078fSIntel 		}
1739af75078fSIntel 	}
1740af75078fSIntel 	if (total_burst == 0)
1741af75078fSIntel 		return;
17427569b8c1SHonnappa Nagarahalli 
17437569b8c1SHonnappa Nagarahalli 	printf("  %s-bursts : %"PRIu64" [", rx_tx, total_burst);
17447569b8c1SHonnappa Nagarahalli 	for (i = 0, sburst = 0, sburstp = 0; i < 4; i++) {
17457569b8c1SHonnappa Nagarahalli 		if (i == 3) {
17467569b8c1SHonnappa Nagarahalli 			printf("%d%% of other]\n", 100 - sburstp);
1747af75078fSIntel 			return;
1748af75078fSIntel 		}
17497569b8c1SHonnappa Nagarahalli 
17507569b8c1SHonnappa Nagarahalli 		sburst += burst_stats[i];
17517569b8c1SHonnappa Nagarahalli 		if (sburst == total_burst) {
17527569b8c1SHonnappa Nagarahalli 			printf("%d%% of %d pkts]\n",
17537569b8c1SHonnappa Nagarahalli 				100 - sburstp, (int) pktnb_stats[i]);
1754af75078fSIntel 			return;
1755af75078fSIntel 		}
17567569b8c1SHonnappa Nagarahalli 
17577569b8c1SHonnappa Nagarahalli 		burst_percent[i] =
17587569b8c1SHonnappa Nagarahalli 			(double)burst_stats[i] / total_burst * 100;
17597569b8c1SHonnappa Nagarahalli 		printf("%d%% of %d pkts + ",
17607569b8c1SHonnappa Nagarahalli 			burst_percent[i], (int) pktnb_stats[i]);
17617569b8c1SHonnappa Nagarahalli 		sburstp += burst_percent[i];
1762af75078fSIntel 	}
1763af75078fSIntel }
1764af75078fSIntel 
1765af75078fSIntel static void
1766af75078fSIntel fwd_stream_stats_display(streamid_t stream_id)
1767af75078fSIntel {
1768af75078fSIntel 	struct fwd_stream *fs;
1769af75078fSIntel 	static const char *fwd_top_stats_border = "-------";
1770af75078fSIntel 
1771af75078fSIntel 	fs = fwd_streams[stream_id];
1772af75078fSIntel 	if ((fs->rx_packets == 0) && (fs->tx_packets == 0) &&
1773af75078fSIntel 	    (fs->fwd_dropped == 0))
1774af75078fSIntel 		return;
1775af75078fSIntel 	printf("\n  %s Forward Stats for RX Port=%2d/Queue=%2d -> "
1776af75078fSIntel 	       "TX Port=%2d/Queue=%2d %s\n",
1777af75078fSIntel 	       fwd_top_stats_border, fs->rx_port, fs->rx_queue,
1778af75078fSIntel 	       fs->tx_port, fs->tx_queue, fwd_top_stats_border);
1779c185d42cSDavid Marchand 	printf("  RX-packets: %-14"PRIu64" TX-packets: %-14"PRIu64
1780c185d42cSDavid Marchand 	       " TX-dropped: %-14"PRIu64,
1781af75078fSIntel 	       fs->rx_packets, fs->tx_packets, fs->fwd_dropped);
1782af75078fSIntel 
1783af75078fSIntel 	/* if checksum mode */
1784af75078fSIntel 	if (cur_fwd_eng == &csum_fwd_engine) {
1785c185d42cSDavid Marchand 		printf("  RX- bad IP checksum: %-14"PRIu64
1786c185d42cSDavid Marchand 		       "  Rx- bad L4 checksum: %-14"PRIu64
1787c185d42cSDavid Marchand 		       " Rx- bad outer L4 checksum: %-14"PRIu64"\n",
178858d475b7SJerin Jacob 			fs->rx_bad_ip_csum, fs->rx_bad_l4_csum,
178958d475b7SJerin Jacob 			fs->rx_bad_outer_l4_csum);
179094d65546SDavid Marchand 	} else {
179194d65546SDavid Marchand 		printf("\n");
1792af75078fSIntel 	}
1793af75078fSIntel 
17940e4b1963SDharmik Thakkar 	if (record_burst_stats) {
1795af75078fSIntel 		pkt_burst_stats_display("RX", &fs->rx_burst_stats);
1796af75078fSIntel 		pkt_burst_stats_display("TX", &fs->tx_burst_stats);
17970e4b1963SDharmik Thakkar 	}
1798af75078fSIntel }
1799af75078fSIntel 
180053324971SDavid Marchand void
180153324971SDavid Marchand fwd_stats_display(void)
180253324971SDavid Marchand {
180353324971SDavid Marchand 	static const char *fwd_stats_border = "----------------------";
180453324971SDavid Marchand 	static const char *acc_stats_border = "+++++++++++++++";
180553324971SDavid Marchand 	struct {
180653324971SDavid Marchand 		struct fwd_stream *rx_stream;
180753324971SDavid Marchand 		struct fwd_stream *tx_stream;
180853324971SDavid Marchand 		uint64_t tx_dropped;
180953324971SDavid Marchand 		uint64_t rx_bad_ip_csum;
181053324971SDavid Marchand 		uint64_t rx_bad_l4_csum;
181153324971SDavid Marchand 		uint64_t rx_bad_outer_l4_csum;
181253324971SDavid Marchand 	} ports_stats[RTE_MAX_ETHPORTS];
181353324971SDavid Marchand 	uint64_t total_rx_dropped = 0;
181453324971SDavid Marchand 	uint64_t total_tx_dropped = 0;
181553324971SDavid Marchand 	uint64_t total_rx_nombuf = 0;
181653324971SDavid Marchand 	struct rte_eth_stats stats;
181753324971SDavid Marchand 	uint64_t fwd_cycles = 0;
181853324971SDavid Marchand 	uint64_t total_recv = 0;
181953324971SDavid Marchand 	uint64_t total_xmit = 0;
182053324971SDavid Marchand 	struct rte_port *port;
182153324971SDavid Marchand 	streamid_t sm_id;
182253324971SDavid Marchand 	portid_t pt_id;
182353324971SDavid Marchand 	int i;
182453324971SDavid Marchand 
182553324971SDavid Marchand 	memset(ports_stats, 0, sizeof(ports_stats));
182653324971SDavid Marchand 
182753324971SDavid Marchand 	for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
182853324971SDavid Marchand 		struct fwd_stream *fs = fwd_streams[sm_id];
182953324971SDavid Marchand 
183053324971SDavid Marchand 		if (cur_fwd_config.nb_fwd_streams >
183153324971SDavid Marchand 		    cur_fwd_config.nb_fwd_ports) {
183253324971SDavid Marchand 			fwd_stream_stats_display(sm_id);
183353324971SDavid Marchand 		} else {
183453324971SDavid Marchand 			ports_stats[fs->tx_port].tx_stream = fs;
183553324971SDavid Marchand 			ports_stats[fs->rx_port].rx_stream = fs;
183653324971SDavid Marchand 		}
183753324971SDavid Marchand 
183853324971SDavid Marchand 		ports_stats[fs->tx_port].tx_dropped += fs->fwd_dropped;
183953324971SDavid Marchand 
184053324971SDavid Marchand 		ports_stats[fs->rx_port].rx_bad_ip_csum += fs->rx_bad_ip_csum;
184153324971SDavid Marchand 		ports_stats[fs->rx_port].rx_bad_l4_csum += fs->rx_bad_l4_csum;
184253324971SDavid Marchand 		ports_stats[fs->rx_port].rx_bad_outer_l4_csum +=
184353324971SDavid Marchand 				fs->rx_bad_outer_l4_csum;
184453324971SDavid Marchand 
1845bc700b67SDharmik Thakkar 		if (record_core_cycles)
184653324971SDavid Marchand 			fwd_cycles += fs->core_cycles;
184753324971SDavid Marchand 	}
184853324971SDavid Marchand 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
184953324971SDavid Marchand 		pt_id = fwd_ports_ids[i];
185053324971SDavid Marchand 		port = &ports[pt_id];
185153324971SDavid Marchand 
185253324971SDavid Marchand 		rte_eth_stats_get(pt_id, &stats);
185353324971SDavid Marchand 		stats.ipackets -= port->stats.ipackets;
185453324971SDavid Marchand 		stats.opackets -= port->stats.opackets;
185553324971SDavid Marchand 		stats.ibytes -= port->stats.ibytes;
185653324971SDavid Marchand 		stats.obytes -= port->stats.obytes;
185753324971SDavid Marchand 		stats.imissed -= port->stats.imissed;
185853324971SDavid Marchand 		stats.oerrors -= port->stats.oerrors;
185953324971SDavid Marchand 		stats.rx_nombuf -= port->stats.rx_nombuf;
186053324971SDavid Marchand 
186153324971SDavid Marchand 		total_recv += stats.ipackets;
186253324971SDavid Marchand 		total_xmit += stats.opackets;
186353324971SDavid Marchand 		total_rx_dropped += stats.imissed;
186453324971SDavid Marchand 		total_tx_dropped += ports_stats[pt_id].tx_dropped;
186553324971SDavid Marchand 		total_tx_dropped += stats.oerrors;
186653324971SDavid Marchand 		total_rx_nombuf  += stats.rx_nombuf;
186753324971SDavid Marchand 
186853324971SDavid Marchand 		printf("\n  %s Forward statistics for port %-2d %s\n",
186953324971SDavid Marchand 		       fwd_stats_border, pt_id, fwd_stats_border);
187053324971SDavid Marchand 
1871*08dcd187SHuisong Li 		printf("  RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64
1872*08dcd187SHuisong Li 		       "RX-total: %-"PRIu64"\n", stats.ipackets, stats.imissed,
187353324971SDavid Marchand 		       stats.ipackets + stats.imissed);
187453324971SDavid Marchand 
187553324971SDavid Marchand 		if (cur_fwd_eng == &csum_fwd_engine)
187653324971SDavid Marchand 			printf("  Bad-ipcsum: %-14"PRIu64
187753324971SDavid Marchand 			       " Bad-l4csum: %-14"PRIu64
187853324971SDavid Marchand 			       "Bad-outer-l4csum: %-14"PRIu64"\n",
187953324971SDavid Marchand 			       ports_stats[pt_id].rx_bad_ip_csum,
188053324971SDavid Marchand 			       ports_stats[pt_id].rx_bad_l4_csum,
188153324971SDavid Marchand 			       ports_stats[pt_id].rx_bad_outer_l4_csum);
188253324971SDavid Marchand 		if (stats.ierrors + stats.rx_nombuf > 0) {
1883*08dcd187SHuisong Li 			printf("  RX-error: %-"PRIu64"\n", stats.ierrors);
1884*08dcd187SHuisong Li 			printf("  RX-nombufs: %-14"PRIu64"\n", stats.rx_nombuf);
188553324971SDavid Marchand 		}
188653324971SDavid Marchand 
1887*08dcd187SHuisong Li 		printf("  TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64
188853324971SDavid Marchand 		       "TX-total: %-"PRIu64"\n",
188953324971SDavid Marchand 		       stats.opackets, ports_stats[pt_id].tx_dropped,
189053324971SDavid Marchand 		       stats.opackets + ports_stats[pt_id].tx_dropped);
189153324971SDavid Marchand 
18920e4b1963SDharmik Thakkar 		if (record_burst_stats) {
189353324971SDavid Marchand 			if (ports_stats[pt_id].rx_stream)
189453324971SDavid Marchand 				pkt_burst_stats_display("RX",
189553324971SDavid Marchand 					&ports_stats[pt_id].rx_stream->rx_burst_stats);
189653324971SDavid Marchand 			if (ports_stats[pt_id].tx_stream)
189753324971SDavid Marchand 				pkt_burst_stats_display("TX",
189853324971SDavid Marchand 				&ports_stats[pt_id].tx_stream->tx_burst_stats);
18990e4b1963SDharmik Thakkar 		}
190053324971SDavid Marchand 
190153324971SDavid Marchand 		printf("  %s--------------------------------%s\n",
190253324971SDavid Marchand 		       fwd_stats_border, fwd_stats_border);
190353324971SDavid Marchand 	}
190453324971SDavid Marchand 
190553324971SDavid Marchand 	printf("\n  %s Accumulated forward statistics for all ports"
190653324971SDavid Marchand 	       "%s\n",
190753324971SDavid Marchand 	       acc_stats_border, acc_stats_border);
190853324971SDavid Marchand 	printf("  RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
190953324971SDavid Marchand 	       "%-"PRIu64"\n"
191053324971SDavid Marchand 	       "  TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
191153324971SDavid Marchand 	       "%-"PRIu64"\n",
191253324971SDavid Marchand 	       total_recv, total_rx_dropped, total_recv + total_rx_dropped,
191353324971SDavid Marchand 	       total_xmit, total_tx_dropped, total_xmit + total_tx_dropped);
191453324971SDavid Marchand 	if (total_rx_nombuf > 0)
191553324971SDavid Marchand 		printf("  RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf);
191653324971SDavid Marchand 	printf("  %s++++++++++++++++++++++++++++++++++++++++++++++"
191753324971SDavid Marchand 	       "%s\n",
191853324971SDavid Marchand 	       acc_stats_border, acc_stats_border);
1919bc700b67SDharmik Thakkar 	if (record_core_cycles) {
19204c0497b1SDharmik Thakkar #define CYC_PER_MHZ 1E6
19213a164e00SPhil Yang 		if (total_recv > 0 || total_xmit > 0) {
19223a164e00SPhil Yang 			uint64_t total_pkts = 0;
19233a164e00SPhil Yang 			if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 ||
19243a164e00SPhil Yang 			    strcmp(cur_fwd_eng->fwd_mode_name, "flowgen") == 0)
19253a164e00SPhil Yang 				total_pkts = total_xmit;
19263a164e00SPhil Yang 			else
19273a164e00SPhil Yang 				total_pkts = total_recv;
19283a164e00SPhil Yang 
19291920832aSDharmik Thakkar 			printf("\n  CPU cycles/packet=%.2F (total cycles="
19303a164e00SPhil Yang 			       "%"PRIu64" / total %s packets=%"PRIu64") at %"PRIu64
19314c0497b1SDharmik Thakkar 			       " MHz Clock\n",
19323a164e00SPhil Yang 			       (double) fwd_cycles / total_pkts,
19333a164e00SPhil Yang 			       fwd_cycles, cur_fwd_eng->fwd_mode_name, total_pkts,
19344c0497b1SDharmik Thakkar 			       (uint64_t)(rte_get_tsc_hz() / CYC_PER_MHZ));
19353a164e00SPhil Yang 		}
1936bc700b67SDharmik Thakkar 	}
193753324971SDavid Marchand }
193853324971SDavid Marchand 
193953324971SDavid Marchand void
194053324971SDavid Marchand fwd_stats_reset(void)
194153324971SDavid Marchand {
194253324971SDavid Marchand 	streamid_t sm_id;
194353324971SDavid Marchand 	portid_t pt_id;
194453324971SDavid Marchand 	int i;
194553324971SDavid Marchand 
194653324971SDavid Marchand 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
194753324971SDavid Marchand 		pt_id = fwd_ports_ids[i];
194853324971SDavid Marchand 		rte_eth_stats_get(pt_id, &ports[pt_id].stats);
194953324971SDavid Marchand 	}
195053324971SDavid Marchand 	for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
195153324971SDavid Marchand 		struct fwd_stream *fs = fwd_streams[sm_id];
195253324971SDavid Marchand 
195353324971SDavid Marchand 		fs->rx_packets = 0;
195453324971SDavid Marchand 		fs->tx_packets = 0;
195553324971SDavid Marchand 		fs->fwd_dropped = 0;
195653324971SDavid Marchand 		fs->rx_bad_ip_csum = 0;
195753324971SDavid Marchand 		fs->rx_bad_l4_csum = 0;
195853324971SDavid Marchand 		fs->rx_bad_outer_l4_csum = 0;
195953324971SDavid Marchand 
196053324971SDavid Marchand 		memset(&fs->rx_burst_stats, 0, sizeof(fs->rx_burst_stats));
196153324971SDavid Marchand 		memset(&fs->tx_burst_stats, 0, sizeof(fs->tx_burst_stats));
196253324971SDavid Marchand 		fs->core_cycles = 0;
196353324971SDavid Marchand 	}
196453324971SDavid Marchand }
196553324971SDavid Marchand 
1966af75078fSIntel static void
19677741e4cfSIntel flush_fwd_rx_queues(void)
1968af75078fSIntel {
1969af75078fSIntel 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1970af75078fSIntel 	portid_t  rxp;
19717741e4cfSIntel 	portid_t port_id;
1972af75078fSIntel 	queueid_t rxq;
1973af75078fSIntel 	uint16_t  nb_rx;
1974af75078fSIntel 	uint16_t  i;
1975af75078fSIntel 	uint8_t   j;
1976f487715fSReshma Pattan 	uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
1977594302c7SJames Poole 	uint64_t timer_period;
1978f487715fSReshma Pattan 
1979f487715fSReshma Pattan 	/* convert to number of cycles */
1980594302c7SJames Poole 	timer_period = rte_get_timer_hz(); /* 1 second timeout */
1981af75078fSIntel 
1982af75078fSIntel 	for (j = 0; j < 2; j++) {
19837741e4cfSIntel 		for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) {
1984af75078fSIntel 			for (rxq = 0; rxq < nb_rxq; rxq++) {
19857741e4cfSIntel 				port_id = fwd_ports_ids[rxp];
1986f487715fSReshma Pattan 				/**
1987f487715fSReshma Pattan 				* testpmd can stuck in the below do while loop
1988f487715fSReshma Pattan 				* if rte_eth_rx_burst() always returns nonzero
1989f487715fSReshma Pattan 				* packets. So timer is added to exit this loop
1990f487715fSReshma Pattan 				* after 1sec timer expiry.
1991f487715fSReshma Pattan 				*/
1992f487715fSReshma Pattan 				prev_tsc = rte_rdtsc();
1993af75078fSIntel 				do {
19947741e4cfSIntel 					nb_rx = rte_eth_rx_burst(port_id, rxq,
1995013af9b6SIntel 						pkts_burst, MAX_PKT_BURST);
1996af75078fSIntel 					for (i = 0; i < nb_rx; i++)
1997af75078fSIntel 						rte_pktmbuf_free(pkts_burst[i]);
1998f487715fSReshma Pattan 
1999f487715fSReshma Pattan 					cur_tsc = rte_rdtsc();
2000f487715fSReshma Pattan 					diff_tsc = cur_tsc - prev_tsc;
2001f487715fSReshma Pattan 					timer_tsc += diff_tsc;
2002f487715fSReshma Pattan 				} while ((nb_rx > 0) &&
2003f487715fSReshma Pattan 					(timer_tsc < timer_period));
2004f487715fSReshma Pattan 				timer_tsc = 0;
2005af75078fSIntel 			}
2006af75078fSIntel 		}
2007af75078fSIntel 		rte_delay_ms(10); /* wait 10 milli-seconds before retrying */
2008af75078fSIntel 	}
2009af75078fSIntel }
2010af75078fSIntel 
2011af75078fSIntel static void
2012af75078fSIntel run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
2013af75078fSIntel {
2014af75078fSIntel 	struct fwd_stream **fsm;
2015af75078fSIntel 	streamid_t nb_fs;
2016af75078fSIntel 	streamid_t sm_id;
2017a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
20187e4441c8SRemy Horton 	uint64_t tics_per_1sec;
20197e4441c8SRemy Horton 	uint64_t tics_datum;
20207e4441c8SRemy Horton 	uint64_t tics_current;
20214918a357SXiaoyun Li 	uint16_t i, cnt_ports;
2022af75078fSIntel 
20234918a357SXiaoyun Li 	cnt_ports = nb_ports;
20247e4441c8SRemy Horton 	tics_datum = rte_rdtsc();
20257e4441c8SRemy Horton 	tics_per_1sec = rte_get_timer_hz();
20267e4441c8SRemy Horton #endif
2027af75078fSIntel 	fsm = &fwd_streams[fc->stream_idx];
2028af75078fSIntel 	nb_fs = fc->stream_nb;
2029af75078fSIntel 	do {
2030af75078fSIntel 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
2031af75078fSIntel 			(*pkt_fwd)(fsm[sm_id]);
2032a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
2033e25e6c70SRemy Horton 		if (bitrate_enabled != 0 &&
2034e25e6c70SRemy Horton 				bitrate_lcore_id == rte_lcore_id()) {
20357e4441c8SRemy Horton 			tics_current = rte_rdtsc();
20367e4441c8SRemy Horton 			if (tics_current - tics_datum >= tics_per_1sec) {
20377e4441c8SRemy Horton 				/* Periodic bitrate calculation */
20384918a357SXiaoyun Li 				for (i = 0; i < cnt_ports; i++)
2039e25e6c70SRemy Horton 					rte_stats_bitrate_calc(bitrate_data,
20404918a357SXiaoyun Li 						ports_ids[i]);
20417e4441c8SRemy Horton 				tics_datum = tics_current;
20427e4441c8SRemy Horton 			}
2043e25e6c70SRemy Horton 		}
20447e4441c8SRemy Horton #endif
2045a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
204665eb1e54SPablo de Lara 		if (latencystats_enabled != 0 &&
204765eb1e54SPablo de Lara 				latencystats_lcore_id == rte_lcore_id())
204862d3216dSReshma Pattan 			rte_latencystats_update();
204962d3216dSReshma Pattan #endif
205062d3216dSReshma Pattan 
2051af75078fSIntel 	} while (! fc->stopped);
2052af75078fSIntel }
2053af75078fSIntel 
2054af75078fSIntel static int
2055af75078fSIntel start_pkt_forward_on_core(void *fwd_arg)
2056af75078fSIntel {
2057af75078fSIntel 	run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg,
2058af75078fSIntel 			     cur_fwd_config.fwd_eng->packet_fwd);
2059af75078fSIntel 	return 0;
2060af75078fSIntel }
2061af75078fSIntel 
2062af75078fSIntel /*
2063af75078fSIntel  * Run the TXONLY packet forwarding engine to send a single burst of packets.
2064af75078fSIntel  * Used to start communication flows in network loopback test configurations.
2065af75078fSIntel  */
2066af75078fSIntel static int
2067af75078fSIntel run_one_txonly_burst_on_core(void *fwd_arg)
2068af75078fSIntel {
2069af75078fSIntel 	struct fwd_lcore *fwd_lc;
2070af75078fSIntel 	struct fwd_lcore tmp_lcore;
2071af75078fSIntel 
2072af75078fSIntel 	fwd_lc = (struct fwd_lcore *) fwd_arg;
2073af75078fSIntel 	tmp_lcore = *fwd_lc;
2074af75078fSIntel 	tmp_lcore.stopped = 1;
2075af75078fSIntel 	run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd);
2076af75078fSIntel 	return 0;
2077af75078fSIntel }
2078af75078fSIntel 
2079af75078fSIntel /*
2080af75078fSIntel  * Launch packet forwarding:
2081af75078fSIntel  *     - Setup per-port forwarding context.
2082af75078fSIntel  *     - launch logical cores with their forwarding configuration.
2083af75078fSIntel  */
2084af75078fSIntel static void
2085af75078fSIntel launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore)
2086af75078fSIntel {
2087af75078fSIntel 	port_fwd_begin_t port_fwd_begin;
2088af75078fSIntel 	unsigned int i;
2089af75078fSIntel 	unsigned int lc_id;
2090af75078fSIntel 	int diag;
2091af75078fSIntel 
2092af75078fSIntel 	port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin;
2093af75078fSIntel 	if (port_fwd_begin != NULL) {
2094af75078fSIntel 		for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
2095af75078fSIntel 			(*port_fwd_begin)(fwd_ports_ids[i]);
2096af75078fSIntel 	}
2097af75078fSIntel 	for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) {
2098af75078fSIntel 		lc_id = fwd_lcores_cpuids[i];
2099af75078fSIntel 		if ((interactive == 0) || (lc_id != rte_lcore_id())) {
2100af75078fSIntel 			fwd_lcores[i]->stopped = 0;
2101af75078fSIntel 			diag = rte_eal_remote_launch(pkt_fwd_on_lcore,
2102af75078fSIntel 						     fwd_lcores[i], lc_id);
2103af75078fSIntel 			if (diag != 0)
2104af75078fSIntel 				printf("launch lcore %u failed - diag=%d\n",
2105af75078fSIntel 				       lc_id, diag);
2106af75078fSIntel 		}
2107af75078fSIntel 	}
2108af75078fSIntel }
2109af75078fSIntel 
2110af75078fSIntel /*
2111af75078fSIntel  * Launch packet forwarding configuration.
2112af75078fSIntel  */
2113af75078fSIntel void
2114af75078fSIntel start_packet_forwarding(int with_tx_first)
2115af75078fSIntel {
2116af75078fSIntel 	port_fwd_begin_t port_fwd_begin;
2117af75078fSIntel 	port_fwd_end_t  port_fwd_end;
2118af75078fSIntel 	struct rte_port *port;
2119af75078fSIntel 	unsigned int i;
2120af75078fSIntel 	portid_t   pt_id;
2121af75078fSIntel 
21225a8fb55cSReshma Pattan 	if (strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") == 0 && !nb_rxq)
21235a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE, "rxq are 0, cannot use rxonly fwd mode\n");
21245a8fb55cSReshma Pattan 
21255a8fb55cSReshma Pattan 	if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 && !nb_txq)
21265a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE, "txq are 0, cannot use txonly fwd mode\n");
21275a8fb55cSReshma Pattan 
21285a8fb55cSReshma Pattan 	if ((strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") != 0 &&
21295a8fb55cSReshma Pattan 		strcmp(cur_fwd_eng->fwd_mode_name, "txonly") != 0) &&
21305a8fb55cSReshma Pattan 		(!nb_rxq || !nb_txq))
21315a8fb55cSReshma Pattan 		rte_exit(EXIT_FAILURE,
21325a8fb55cSReshma Pattan 			"Either rxq or txq are 0, cannot use %s fwd mode\n",
21335a8fb55cSReshma Pattan 			cur_fwd_eng->fwd_mode_name);
21345a8fb55cSReshma Pattan 
2135ce8d5614SIntel 	if (all_ports_started() == 0) {
2136ce8d5614SIntel 		printf("Not all ports were started\n");
2137ce8d5614SIntel 		return;
2138ce8d5614SIntel 	}
2139af75078fSIntel 	if (test_done == 0) {
2140af75078fSIntel 		printf("Packet forwarding already started\n");
2141af75078fSIntel 		return;
2142af75078fSIntel 	}
2143edf87b4aSBernard Iremonger 
2144edf87b4aSBernard Iremonger 
21457741e4cfSIntel 	if(dcb_test) {
21467741e4cfSIntel 		for (i = 0; i < nb_fwd_ports; i++) {
21477741e4cfSIntel 			pt_id = fwd_ports_ids[i];
21487741e4cfSIntel 			port = &ports[pt_id];
21497741e4cfSIntel 			if (!port->dcb_flag) {
21507741e4cfSIntel 				printf("In DCB mode, all forwarding ports must "
21517741e4cfSIntel                                        "be configured in this mode.\n");
2152013af9b6SIntel 				return;
2153013af9b6SIntel 			}
21547741e4cfSIntel 		}
21557741e4cfSIntel 		if (nb_fwd_lcores == 1) {
21567741e4cfSIntel 			printf("In DCB mode,the nb forwarding cores "
21577741e4cfSIntel                                "should be larger than 1.\n");
21587741e4cfSIntel 			return;
21597741e4cfSIntel 		}
21607741e4cfSIntel 	}
2161af75078fSIntel 	test_done = 0;
21627741e4cfSIntel 
216347a767b2SMatan Azrad 	fwd_config_setup();
216447a767b2SMatan Azrad 
21657741e4cfSIntel 	if(!no_flush_rx)
21667741e4cfSIntel 		flush_fwd_rx_queues();
21677741e4cfSIntel 
2168933617d8SZhihong Wang 	pkt_fwd_config_display(&cur_fwd_config);
2169af75078fSIntel 	rxtx_config_display();
2170af75078fSIntel 
217153324971SDavid Marchand 	fwd_stats_reset();
2172af75078fSIntel 	if (with_tx_first) {
2173af75078fSIntel 		port_fwd_begin = tx_only_engine.port_fwd_begin;
2174af75078fSIntel 		if (port_fwd_begin != NULL) {
2175af75078fSIntel 			for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
2176af75078fSIntel 				(*port_fwd_begin)(fwd_ports_ids[i]);
2177af75078fSIntel 		}
2178acbf77a6SZhihong Wang 		while (with_tx_first--) {
2179acbf77a6SZhihong Wang 			launch_packet_forwarding(
2180acbf77a6SZhihong Wang 					run_one_txonly_burst_on_core);
2181af75078fSIntel 			rte_eal_mp_wait_lcore();
2182acbf77a6SZhihong Wang 		}
2183af75078fSIntel 		port_fwd_end = tx_only_engine.port_fwd_end;
2184af75078fSIntel 		if (port_fwd_end != NULL) {
2185af75078fSIntel 			for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
2186af75078fSIntel 				(*port_fwd_end)(fwd_ports_ids[i]);
2187af75078fSIntel 		}
2188af75078fSIntel 	}
2189af75078fSIntel 	launch_packet_forwarding(start_pkt_forward_on_core);
2190af75078fSIntel }
2191af75078fSIntel 
2192af75078fSIntel void
2193af75078fSIntel stop_packet_forwarding(void)
2194af75078fSIntel {
2195af75078fSIntel 	port_fwd_end_t port_fwd_end;
2196af75078fSIntel 	lcoreid_t lc_id;
219753324971SDavid Marchand 	portid_t pt_id;
219853324971SDavid Marchand 	int i;
2199af75078fSIntel 
2200af75078fSIntel 	if (test_done) {
2201af75078fSIntel 		printf("Packet forwarding not started\n");
2202af75078fSIntel 		return;
2203af75078fSIntel 	}
2204af75078fSIntel 	printf("Telling cores to stop...");
2205af75078fSIntel 	for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++)
2206af75078fSIntel 		fwd_lcores[lc_id]->stopped = 1;
2207af75078fSIntel 	printf("\nWaiting for lcores to finish...\n");
2208af75078fSIntel 	rte_eal_mp_wait_lcore();
2209af75078fSIntel 	port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end;
2210af75078fSIntel 	if (port_fwd_end != NULL) {
2211af75078fSIntel 		for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
2212af75078fSIntel 			pt_id = fwd_ports_ids[i];
2213af75078fSIntel 			(*port_fwd_end)(pt_id);
2214af75078fSIntel 		}
2215af75078fSIntel 	}
2216c185d42cSDavid Marchand 
221753324971SDavid Marchand 	fwd_stats_display();
221858d475b7SJerin Jacob 
2219af75078fSIntel 	printf("\nDone.\n");
2220af75078fSIntel 	test_done = 1;
2221af75078fSIntel }
2222af75078fSIntel 
2223cfae07fdSOuyang Changchun void
2224cfae07fdSOuyang Changchun dev_set_link_up(portid_t pid)
2225cfae07fdSOuyang Changchun {
2226492ab604SZhiyong Yang 	if (rte_eth_dev_set_link_up(pid) < 0)
2227cfae07fdSOuyang Changchun 		printf("\nSet link up fail.\n");
2228cfae07fdSOuyang Changchun }
2229cfae07fdSOuyang Changchun 
2230cfae07fdSOuyang Changchun void
2231cfae07fdSOuyang Changchun dev_set_link_down(portid_t pid)
2232cfae07fdSOuyang Changchun {
2233492ab604SZhiyong Yang 	if (rte_eth_dev_set_link_down(pid) < 0)
2234cfae07fdSOuyang Changchun 		printf("\nSet link down fail.\n");
2235cfae07fdSOuyang Changchun }
2236cfae07fdSOuyang Changchun 
2237ce8d5614SIntel static int
2238ce8d5614SIntel all_ports_started(void)
2239ce8d5614SIntel {
2240ce8d5614SIntel 	portid_t pi;
2241ce8d5614SIntel 	struct rte_port *port;
2242ce8d5614SIntel 
22437d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
2244ce8d5614SIntel 		port = &ports[pi];
2245ce8d5614SIntel 		/* Check if there is a port which is not started */
224641b05095SBernard Iremonger 		if ((port->port_status != RTE_PORT_STARTED) &&
224741b05095SBernard Iremonger 			(port->slave_flag == 0))
2248ce8d5614SIntel 			return 0;
2249ce8d5614SIntel 	}
2250ce8d5614SIntel 
2251ce8d5614SIntel 	/* No port is not started */
2252ce8d5614SIntel 	return 1;
2253ce8d5614SIntel }
2254ce8d5614SIntel 
2255148f963fSBruce Richardson int
22566018eb8cSShahaf Shuler port_is_stopped(portid_t port_id)
22576018eb8cSShahaf Shuler {
22586018eb8cSShahaf Shuler 	struct rte_port *port = &ports[port_id];
22596018eb8cSShahaf Shuler 
22606018eb8cSShahaf Shuler 	if ((port->port_status != RTE_PORT_STOPPED) &&
22616018eb8cSShahaf Shuler 	    (port->slave_flag == 0))
22626018eb8cSShahaf Shuler 		return 0;
22636018eb8cSShahaf Shuler 	return 1;
22646018eb8cSShahaf Shuler }
22656018eb8cSShahaf Shuler 
22666018eb8cSShahaf Shuler int
2267edab33b1STetsuya Mukawa all_ports_stopped(void)
2268edab33b1STetsuya Mukawa {
2269edab33b1STetsuya Mukawa 	portid_t pi;
2270edab33b1STetsuya Mukawa 
22717d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
22726018eb8cSShahaf Shuler 		if (!port_is_stopped(pi))
2273edab33b1STetsuya Mukawa 			return 0;
2274edab33b1STetsuya Mukawa 	}
2275edab33b1STetsuya Mukawa 
2276edab33b1STetsuya Mukawa 	return 1;
2277edab33b1STetsuya Mukawa }
2278edab33b1STetsuya Mukawa 
2279edab33b1STetsuya Mukawa int
2280edab33b1STetsuya Mukawa port_is_started(portid_t port_id)
2281edab33b1STetsuya Mukawa {
2282edab33b1STetsuya Mukawa 	if (port_id_is_invalid(port_id, ENABLED_WARN))
2283edab33b1STetsuya Mukawa 		return 0;
2284edab33b1STetsuya Mukawa 
2285edab33b1STetsuya Mukawa 	if (ports[port_id].port_status != RTE_PORT_STARTED)
2286edab33b1STetsuya Mukawa 		return 0;
2287edab33b1STetsuya Mukawa 
2288edab33b1STetsuya Mukawa 	return 1;
2289edab33b1STetsuya Mukawa }
2290edab33b1STetsuya Mukawa 
22911c69df45SOri Kam /* Configure the Rx and Tx hairpin queues for the selected port. */
22921c69df45SOri Kam static int
229301817b10SBing Zhao setup_hairpin_queues(portid_t pi, portid_t p_pi, uint16_t cnt_pi)
22941c69df45SOri Kam {
22951c69df45SOri Kam 	queueid_t qi;
22961c69df45SOri Kam 	struct rte_eth_hairpin_conf hairpin_conf = {
22971c69df45SOri Kam 		.peer_count = 1,
22981c69df45SOri Kam 	};
22991c69df45SOri Kam 	int i;
23001c69df45SOri Kam 	int diag;
23011c69df45SOri Kam 	struct rte_port *port = &ports[pi];
230201817b10SBing Zhao 	uint16_t peer_rx_port = pi;
230301817b10SBing Zhao 	uint16_t peer_tx_port = pi;
230401817b10SBing Zhao 	uint32_t manual = 1;
230501817b10SBing Zhao 	uint32_t tx_exp = hairpin_mode & 0x10;
230601817b10SBing Zhao 
230701817b10SBing Zhao 	if (!(hairpin_mode & 0xf)) {
230801817b10SBing Zhao 		peer_rx_port = pi;
230901817b10SBing Zhao 		peer_tx_port = pi;
231001817b10SBing Zhao 		manual = 0;
231101817b10SBing Zhao 	} else if (hairpin_mode & 0x1) {
231201817b10SBing Zhao 		peer_tx_port = rte_eth_find_next_owned_by(pi + 1,
231301817b10SBing Zhao 						       RTE_ETH_DEV_NO_OWNER);
231401817b10SBing Zhao 		if (peer_tx_port >= RTE_MAX_ETHPORTS)
231501817b10SBing Zhao 			peer_tx_port = rte_eth_find_next_owned_by(0,
231601817b10SBing Zhao 						RTE_ETH_DEV_NO_OWNER);
231701817b10SBing Zhao 		if (p_pi != RTE_MAX_ETHPORTS) {
231801817b10SBing Zhao 			peer_rx_port = p_pi;
231901817b10SBing Zhao 		} else {
232001817b10SBing Zhao 			uint16_t next_pi;
232101817b10SBing Zhao 
232201817b10SBing Zhao 			/* Last port will be the peer RX port of the first. */
232301817b10SBing Zhao 			RTE_ETH_FOREACH_DEV(next_pi)
232401817b10SBing Zhao 				peer_rx_port = next_pi;
232501817b10SBing Zhao 		}
232601817b10SBing Zhao 		manual = 1;
232701817b10SBing Zhao 	} else if (hairpin_mode & 0x2) {
232801817b10SBing Zhao 		if (cnt_pi & 0x1) {
232901817b10SBing Zhao 			peer_rx_port = p_pi;
233001817b10SBing Zhao 		} else {
233101817b10SBing Zhao 			peer_rx_port = rte_eth_find_next_owned_by(pi + 1,
233201817b10SBing Zhao 						RTE_ETH_DEV_NO_OWNER);
233301817b10SBing Zhao 			if (peer_rx_port >= RTE_MAX_ETHPORTS)
233401817b10SBing Zhao 				peer_rx_port = pi;
233501817b10SBing Zhao 		}
233601817b10SBing Zhao 		peer_tx_port = peer_rx_port;
233701817b10SBing Zhao 		manual = 1;
233801817b10SBing Zhao 	}
23391c69df45SOri Kam 
23401c69df45SOri Kam 	for (qi = nb_txq, i = 0; qi < nb_hairpinq + nb_txq; qi++) {
234101817b10SBing Zhao 		hairpin_conf.peers[0].port = peer_rx_port;
23421c69df45SOri Kam 		hairpin_conf.peers[0].queue = i + nb_rxq;
234301817b10SBing Zhao 		hairpin_conf.manual_bind = !!manual;
234401817b10SBing Zhao 		hairpin_conf.tx_explicit = !!tx_exp;
23451c69df45SOri Kam 		diag = rte_eth_tx_hairpin_queue_setup
23461c69df45SOri Kam 			(pi, qi, nb_txd, &hairpin_conf);
23471c69df45SOri Kam 		i++;
23481c69df45SOri Kam 		if (diag == 0)
23491c69df45SOri Kam 			continue;
23501c69df45SOri Kam 
23511c69df45SOri Kam 		/* Fail to setup rx queue, return */
23521c69df45SOri Kam 		if (rte_atomic16_cmpset(&(port->port_status),
23531c69df45SOri Kam 					RTE_PORT_HANDLING,
23541c69df45SOri Kam 					RTE_PORT_STOPPED) == 0)
23551c69df45SOri Kam 			printf("Port %d can not be set back "
23561c69df45SOri Kam 					"to stopped\n", pi);
23571c69df45SOri Kam 		printf("Fail to configure port %d hairpin "
23581c69df45SOri Kam 				"queues\n", pi);
23591c69df45SOri Kam 		/* try to reconfigure queues next time */
23601c69df45SOri Kam 		port->need_reconfig_queues = 1;
23611c69df45SOri Kam 		return -1;
23621c69df45SOri Kam 	}
23631c69df45SOri Kam 	for (qi = nb_rxq, i = 0; qi < nb_hairpinq + nb_rxq; qi++) {
236401817b10SBing Zhao 		hairpin_conf.peers[0].port = peer_tx_port;
23651c69df45SOri Kam 		hairpin_conf.peers[0].queue = i + nb_txq;
236601817b10SBing Zhao 		hairpin_conf.manual_bind = !!manual;
236701817b10SBing Zhao 		hairpin_conf.tx_explicit = !!tx_exp;
23681c69df45SOri Kam 		diag = rte_eth_rx_hairpin_queue_setup
23691c69df45SOri Kam 			(pi, qi, nb_rxd, &hairpin_conf);
23701c69df45SOri Kam 		i++;
23711c69df45SOri Kam 		if (diag == 0)
23721c69df45SOri Kam 			continue;
23731c69df45SOri Kam 
23741c69df45SOri Kam 		/* Fail to setup rx queue, return */
23751c69df45SOri Kam 		if (rte_atomic16_cmpset(&(port->port_status),
23761c69df45SOri Kam 					RTE_PORT_HANDLING,
23771c69df45SOri Kam 					RTE_PORT_STOPPED) == 0)
23781c69df45SOri Kam 			printf("Port %d can not be set back "
23791c69df45SOri Kam 					"to stopped\n", pi);
23801c69df45SOri Kam 		printf("Fail to configure port %d hairpin "
23811c69df45SOri Kam 				"queues\n", pi);
23821c69df45SOri Kam 		/* try to reconfigure queues next time */
23831c69df45SOri Kam 		port->need_reconfig_queues = 1;
23841c69df45SOri Kam 		return -1;
23851c69df45SOri Kam 	}
23861c69df45SOri Kam 	return 0;
23871c69df45SOri Kam }
23881c69df45SOri Kam 
23892befc67fSViacheslav Ovsiienko /* Configure the Rx with optional split. */
23902befc67fSViacheslav Ovsiienko int
23912befc67fSViacheslav Ovsiienko rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
23922befc67fSViacheslav Ovsiienko 	       uint16_t nb_rx_desc, unsigned int socket_id,
23932befc67fSViacheslav Ovsiienko 	       struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp)
23942befc67fSViacheslav Ovsiienko {
23952befc67fSViacheslav Ovsiienko 	union rte_eth_rxseg rx_useg[MAX_SEGS_BUFFER_SPLIT] = {};
23962befc67fSViacheslav Ovsiienko 	unsigned int i, mp_n;
23972befc67fSViacheslav Ovsiienko 	int ret;
23982befc67fSViacheslav Ovsiienko 
23992befc67fSViacheslav Ovsiienko 	if (rx_pkt_nb_segs <= 1 ||
24002befc67fSViacheslav Ovsiienko 	    (rx_conf->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) == 0) {
24012befc67fSViacheslav Ovsiienko 		rx_conf->rx_seg = NULL;
24022befc67fSViacheslav Ovsiienko 		rx_conf->rx_nseg = 0;
24032befc67fSViacheslav Ovsiienko 		ret = rte_eth_rx_queue_setup(port_id, rx_queue_id,
24042befc67fSViacheslav Ovsiienko 					     nb_rx_desc, socket_id,
24052befc67fSViacheslav Ovsiienko 					     rx_conf, mp);
24062befc67fSViacheslav Ovsiienko 		return ret;
24072befc67fSViacheslav Ovsiienko 	}
24082befc67fSViacheslav Ovsiienko 	for (i = 0; i < rx_pkt_nb_segs; i++) {
24092befc67fSViacheslav Ovsiienko 		struct rte_eth_rxseg_split *rx_seg = &rx_useg[i].split;
24102befc67fSViacheslav Ovsiienko 		struct rte_mempool *mpx;
24112befc67fSViacheslav Ovsiienko 		/*
24122befc67fSViacheslav Ovsiienko 		 * Use last valid pool for the segments with number
24132befc67fSViacheslav Ovsiienko 		 * exceeding the pool index.
24142befc67fSViacheslav Ovsiienko 		 */
24152befc67fSViacheslav Ovsiienko 		mp_n = (i > mbuf_data_size_n) ? mbuf_data_size_n - 1 : i;
24162befc67fSViacheslav Ovsiienko 		mpx = mbuf_pool_find(socket_id, mp_n);
24172befc67fSViacheslav Ovsiienko 		/* Handle zero as mbuf data buffer size. */
24182befc67fSViacheslav Ovsiienko 		rx_seg->length = rx_pkt_seg_lengths[i] ?
24192befc67fSViacheslav Ovsiienko 				   rx_pkt_seg_lengths[i] :
24202befc67fSViacheslav Ovsiienko 				   mbuf_data_size[mp_n];
24212befc67fSViacheslav Ovsiienko 		rx_seg->offset = i < rx_pkt_nb_offs ?
24222befc67fSViacheslav Ovsiienko 				   rx_pkt_seg_offsets[i] : 0;
24232befc67fSViacheslav Ovsiienko 		rx_seg->mp = mpx ? mpx : mp;
24242befc67fSViacheslav Ovsiienko 	}
24252befc67fSViacheslav Ovsiienko 	rx_conf->rx_nseg = rx_pkt_nb_segs;
24262befc67fSViacheslav Ovsiienko 	rx_conf->rx_seg = rx_useg;
24272befc67fSViacheslav Ovsiienko 	ret = rte_eth_rx_queue_setup(port_id, rx_queue_id, nb_rx_desc,
24282befc67fSViacheslav Ovsiienko 				    socket_id, rx_conf, NULL);
24292befc67fSViacheslav Ovsiienko 	rx_conf->rx_seg = NULL;
24302befc67fSViacheslav Ovsiienko 	rx_conf->rx_nseg = 0;
24312befc67fSViacheslav Ovsiienko 	return ret;
24322befc67fSViacheslav Ovsiienko }
24332befc67fSViacheslav Ovsiienko 
2434edab33b1STetsuya Mukawa int
2435ce8d5614SIntel start_port(portid_t pid)
2436ce8d5614SIntel {
243792d2703eSMichael Qiu 	int diag, need_check_link_status = -1;
2438ce8d5614SIntel 	portid_t pi;
243901817b10SBing Zhao 	portid_t p_pi = RTE_MAX_ETHPORTS;
244001817b10SBing Zhao 	portid_t pl[RTE_MAX_ETHPORTS];
244101817b10SBing Zhao 	portid_t peer_pl[RTE_MAX_ETHPORTS];
244201817b10SBing Zhao 	uint16_t cnt_pi = 0;
244301817b10SBing Zhao 	uint16_t cfg_pi = 0;
244401817b10SBing Zhao 	int peer_pi;
2445ce8d5614SIntel 	queueid_t qi;
2446ce8d5614SIntel 	struct rte_port *port;
24476d13ea8eSOlivier Matz 	struct rte_ether_addr mac_addr;
24481c69df45SOri Kam 	struct rte_eth_hairpin_cap cap;
2449ce8d5614SIntel 
24504468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
24514468635fSMichael Qiu 		return 0;
24524468635fSMichael Qiu 
2453ce8d5614SIntel 	if(dcb_config)
2454ce8d5614SIntel 		dcb_test = 1;
24557d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
2456edab33b1STetsuya Mukawa 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
2457ce8d5614SIntel 			continue;
2458ce8d5614SIntel 
245992d2703eSMichael Qiu 		need_check_link_status = 0;
2460ce8d5614SIntel 		port = &ports[pi];
2461ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED,
2462ce8d5614SIntel 						 RTE_PORT_HANDLING) == 0) {
2463ce8d5614SIntel 			printf("Port %d is now not stopped\n", pi);
2464ce8d5614SIntel 			continue;
2465ce8d5614SIntel 		}
2466ce8d5614SIntel 
2467ce8d5614SIntel 		if (port->need_reconfig > 0) {
2468ce8d5614SIntel 			port->need_reconfig = 0;
2469ce8d5614SIntel 
24707ee3e944SVasily Philipov 			if (flow_isolate_all) {
24717ee3e944SVasily Philipov 				int ret = port_flow_isolate(pi, 1);
24727ee3e944SVasily Philipov 				if (ret) {
24737ee3e944SVasily Philipov 					printf("Failed to apply isolated"
24747ee3e944SVasily Philipov 					       " mode on port %d\n", pi);
24757ee3e944SVasily Philipov 					return -1;
24767ee3e944SVasily Philipov 				}
24777ee3e944SVasily Philipov 			}
2478b5b38ed8SRaslan Darawsheh 			configure_rxtx_dump_callbacks(0);
24795706de65SJulien Cretin 			printf("Configuring Port %d (socket %u)\n", pi,
248020a0286fSLiu Xiaofeng 					port->socket_id);
24811c69df45SOri Kam 			if (nb_hairpinq > 0 &&
24821c69df45SOri Kam 			    rte_eth_dev_hairpin_capability_get(pi, &cap)) {
24831c69df45SOri Kam 				printf("Port %d doesn't support hairpin "
24841c69df45SOri Kam 				       "queues\n", pi);
24851c69df45SOri Kam 				return -1;
24861c69df45SOri Kam 			}
2487ce8d5614SIntel 			/* configure port */
24881c69df45SOri Kam 			diag = rte_eth_dev_configure(pi, nb_rxq + nb_hairpinq,
24891c69df45SOri Kam 						     nb_txq + nb_hairpinq,
2490ce8d5614SIntel 						     &(port->dev_conf));
2491ce8d5614SIntel 			if (diag != 0) {
2492ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
2493ce8d5614SIntel 				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
2494ce8d5614SIntel 					printf("Port %d can not be set back "
2495ce8d5614SIntel 							"to stopped\n", pi);
2496ce8d5614SIntel 				printf("Fail to configure port %d\n", pi);
2497ce8d5614SIntel 				/* try to reconfigure port next time */
2498ce8d5614SIntel 				port->need_reconfig = 1;
2499148f963fSBruce Richardson 				return -1;
2500ce8d5614SIntel 			}
2501ce8d5614SIntel 		}
2502ce8d5614SIntel 		if (port->need_reconfig_queues > 0) {
2503ce8d5614SIntel 			port->need_reconfig_queues = 0;
2504ce8d5614SIntel 			/* setup tx queues */
2505ce8d5614SIntel 			for (qi = 0; qi < nb_txq; qi++) {
2506b6ea6408SIntel 				if ((numa_support) &&
2507b6ea6408SIntel 					(txring_numa[pi] != NUMA_NO_CONFIG))
2508b6ea6408SIntel 					diag = rte_eth_tx_queue_setup(pi, qi,
2509d44f8a48SQi Zhang 						port->nb_tx_desc[qi],
2510d44f8a48SQi Zhang 						txring_numa[pi],
2511d44f8a48SQi Zhang 						&(port->tx_conf[qi]));
2512b6ea6408SIntel 				else
2513b6ea6408SIntel 					diag = rte_eth_tx_queue_setup(pi, qi,
2514d44f8a48SQi Zhang 						port->nb_tx_desc[qi],
2515d44f8a48SQi Zhang 						port->socket_id,
2516d44f8a48SQi Zhang 						&(port->tx_conf[qi]));
2517b6ea6408SIntel 
2518ce8d5614SIntel 				if (diag == 0)
2519ce8d5614SIntel 					continue;
2520ce8d5614SIntel 
2521ce8d5614SIntel 				/* Fail to setup tx queue, return */
2522ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
2523ce8d5614SIntel 							RTE_PORT_HANDLING,
2524ce8d5614SIntel 							RTE_PORT_STOPPED) == 0)
2525ce8d5614SIntel 					printf("Port %d can not be set back "
2526ce8d5614SIntel 							"to stopped\n", pi);
2527d44f8a48SQi Zhang 				printf("Fail to configure port %d tx queues\n",
2528d44f8a48SQi Zhang 				       pi);
2529ce8d5614SIntel 				/* try to reconfigure queues next time */
2530ce8d5614SIntel 				port->need_reconfig_queues = 1;
2531148f963fSBruce Richardson 				return -1;
2532ce8d5614SIntel 			}
2533ce8d5614SIntel 			for (qi = 0; qi < nb_rxq; qi++) {
2534d44f8a48SQi Zhang 				/* setup rx queues */
2535b6ea6408SIntel 				if ((numa_support) &&
2536b6ea6408SIntel 					(rxring_numa[pi] != NUMA_NO_CONFIG)) {
2537b6ea6408SIntel 					struct rte_mempool * mp =
253826cbb419SViacheslav Ovsiienko 						mbuf_pool_find
253926cbb419SViacheslav Ovsiienko 							(rxring_numa[pi], 0);
2540b6ea6408SIntel 					if (mp == NULL) {
2541b6ea6408SIntel 						printf("Failed to setup RX queue:"
2542b6ea6408SIntel 							"No mempool allocation"
2543b6ea6408SIntel 							" on the socket %d\n",
2544b6ea6408SIntel 							rxring_numa[pi]);
2545148f963fSBruce Richardson 						return -1;
2546b6ea6408SIntel 					}
2547b6ea6408SIntel 
25482befc67fSViacheslav Ovsiienko 					diag = rx_queue_setup(pi, qi,
2549d4930794SFerruh Yigit 					     port->nb_rx_desc[qi],
2550d44f8a48SQi Zhang 					     rxring_numa[pi],
2551d44f8a48SQi Zhang 					     &(port->rx_conf[qi]),
2552d44f8a48SQi Zhang 					     mp);
25531e1d6bddSBernard Iremonger 				} else {
25541e1d6bddSBernard Iremonger 					struct rte_mempool *mp =
255526cbb419SViacheslav Ovsiienko 						mbuf_pool_find
255626cbb419SViacheslav Ovsiienko 							(port->socket_id, 0);
25571e1d6bddSBernard Iremonger 					if (mp == NULL) {
25581e1d6bddSBernard Iremonger 						printf("Failed to setup RX queue:"
25591e1d6bddSBernard Iremonger 							"No mempool allocation"
25601e1d6bddSBernard Iremonger 							" on the socket %d\n",
25611e1d6bddSBernard Iremonger 							port->socket_id);
25621e1d6bddSBernard Iremonger 						return -1;
2563b6ea6408SIntel 					}
25642befc67fSViacheslav Ovsiienko 					diag = rx_queue_setup(pi, qi,
2565d4930794SFerruh Yigit 					     port->nb_rx_desc[qi],
2566d44f8a48SQi Zhang 					     port->socket_id,
2567d44f8a48SQi Zhang 					     &(port->rx_conf[qi]),
2568d44f8a48SQi Zhang 					     mp);
25691e1d6bddSBernard Iremonger 				}
2570ce8d5614SIntel 				if (diag == 0)
2571ce8d5614SIntel 					continue;
2572ce8d5614SIntel 
2573ce8d5614SIntel 				/* Fail to setup rx queue, return */
2574ce8d5614SIntel 				if (rte_atomic16_cmpset(&(port->port_status),
2575ce8d5614SIntel 							RTE_PORT_HANDLING,
2576ce8d5614SIntel 							RTE_PORT_STOPPED) == 0)
2577ce8d5614SIntel 					printf("Port %d can not be set back "
2578ce8d5614SIntel 							"to stopped\n", pi);
2579d44f8a48SQi Zhang 				printf("Fail to configure port %d rx queues\n",
2580d44f8a48SQi Zhang 				       pi);
2581ce8d5614SIntel 				/* try to reconfigure queues next time */
2582ce8d5614SIntel 				port->need_reconfig_queues = 1;
2583148f963fSBruce Richardson 				return -1;
2584ce8d5614SIntel 			}
25851c69df45SOri Kam 			/* setup hairpin queues */
258601817b10SBing Zhao 			if (setup_hairpin_queues(pi, p_pi, cnt_pi) != 0)
25871c69df45SOri Kam 				return -1;
2588ce8d5614SIntel 		}
2589b5b38ed8SRaslan Darawsheh 		configure_rxtx_dump_callbacks(verbose_level);
2590b0a9354aSPavan Nikhilesh 		if (clear_ptypes) {
2591b0a9354aSPavan Nikhilesh 			diag = rte_eth_dev_set_ptypes(pi, RTE_PTYPE_UNKNOWN,
2592b0a9354aSPavan Nikhilesh 					NULL, 0);
2593b0a9354aSPavan Nikhilesh 			if (diag < 0)
2594b0a9354aSPavan Nikhilesh 				printf(
2595b0a9354aSPavan Nikhilesh 				"Port %d: Failed to disable Ptype parsing\n",
2596b0a9354aSPavan Nikhilesh 				pi);
2597b0a9354aSPavan Nikhilesh 		}
2598b0a9354aSPavan Nikhilesh 
259901817b10SBing Zhao 		p_pi = pi;
260001817b10SBing Zhao 		cnt_pi++;
260101817b10SBing Zhao 
2602ce8d5614SIntel 		/* start port */
2603ce8d5614SIntel 		if (rte_eth_dev_start(pi) < 0) {
2604ce8d5614SIntel 			printf("Fail to start port %d\n", pi);
2605ce8d5614SIntel 
2606ce8d5614SIntel 			/* Fail to setup rx queue, return */
2607ce8d5614SIntel 			if (rte_atomic16_cmpset(&(port->port_status),
2608ce8d5614SIntel 				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
2609ce8d5614SIntel 				printf("Port %d can not be set back to "
2610ce8d5614SIntel 							"stopped\n", pi);
2611ce8d5614SIntel 			continue;
2612ce8d5614SIntel 		}
2613ce8d5614SIntel 
2614ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
2615ce8d5614SIntel 			RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0)
2616ce8d5614SIntel 			printf("Port %d can not be set into started\n", pi);
2617ce8d5614SIntel 
2618a5279d25SIgor Romanov 		if (eth_macaddr_get_print_err(pi, &mac_addr) == 0)
2619d8c89163SZijie Pan 			printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi,
26202950a769SDeclan Doherty 				mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
26212950a769SDeclan Doherty 				mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
26222950a769SDeclan Doherty 				mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]);
2623d8c89163SZijie Pan 
2624ce8d5614SIntel 		/* at least one port started, need checking link status */
2625ce8d5614SIntel 		need_check_link_status = 1;
262601817b10SBing Zhao 
262701817b10SBing Zhao 		pl[cfg_pi++] = pi;
2628ce8d5614SIntel 	}
2629ce8d5614SIntel 
263092d2703eSMichael Qiu 	if (need_check_link_status == 1 && !no_link_check)
2631edab33b1STetsuya Mukawa 		check_all_ports_link_status(RTE_PORT_ALL);
263292d2703eSMichael Qiu 	else if (need_check_link_status == 0)
2633ce8d5614SIntel 		printf("Please stop the ports first\n");
2634ce8d5614SIntel 
263501817b10SBing Zhao 	if (hairpin_mode & 0xf) {
263601817b10SBing Zhao 		uint16_t i;
263701817b10SBing Zhao 		int j;
263801817b10SBing Zhao 
263901817b10SBing Zhao 		/* bind all started hairpin ports */
264001817b10SBing Zhao 		for (i = 0; i < cfg_pi; i++) {
264101817b10SBing Zhao 			pi = pl[i];
264201817b10SBing Zhao 			/* bind current Tx to all peer Rx */
264301817b10SBing Zhao 			peer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,
264401817b10SBing Zhao 							RTE_MAX_ETHPORTS, 1);
264501817b10SBing Zhao 			if (peer_pi < 0)
264601817b10SBing Zhao 				return peer_pi;
264701817b10SBing Zhao 			for (j = 0; j < peer_pi; j++) {
264801817b10SBing Zhao 				if (!port_is_started(peer_pl[j]))
264901817b10SBing Zhao 					continue;
265001817b10SBing Zhao 				diag = rte_eth_hairpin_bind(pi, peer_pl[j]);
265101817b10SBing Zhao 				if (diag < 0) {
265201817b10SBing Zhao 					printf("Error during binding hairpin"
265301817b10SBing Zhao 					       " Tx port %u to %u: %s\n",
265401817b10SBing Zhao 					       pi, peer_pl[j],
265501817b10SBing Zhao 					       rte_strerror(-diag));
265601817b10SBing Zhao 					return -1;
265701817b10SBing Zhao 				}
265801817b10SBing Zhao 			}
265901817b10SBing Zhao 			/* bind all peer Tx to current Rx */
266001817b10SBing Zhao 			peer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,
266101817b10SBing Zhao 							RTE_MAX_ETHPORTS, 0);
266201817b10SBing Zhao 			if (peer_pi < 0)
266301817b10SBing Zhao 				return peer_pi;
266401817b10SBing Zhao 			for (j = 0; j < peer_pi; j++) {
266501817b10SBing Zhao 				if (!port_is_started(peer_pl[j]))
266601817b10SBing Zhao 					continue;
266701817b10SBing Zhao 				diag = rte_eth_hairpin_bind(peer_pl[j], pi);
266801817b10SBing Zhao 				if (diag < 0) {
266901817b10SBing Zhao 					printf("Error during binding hairpin"
267001817b10SBing Zhao 					       " Tx port %u to %u: %s\n",
267101817b10SBing Zhao 					       peer_pl[j], pi,
267201817b10SBing Zhao 					       rte_strerror(-diag));
267301817b10SBing Zhao 					return -1;
267401817b10SBing Zhao 				}
267501817b10SBing Zhao 			}
267601817b10SBing Zhao 		}
267701817b10SBing Zhao 	}
267801817b10SBing Zhao 
2679ce8d5614SIntel 	printf("Done\n");
2680148f963fSBruce Richardson 	return 0;
2681ce8d5614SIntel }
2682ce8d5614SIntel 
2683ce8d5614SIntel void
2684ce8d5614SIntel stop_port(portid_t pid)
2685ce8d5614SIntel {
2686ce8d5614SIntel 	portid_t pi;
2687ce8d5614SIntel 	struct rte_port *port;
2688ce8d5614SIntel 	int need_check_link_status = 0;
268901817b10SBing Zhao 	portid_t peer_pl[RTE_MAX_ETHPORTS];
269001817b10SBing Zhao 	int peer_pi;
2691ce8d5614SIntel 
2692ce8d5614SIntel 	if (dcb_test) {
2693ce8d5614SIntel 		dcb_test = 0;
2694ce8d5614SIntel 		dcb_config = 0;
2695ce8d5614SIntel 	}
26964468635fSMichael Qiu 
26974468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
26984468635fSMichael Qiu 		return;
26994468635fSMichael Qiu 
2700ce8d5614SIntel 	printf("Stopping ports...\n");
2701ce8d5614SIntel 
27027d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
27034468635fSMichael Qiu 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
2704ce8d5614SIntel 			continue;
2705ce8d5614SIntel 
2706a8ef3e3aSBernard Iremonger 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
2707a8ef3e3aSBernard Iremonger 			printf("Please remove port %d from forwarding configuration.\n", pi);
2708a8ef3e3aSBernard Iremonger 			continue;
2709a8ef3e3aSBernard Iremonger 		}
2710a8ef3e3aSBernard Iremonger 
27110e545d30SBernard Iremonger 		if (port_is_bonding_slave(pi)) {
27120e545d30SBernard Iremonger 			printf("Please remove port %d from bonded device.\n", pi);
27130e545d30SBernard Iremonger 			continue;
27140e545d30SBernard Iremonger 		}
27150e545d30SBernard Iremonger 
2716ce8d5614SIntel 		port = &ports[pi];
2717ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED,
2718ce8d5614SIntel 						RTE_PORT_HANDLING) == 0)
2719ce8d5614SIntel 			continue;
2720ce8d5614SIntel 
272101817b10SBing Zhao 		if (hairpin_mode & 0xf) {
272201817b10SBing Zhao 			int j;
272301817b10SBing Zhao 
272401817b10SBing Zhao 			rte_eth_hairpin_unbind(pi, RTE_MAX_ETHPORTS);
272501817b10SBing Zhao 			/* unbind all peer Tx from current Rx */
272601817b10SBing Zhao 			peer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,
272701817b10SBing Zhao 							RTE_MAX_ETHPORTS, 0);
272801817b10SBing Zhao 			if (peer_pi < 0)
272901817b10SBing Zhao 				continue;
273001817b10SBing Zhao 			for (j = 0; j < peer_pi; j++) {
273101817b10SBing Zhao 				if (!port_is_started(peer_pl[j]))
273201817b10SBing Zhao 					continue;
273301817b10SBing Zhao 				rte_eth_hairpin_unbind(peer_pl[j], pi);
273401817b10SBing Zhao 			}
273501817b10SBing Zhao 		}
273601817b10SBing Zhao 
2737e62c5a12SIvan Ilchenko 		if (rte_eth_dev_stop(pi) != 0)
2738e62c5a12SIvan Ilchenko 			RTE_LOG(ERR, EAL, "rte_eth_dev_stop failed for port %u\n",
2739e62c5a12SIvan Ilchenko 				pi);
2740ce8d5614SIntel 
2741ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
2742ce8d5614SIntel 			RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
2743ce8d5614SIntel 			printf("Port %d can not be set into stopped\n", pi);
2744ce8d5614SIntel 		need_check_link_status = 1;
2745ce8d5614SIntel 	}
2746bc202406SDavid Marchand 	if (need_check_link_status && !no_link_check)
2747edab33b1STetsuya Mukawa 		check_all_ports_link_status(RTE_PORT_ALL);
2748ce8d5614SIntel 
2749ce8d5614SIntel 	printf("Done\n");
2750ce8d5614SIntel }
2751ce8d5614SIntel 
2752ce6959bfSWisam Jaddo static void
27534f1de450SThomas Monjalon remove_invalid_ports_in(portid_t *array, portid_t *total)
2754ce6959bfSWisam Jaddo {
27554f1de450SThomas Monjalon 	portid_t i;
27564f1de450SThomas Monjalon 	portid_t new_total = 0;
2757ce6959bfSWisam Jaddo 
27584f1de450SThomas Monjalon 	for (i = 0; i < *total; i++)
27594f1de450SThomas Monjalon 		if (!port_id_is_invalid(array[i], DISABLED_WARN)) {
27604f1de450SThomas Monjalon 			array[new_total] = array[i];
27614f1de450SThomas Monjalon 			new_total++;
2762ce6959bfSWisam Jaddo 		}
27634f1de450SThomas Monjalon 	*total = new_total;
27644f1de450SThomas Monjalon }
27654f1de450SThomas Monjalon 
27664f1de450SThomas Monjalon static void
27674f1de450SThomas Monjalon remove_invalid_ports(void)
27684f1de450SThomas Monjalon {
27694f1de450SThomas Monjalon 	remove_invalid_ports_in(ports_ids, &nb_ports);
27704f1de450SThomas Monjalon 	remove_invalid_ports_in(fwd_ports_ids, &nb_fwd_ports);
27714f1de450SThomas Monjalon 	nb_cfg_ports = nb_fwd_ports;
2772ce6959bfSWisam Jaddo }
2773ce6959bfSWisam Jaddo 
2774ce8d5614SIntel void
2775ce8d5614SIntel close_port(portid_t pid)
2776ce8d5614SIntel {
2777ce8d5614SIntel 	portid_t pi;
2778ce8d5614SIntel 	struct rte_port *port;
2779ce8d5614SIntel 
27804468635fSMichael Qiu 	if (port_id_is_invalid(pid, ENABLED_WARN))
27814468635fSMichael Qiu 		return;
27824468635fSMichael Qiu 
2783ce8d5614SIntel 	printf("Closing ports...\n");
2784ce8d5614SIntel 
27857d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pi) {
27864468635fSMichael Qiu 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
2787ce8d5614SIntel 			continue;
2788ce8d5614SIntel 
2789a8ef3e3aSBernard Iremonger 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
2790a8ef3e3aSBernard Iremonger 			printf("Please remove port %d from forwarding configuration.\n", pi);
2791a8ef3e3aSBernard Iremonger 			continue;
2792a8ef3e3aSBernard Iremonger 		}
2793a8ef3e3aSBernard Iremonger 
27940e545d30SBernard Iremonger 		if (port_is_bonding_slave(pi)) {
27950e545d30SBernard Iremonger 			printf("Please remove port %d from bonded device.\n", pi);
27960e545d30SBernard Iremonger 			continue;
27970e545d30SBernard Iremonger 		}
27980e545d30SBernard Iremonger 
2799ce8d5614SIntel 		port = &ports[pi];
2800ce8d5614SIntel 		if (rte_atomic16_cmpset(&(port->port_status),
2801d4e8ad64SMichael Qiu 			RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) {
2802d4e8ad64SMichael Qiu 			printf("Port %d is already closed\n", pi);
2803d4e8ad64SMichael Qiu 			continue;
2804d4e8ad64SMichael Qiu 		}
2805d4e8ad64SMichael Qiu 
2806938a184aSAdrien Mazarguil 		port_flow_flush(pi);
2807ce8d5614SIntel 		rte_eth_dev_close(pi);
2808ce8d5614SIntel 	}
2809ce8d5614SIntel 
281085c6571cSThomas Monjalon 	remove_invalid_ports();
2811ce8d5614SIntel 	printf("Done\n");
2812ce8d5614SIntel }
2813ce8d5614SIntel 
2814edab33b1STetsuya Mukawa void
281597f1e196SWei Dai reset_port(portid_t pid)
281697f1e196SWei Dai {
281797f1e196SWei Dai 	int diag;
281897f1e196SWei Dai 	portid_t pi;
281997f1e196SWei Dai 	struct rte_port *port;
282097f1e196SWei Dai 
282197f1e196SWei Dai 	if (port_id_is_invalid(pid, ENABLED_WARN))
282297f1e196SWei Dai 		return;
282397f1e196SWei Dai 
28241cde1b9aSShougang Wang 	if ((pid == (portid_t)RTE_PORT_ALL && !all_ports_stopped()) ||
28251cde1b9aSShougang Wang 		(pid != (portid_t)RTE_PORT_ALL && !port_is_stopped(pid))) {
28261cde1b9aSShougang Wang 		printf("Can not reset port(s), please stop port(s) first.\n");
28271cde1b9aSShougang Wang 		return;
28281cde1b9aSShougang Wang 	}
28291cde1b9aSShougang Wang 
283097f1e196SWei Dai 	printf("Resetting ports...\n");
283197f1e196SWei Dai 
283297f1e196SWei Dai 	RTE_ETH_FOREACH_DEV(pi) {
283397f1e196SWei Dai 		if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
283497f1e196SWei Dai 			continue;
283597f1e196SWei Dai 
283697f1e196SWei Dai 		if (port_is_forwarding(pi) != 0 && test_done == 0) {
283797f1e196SWei Dai 			printf("Please remove port %d from forwarding "
283897f1e196SWei Dai 			       "configuration.\n", pi);
283997f1e196SWei Dai 			continue;
284097f1e196SWei Dai 		}
284197f1e196SWei Dai 
284297f1e196SWei Dai 		if (port_is_bonding_slave(pi)) {
284397f1e196SWei Dai 			printf("Please remove port %d from bonded device.\n",
284497f1e196SWei Dai 			       pi);
284597f1e196SWei Dai 			continue;
284697f1e196SWei Dai 		}
284797f1e196SWei Dai 
284897f1e196SWei Dai 		diag = rte_eth_dev_reset(pi);
284997f1e196SWei Dai 		if (diag == 0) {
285097f1e196SWei Dai 			port = &ports[pi];
285197f1e196SWei Dai 			port->need_reconfig = 1;
285297f1e196SWei Dai 			port->need_reconfig_queues = 1;
285397f1e196SWei Dai 		} else {
285497f1e196SWei Dai 			printf("Failed to reset port %d. diag=%d\n", pi, diag);
285597f1e196SWei Dai 		}
285697f1e196SWei Dai 	}
285797f1e196SWei Dai 
285897f1e196SWei Dai 	printf("Done\n");
285997f1e196SWei Dai }
286097f1e196SWei Dai 
286197f1e196SWei Dai void
2862edab33b1STetsuya Mukawa attach_port(char *identifier)
2863ce8d5614SIntel {
28644f1ed78eSThomas Monjalon 	portid_t pi;
2865c9cce428SThomas Monjalon 	struct rte_dev_iterator iterator;
2866ce8d5614SIntel 
2867edab33b1STetsuya Mukawa 	printf("Attaching a new port...\n");
2868edab33b1STetsuya Mukawa 
2869edab33b1STetsuya Mukawa 	if (identifier == NULL) {
2870edab33b1STetsuya Mukawa 		printf("Invalid parameters are specified\n");
2871edab33b1STetsuya Mukawa 		return;
2872ce8d5614SIntel 	}
2873ce8d5614SIntel 
287475b66decSIlya Maximets 	if (rte_dev_probe(identifier) < 0) {
2875c9cce428SThomas Monjalon 		TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
2876edab33b1STetsuya Mukawa 		return;
2877c9cce428SThomas Monjalon 	}
2878c9cce428SThomas Monjalon 
28794f1ed78eSThomas Monjalon 	/* first attach mode: event */
28804f1ed78eSThomas Monjalon 	if (setup_on_probe_event) {
28814f1ed78eSThomas Monjalon 		/* new ports are detected on RTE_ETH_EVENT_NEW event */
28824f1ed78eSThomas Monjalon 		for (pi = 0; pi < RTE_MAX_ETHPORTS; pi++)
28834f1ed78eSThomas Monjalon 			if (ports[pi].port_status == RTE_PORT_HANDLING &&
28844f1ed78eSThomas Monjalon 					ports[pi].need_setup != 0)
28854f1ed78eSThomas Monjalon 				setup_attached_port(pi);
28864f1ed78eSThomas Monjalon 		return;
28874f1ed78eSThomas Monjalon 	}
28884f1ed78eSThomas Monjalon 
28894f1ed78eSThomas Monjalon 	/* second attach mode: iterator */
289086fa5de1SThomas Monjalon 	RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator) {
28914f1ed78eSThomas Monjalon 		/* setup ports matching the devargs used for probing */
289286fa5de1SThomas Monjalon 		if (port_is_forwarding(pi))
289386fa5de1SThomas Monjalon 			continue; /* port was already attached before */
2894c9cce428SThomas Monjalon 		setup_attached_port(pi);
2895c9cce428SThomas Monjalon 	}
289686fa5de1SThomas Monjalon }
2897c9cce428SThomas Monjalon 
2898c9cce428SThomas Monjalon static void
2899c9cce428SThomas Monjalon setup_attached_port(portid_t pi)
2900c9cce428SThomas Monjalon {
2901c9cce428SThomas Monjalon 	unsigned int socket_id;
290234fc1051SIvan Ilchenko 	int ret;
2903edab33b1STetsuya Mukawa 
2904931126baSBernard Iremonger 	socket_id = (unsigned)rte_eth_dev_socket_id(pi);
290529841336SPhil Yang 	/* if socket_id is invalid, set to the first available socket. */
2906931126baSBernard Iremonger 	if (check_socket_id(socket_id) < 0)
290729841336SPhil Yang 		socket_id = socket_ids[0];
2908931126baSBernard Iremonger 	reconfig(pi, socket_id);
290934fc1051SIvan Ilchenko 	ret = rte_eth_promiscuous_enable(pi);
291034fc1051SIvan Ilchenko 	if (ret != 0)
291134fc1051SIvan Ilchenko 		printf("Error during enabling promiscuous mode for port %u: %s - ignore\n",
291234fc1051SIvan Ilchenko 			pi, rte_strerror(-ret));
2913edab33b1STetsuya Mukawa 
29144f1de450SThomas Monjalon 	ports_ids[nb_ports++] = pi;
29154f1de450SThomas Monjalon 	fwd_ports_ids[nb_fwd_ports++] = pi;
29164f1de450SThomas Monjalon 	nb_cfg_ports = nb_fwd_ports;
29174f1ed78eSThomas Monjalon 	ports[pi].need_setup = 0;
2918edab33b1STetsuya Mukawa 	ports[pi].port_status = RTE_PORT_STOPPED;
2919edab33b1STetsuya Mukawa 
2920edab33b1STetsuya Mukawa 	printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
2921edab33b1STetsuya Mukawa 	printf("Done\n");
2922edab33b1STetsuya Mukawa }
2923edab33b1STetsuya Mukawa 
29240654d4a8SThomas Monjalon static void
29250654d4a8SThomas Monjalon detach_device(struct rte_device *dev)
29265f4ec54fSChen Jing D(Mark) {
2927f8e5baa2SThomas Monjalon 	portid_t sibling;
2928f8e5baa2SThomas Monjalon 
2929f8e5baa2SThomas Monjalon 	if (dev == NULL) {
2930f8e5baa2SThomas Monjalon 		printf("Device already removed\n");
2931f8e5baa2SThomas Monjalon 		return;
2932f8e5baa2SThomas Monjalon 	}
2933f8e5baa2SThomas Monjalon 
29340654d4a8SThomas Monjalon 	printf("Removing a device...\n");
2935938a184aSAdrien Mazarguil 
29362a449871SThomas Monjalon 	RTE_ETH_FOREACH_DEV_OF(sibling, dev) {
29372a449871SThomas Monjalon 		if (ports[sibling].port_status != RTE_PORT_CLOSED) {
29382a449871SThomas Monjalon 			if (ports[sibling].port_status != RTE_PORT_STOPPED) {
29392a449871SThomas Monjalon 				printf("Port %u not stopped\n", sibling);
29402a449871SThomas Monjalon 				return;
29412a449871SThomas Monjalon 			}
29422a449871SThomas Monjalon 			port_flow_flush(sibling);
29432a449871SThomas Monjalon 		}
29442a449871SThomas Monjalon 	}
29452a449871SThomas Monjalon 
294675b66decSIlya Maximets 	if (rte_dev_remove(dev) < 0) {
2947f8e5baa2SThomas Monjalon 		TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
2948edab33b1STetsuya Mukawa 		return;
29493070419eSGaetan Rivet 	}
29504f1de450SThomas Monjalon 	remove_invalid_ports();
295103ce2c53SMatan Azrad 
29520654d4a8SThomas Monjalon 	printf("Device is detached\n");
2953f8e5baa2SThomas Monjalon 	printf("Now total ports is %d\n", nb_ports);
2954edab33b1STetsuya Mukawa 	printf("Done\n");
2955edab33b1STetsuya Mukawa 	return;
29565f4ec54fSChen Jing D(Mark) }
29575f4ec54fSChen Jing D(Mark) 
2958af75078fSIntel void
29590654d4a8SThomas Monjalon detach_port_device(portid_t port_id)
29600654d4a8SThomas Monjalon {
29610654d4a8SThomas Monjalon 	if (port_id_is_invalid(port_id, ENABLED_WARN))
29620654d4a8SThomas Monjalon 		return;
29630654d4a8SThomas Monjalon 
29640654d4a8SThomas Monjalon 	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
29650654d4a8SThomas Monjalon 		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
29660654d4a8SThomas Monjalon 			printf("Port not stopped\n");
29670654d4a8SThomas Monjalon 			return;
29680654d4a8SThomas Monjalon 		}
29690654d4a8SThomas Monjalon 		printf("Port was not closed\n");
29700654d4a8SThomas Monjalon 	}
29710654d4a8SThomas Monjalon 
29720654d4a8SThomas Monjalon 	detach_device(rte_eth_devices[port_id].device);
29730654d4a8SThomas Monjalon }
29740654d4a8SThomas Monjalon 
29750654d4a8SThomas Monjalon void
29765edee5f6SThomas Monjalon detach_devargs(char *identifier)
297755e51c96SNithin Dabilpuram {
297855e51c96SNithin Dabilpuram 	struct rte_dev_iterator iterator;
297955e51c96SNithin Dabilpuram 	struct rte_devargs da;
298055e51c96SNithin Dabilpuram 	portid_t port_id;
298155e51c96SNithin Dabilpuram 
298255e51c96SNithin Dabilpuram 	printf("Removing a device...\n");
298355e51c96SNithin Dabilpuram 
298455e51c96SNithin Dabilpuram 	memset(&da, 0, sizeof(da));
298555e51c96SNithin Dabilpuram 	if (rte_devargs_parsef(&da, "%s", identifier)) {
298655e51c96SNithin Dabilpuram 		printf("cannot parse identifier\n");
298755e51c96SNithin Dabilpuram 		if (da.args)
298855e51c96SNithin Dabilpuram 			free(da.args);
298955e51c96SNithin Dabilpuram 		return;
299055e51c96SNithin Dabilpuram 	}
299155e51c96SNithin Dabilpuram 
299255e51c96SNithin Dabilpuram 	RTE_ETH_FOREACH_MATCHING_DEV(port_id, identifier, &iterator) {
299355e51c96SNithin Dabilpuram 		if (ports[port_id].port_status != RTE_PORT_CLOSED) {
299455e51c96SNithin Dabilpuram 			if (ports[port_id].port_status != RTE_PORT_STOPPED) {
299555e51c96SNithin Dabilpuram 				printf("Port %u not stopped\n", port_id);
2996149677c9SStephen Hemminger 				rte_eth_iterator_cleanup(&iterator);
299755e51c96SNithin Dabilpuram 				return;
299855e51c96SNithin Dabilpuram 			}
299955e51c96SNithin Dabilpuram 			port_flow_flush(port_id);
300055e51c96SNithin Dabilpuram 		}
300155e51c96SNithin Dabilpuram 	}
300255e51c96SNithin Dabilpuram 
300355e51c96SNithin Dabilpuram 	if (rte_eal_hotplug_remove(da.bus->name, da.name) != 0) {
300455e51c96SNithin Dabilpuram 		TESTPMD_LOG(ERR, "Failed to detach device %s(%s)\n",
300555e51c96SNithin Dabilpuram 			    da.name, da.bus->name);
300655e51c96SNithin Dabilpuram 		return;
300755e51c96SNithin Dabilpuram 	}
300855e51c96SNithin Dabilpuram 
300955e51c96SNithin Dabilpuram 	remove_invalid_ports();
301055e51c96SNithin Dabilpuram 
301155e51c96SNithin Dabilpuram 	printf("Device %s is detached\n", identifier);
301255e51c96SNithin Dabilpuram 	printf("Now total ports is %d\n", nb_ports);
301355e51c96SNithin Dabilpuram 	printf("Done\n");
301455e51c96SNithin Dabilpuram }
301555e51c96SNithin Dabilpuram 
301655e51c96SNithin Dabilpuram void
3017af75078fSIntel pmd_test_exit(void)
3018af75078fSIntel {
3019af75078fSIntel 	portid_t pt_id;
302026cbb419SViacheslav Ovsiienko 	unsigned int i;
3021fb73e096SJeff Guo 	int ret;
3022af75078fSIntel 
30238210ec25SPablo de Lara 	if (test_done == 0)
30248210ec25SPablo de Lara 		stop_packet_forwarding();
30258210ec25SPablo de Lara 
302626cbb419SViacheslav Ovsiienko 	for (i = 0 ; i < RTE_DIM(mempools) ; i++) {
30273a0968c8SShahaf Shuler 		if (mempools[i]) {
30283a0968c8SShahaf Shuler 			if (mp_alloc_type == MP_ALLOC_ANON)
30293a0968c8SShahaf Shuler 				rte_mempool_mem_iter(mempools[i], dma_unmap_cb,
30303a0968c8SShahaf Shuler 						     NULL);
30313a0968c8SShahaf Shuler 		}
30323a0968c8SShahaf Shuler 	}
3033d3a274ceSZhihong Wang 	if (ports != NULL) {
3034d3a274ceSZhihong Wang 		no_link_check = 1;
30357d89b261SGaetan Rivet 		RTE_ETH_FOREACH_DEV(pt_id) {
303608fd782bSCristian Dumitrescu 			printf("\nStopping port %d...\n", pt_id);
3037af75078fSIntel 			fflush(stdout);
3038d3a274ceSZhihong Wang 			stop_port(pt_id);
303908fd782bSCristian Dumitrescu 		}
304008fd782bSCristian Dumitrescu 		RTE_ETH_FOREACH_DEV(pt_id) {
304108fd782bSCristian Dumitrescu 			printf("\nShutting down port %d...\n", pt_id);
304208fd782bSCristian Dumitrescu 			fflush(stdout);
3043d3a274ceSZhihong Wang 			close_port(pt_id);
3044af75078fSIntel 		}
3045d3a274ceSZhihong Wang 	}
3046fb73e096SJeff Guo 
3047fb73e096SJeff Guo 	if (hot_plug) {
3048fb73e096SJeff Guo 		ret = rte_dev_event_monitor_stop();
30492049c511SJeff Guo 		if (ret) {
3050fb73e096SJeff Guo 			RTE_LOG(ERR, EAL,
3051fb73e096SJeff Guo 				"fail to stop device event monitor.");
30522049c511SJeff Guo 			return;
30532049c511SJeff Guo 		}
3054fb73e096SJeff Guo 
30552049c511SJeff Guo 		ret = rte_dev_event_callback_unregister(NULL,
3056cc1bf307SJeff Guo 			dev_event_callback, NULL);
30572049c511SJeff Guo 		if (ret < 0) {
3058fb73e096SJeff Guo 			RTE_LOG(ERR, EAL,
30592049c511SJeff Guo 				"fail to unregister device event callback.\n");
30602049c511SJeff Guo 			return;
30612049c511SJeff Guo 		}
30622049c511SJeff Guo 
30632049c511SJeff Guo 		ret = rte_dev_hotplug_handle_disable();
30642049c511SJeff Guo 		if (ret) {
30652049c511SJeff Guo 			RTE_LOG(ERR, EAL,
30662049c511SJeff Guo 				"fail to disable hotplug handling.\n");
30672049c511SJeff Guo 			return;
30682049c511SJeff Guo 		}
3069fb73e096SJeff Guo 	}
307026cbb419SViacheslav Ovsiienko 	for (i = 0 ; i < RTE_DIM(mempools) ; i++) {
3071401b744dSShahaf Shuler 		if (mempools[i])
3072401b744dSShahaf Shuler 			rte_mempool_free(mempools[i]);
3073401b744dSShahaf Shuler 	}
3074fb73e096SJeff Guo 
3075d3a274ceSZhihong Wang 	printf("\nBye...\n");
3076af75078fSIntel }
3077af75078fSIntel 
3078af75078fSIntel typedef void (*cmd_func_t)(void);
3079af75078fSIntel struct pmd_test_command {
3080af75078fSIntel 	const char *cmd_name;
3081af75078fSIntel 	cmd_func_t cmd_func;
3082af75078fSIntel };
3083af75078fSIntel 
3084ce8d5614SIntel /* Check the link status of all ports in up to 9s, and print them finally */
3085af75078fSIntel static void
3086edab33b1STetsuya Mukawa check_all_ports_link_status(uint32_t port_mask)
3087af75078fSIntel {
3088ce8d5614SIntel #define CHECK_INTERVAL 100 /* 100ms */
3089ce8d5614SIntel #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
3090f8244c63SZhiyong Yang 	portid_t portid;
3091f8244c63SZhiyong Yang 	uint8_t count, all_ports_up, print_flag = 0;
3092ce8d5614SIntel 	struct rte_eth_link link;
3093e661a08bSIgor Romanov 	int ret;
3094ba5509a6SIvan Dyukov 	char link_status[RTE_ETH_LINK_MAX_STR_LEN];
3095ce8d5614SIntel 
3096ce8d5614SIntel 	printf("Checking link statuses...\n");
3097ce8d5614SIntel 	fflush(stdout);
3098ce8d5614SIntel 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
3099ce8d5614SIntel 		all_ports_up = 1;
31007d89b261SGaetan Rivet 		RTE_ETH_FOREACH_DEV(portid) {
3101ce8d5614SIntel 			if ((port_mask & (1 << portid)) == 0)
3102ce8d5614SIntel 				continue;
3103ce8d5614SIntel 			memset(&link, 0, sizeof(link));
3104e661a08bSIgor Romanov 			ret = rte_eth_link_get_nowait(portid, &link);
3105e661a08bSIgor Romanov 			if (ret < 0) {
3106e661a08bSIgor Romanov 				all_ports_up = 0;
3107e661a08bSIgor Romanov 				if (print_flag == 1)
3108e661a08bSIgor Romanov 					printf("Port %u link get failed: %s\n",
3109e661a08bSIgor Romanov 						portid, rte_strerror(-ret));
3110e661a08bSIgor Romanov 				continue;
3111e661a08bSIgor Romanov 			}
3112ce8d5614SIntel 			/* print link status if flag set */
3113ce8d5614SIntel 			if (print_flag == 1) {
3114ba5509a6SIvan Dyukov 				rte_eth_link_to_str(link_status,
3115ba5509a6SIvan Dyukov 					sizeof(link_status), &link);
3116ba5509a6SIvan Dyukov 				printf("Port %d %s\n", portid, link_status);
3117ce8d5614SIntel 				continue;
3118ce8d5614SIntel 			}
3119ce8d5614SIntel 			/* clear all_ports_up flag if any link down */
312009419f23SThomas Monjalon 			if (link.link_status == ETH_LINK_DOWN) {
3121ce8d5614SIntel 				all_ports_up = 0;
3122ce8d5614SIntel 				break;
3123ce8d5614SIntel 			}
3124ce8d5614SIntel 		}
3125ce8d5614SIntel 		/* after finally printing all link status, get out */
3126ce8d5614SIntel 		if (print_flag == 1)
3127ce8d5614SIntel 			break;
3128ce8d5614SIntel 
3129ce8d5614SIntel 		if (all_ports_up == 0) {
3130ce8d5614SIntel 			fflush(stdout);
3131ce8d5614SIntel 			rte_delay_ms(CHECK_INTERVAL);
3132ce8d5614SIntel 		}
3133ce8d5614SIntel 
3134ce8d5614SIntel 		/* set the print_flag if all ports up or timeout */
3135ce8d5614SIntel 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
3136ce8d5614SIntel 			print_flag = 1;
3137ce8d5614SIntel 		}
31388ea656f8SGaetan Rivet 
31398ea656f8SGaetan Rivet 		if (lsc_interrupt)
31408ea656f8SGaetan Rivet 			break;
3141ce8d5614SIntel 	}
3142af75078fSIntel }
3143af75078fSIntel 
3144284c908cSGaetan Rivet static void
3145cc1bf307SJeff Guo rmv_port_callback(void *arg)
3146284c908cSGaetan Rivet {
31473b97888aSMatan Azrad 	int need_to_start = 0;
31480da2a62bSMatan Azrad 	int org_no_link_check = no_link_check;
314928caa76aSZhiyong Yang 	portid_t port_id = (intptr_t)arg;
31500654d4a8SThomas Monjalon 	struct rte_device *dev;
3151284c908cSGaetan Rivet 
3152284c908cSGaetan Rivet 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
3153284c908cSGaetan Rivet 
31543b97888aSMatan Azrad 	if (!test_done && port_is_forwarding(port_id)) {
31553b97888aSMatan Azrad 		need_to_start = 1;
31563b97888aSMatan Azrad 		stop_packet_forwarding();
31573b97888aSMatan Azrad 	}
31580da2a62bSMatan Azrad 	no_link_check = 1;
3159284c908cSGaetan Rivet 	stop_port(port_id);
31600da2a62bSMatan Azrad 	no_link_check = org_no_link_check;
31610654d4a8SThomas Monjalon 
31620654d4a8SThomas Monjalon 	/* Save rte_device pointer before closing ethdev port */
31630654d4a8SThomas Monjalon 	dev = rte_eth_devices[port_id].device;
3164284c908cSGaetan Rivet 	close_port(port_id);
31650654d4a8SThomas Monjalon 	detach_device(dev); /* might be already removed or have more ports */
31660654d4a8SThomas Monjalon 
31673b97888aSMatan Azrad 	if (need_to_start)
31683b97888aSMatan Azrad 		start_packet_forwarding(0);
3169284c908cSGaetan Rivet }
3170284c908cSGaetan Rivet 
317176ad4a2dSGaetan Rivet /* This function is used by the interrupt thread */
3172d6af1a13SBernard Iremonger static int
3173f8244c63SZhiyong Yang eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
3174d6af1a13SBernard Iremonger 		  void *ret_param)
317576ad4a2dSGaetan Rivet {
317676ad4a2dSGaetan Rivet 	RTE_SET_USED(param);
3177d6af1a13SBernard Iremonger 	RTE_SET_USED(ret_param);
317876ad4a2dSGaetan Rivet 
317976ad4a2dSGaetan Rivet 	if (type >= RTE_ETH_EVENT_MAX) {
3180f431e010SHerakliusz Lipiec 		fprintf(stderr, "\nPort %" PRIu16 ": %s called upon invalid event %d\n",
318176ad4a2dSGaetan Rivet 			port_id, __func__, type);
318276ad4a2dSGaetan Rivet 		fflush(stderr);
31833af72783SGaetan Rivet 	} else if (event_print_mask & (UINT32_C(1) << type)) {
3184f431e010SHerakliusz Lipiec 		printf("\nPort %" PRIu16 ": %s event\n", port_id,
318597b5d8b5SThomas Monjalon 			eth_event_desc[type]);
318676ad4a2dSGaetan Rivet 		fflush(stdout);
318776ad4a2dSGaetan Rivet 	}
3188284c908cSGaetan Rivet 
3189284c908cSGaetan Rivet 	switch (type) {
31904f1ed78eSThomas Monjalon 	case RTE_ETH_EVENT_NEW:
31914f1ed78eSThomas Monjalon 		ports[port_id].need_setup = 1;
31924f1ed78eSThomas Monjalon 		ports[port_id].port_status = RTE_PORT_HANDLING;
31934f1ed78eSThomas Monjalon 		break;
3194284c908cSGaetan Rivet 	case RTE_ETH_EVENT_INTR_RMV:
31954f1ed78eSThomas Monjalon 		if (port_id_is_invalid(port_id, DISABLED_WARN))
31964f1ed78eSThomas Monjalon 			break;
3197284c908cSGaetan Rivet 		if (rte_eal_alarm_set(100000,
3198cc1bf307SJeff Guo 				rmv_port_callback, (void *)(intptr_t)port_id))
3199284c908cSGaetan Rivet 			fprintf(stderr, "Could not set up deferred device removal\n");
3200284c908cSGaetan Rivet 		break;
320185c6571cSThomas Monjalon 	case RTE_ETH_EVENT_DESTROY:
320285c6571cSThomas Monjalon 		ports[port_id].port_status = RTE_PORT_CLOSED;
320385c6571cSThomas Monjalon 		printf("Port %u is closed\n", port_id);
320485c6571cSThomas Monjalon 		break;
3205284c908cSGaetan Rivet 	default:
3206284c908cSGaetan Rivet 		break;
3207284c908cSGaetan Rivet 	}
3208d6af1a13SBernard Iremonger 	return 0;
320976ad4a2dSGaetan Rivet }
321076ad4a2dSGaetan Rivet 
321197b5d8b5SThomas Monjalon static int
321297b5d8b5SThomas Monjalon register_eth_event_callback(void)
321397b5d8b5SThomas Monjalon {
321497b5d8b5SThomas Monjalon 	int ret;
321597b5d8b5SThomas Monjalon 	enum rte_eth_event_type event;
321697b5d8b5SThomas Monjalon 
321797b5d8b5SThomas Monjalon 	for (event = RTE_ETH_EVENT_UNKNOWN;
321897b5d8b5SThomas Monjalon 			event < RTE_ETH_EVENT_MAX; event++) {
321997b5d8b5SThomas Monjalon 		ret = rte_eth_dev_callback_register(RTE_ETH_ALL,
322097b5d8b5SThomas Monjalon 				event,
322197b5d8b5SThomas Monjalon 				eth_event_callback,
322297b5d8b5SThomas Monjalon 				NULL);
322397b5d8b5SThomas Monjalon 		if (ret != 0) {
322497b5d8b5SThomas Monjalon 			TESTPMD_LOG(ERR, "Failed to register callback for "
322597b5d8b5SThomas Monjalon 					"%s event\n", eth_event_desc[event]);
322697b5d8b5SThomas Monjalon 			return -1;
322797b5d8b5SThomas Monjalon 		}
322897b5d8b5SThomas Monjalon 	}
322997b5d8b5SThomas Monjalon 
323097b5d8b5SThomas Monjalon 	return 0;
323197b5d8b5SThomas Monjalon }
323297b5d8b5SThomas Monjalon 
3233fb73e096SJeff Guo /* This function is used by the interrupt thread */
3234fb73e096SJeff Guo static void
3235cc1bf307SJeff Guo dev_event_callback(const char *device_name, enum rte_dev_event_type type,
3236fb73e096SJeff Guo 			     __rte_unused void *arg)
3237fb73e096SJeff Guo {
32382049c511SJeff Guo 	uint16_t port_id;
32392049c511SJeff Guo 	int ret;
32402049c511SJeff Guo 
3241fb73e096SJeff Guo 	if (type >= RTE_DEV_EVENT_MAX) {
3242fb73e096SJeff Guo 		fprintf(stderr, "%s called upon invalid event %d\n",
3243fb73e096SJeff Guo 			__func__, type);
3244fb73e096SJeff Guo 		fflush(stderr);
3245fb73e096SJeff Guo 	}
3246fb73e096SJeff Guo 
3247fb73e096SJeff Guo 	switch (type) {
3248fb73e096SJeff Guo 	case RTE_DEV_EVENT_REMOVE:
3249cc1bf307SJeff Guo 		RTE_LOG(DEBUG, EAL, "The device: %s has been removed!\n",
3250fb73e096SJeff Guo 			device_name);
32512049c511SJeff Guo 		ret = rte_eth_dev_get_port_by_name(device_name, &port_id);
32522049c511SJeff Guo 		if (ret) {
32532049c511SJeff Guo 			RTE_LOG(ERR, EAL, "can not get port by device %s!\n",
32542049c511SJeff Guo 				device_name);
32552049c511SJeff Guo 			return;
32562049c511SJeff Guo 		}
3257cc1bf307SJeff Guo 		/*
3258cc1bf307SJeff Guo 		 * Because the user's callback is invoked in eal interrupt
3259cc1bf307SJeff Guo 		 * callback, the interrupt callback need to be finished before
3260cc1bf307SJeff Guo 		 * it can be unregistered when detaching device. So finish
3261cc1bf307SJeff Guo 		 * callback soon and use a deferred removal to detach device
3262cc1bf307SJeff Guo 		 * is need. It is a workaround, once the device detaching be
3263cc1bf307SJeff Guo 		 * moved into the eal in the future, the deferred removal could
3264cc1bf307SJeff Guo 		 * be deleted.
3265cc1bf307SJeff Guo 		 */
3266cc1bf307SJeff Guo 		if (rte_eal_alarm_set(100000,
3267cc1bf307SJeff Guo 				rmv_port_callback, (void *)(intptr_t)port_id))
3268cc1bf307SJeff Guo 			RTE_LOG(ERR, EAL,
3269cc1bf307SJeff Guo 				"Could not set up deferred device removal\n");
3270fb73e096SJeff Guo 		break;
3271fb73e096SJeff Guo 	case RTE_DEV_EVENT_ADD:
3272fb73e096SJeff Guo 		RTE_LOG(ERR, EAL, "The device: %s has been added!\n",
3273fb73e096SJeff Guo 			device_name);
3274fb73e096SJeff Guo 		/* TODO: After finish kernel driver binding,
3275fb73e096SJeff Guo 		 * begin to attach port.
3276fb73e096SJeff Guo 		 */
3277fb73e096SJeff Guo 		break;
3278fb73e096SJeff Guo 	default:
3279fb73e096SJeff Guo 		break;
3280fb73e096SJeff Guo 	}
3281fb73e096SJeff Guo }
3282fb73e096SJeff Guo 
3283f2c5125aSPablo de Lara static void
3284f2c5125aSPablo de Lara rxtx_port_config(struct rte_port *port)
3285f2c5125aSPablo de Lara {
3286d44f8a48SQi Zhang 	uint16_t qid;
32875e91aeefSWei Zhao 	uint64_t offloads;
3288f2c5125aSPablo de Lara 
3289d44f8a48SQi Zhang 	for (qid = 0; qid < nb_rxq; qid++) {
32905e91aeefSWei Zhao 		offloads = port->rx_conf[qid].offloads;
3291d44f8a48SQi Zhang 		port->rx_conf[qid] = port->dev_info.default_rxconf;
3292575e0fd1SWei Zhao 		if (offloads != 0)
3293575e0fd1SWei Zhao 			port->rx_conf[qid].offloads = offloads;
3294d44f8a48SQi Zhang 
3295d44f8a48SQi Zhang 		/* Check if any Rx parameters have been passed */
3296f2c5125aSPablo de Lara 		if (rx_pthresh != RTE_PMD_PARAM_UNSET)
3297d44f8a48SQi Zhang 			port->rx_conf[qid].rx_thresh.pthresh = rx_pthresh;
3298f2c5125aSPablo de Lara 
3299f2c5125aSPablo de Lara 		if (rx_hthresh != RTE_PMD_PARAM_UNSET)
3300d44f8a48SQi Zhang 			port->rx_conf[qid].rx_thresh.hthresh = rx_hthresh;
3301f2c5125aSPablo de Lara 
3302f2c5125aSPablo de Lara 		if (rx_wthresh != RTE_PMD_PARAM_UNSET)
3303d44f8a48SQi Zhang 			port->rx_conf[qid].rx_thresh.wthresh = rx_wthresh;
3304f2c5125aSPablo de Lara 
3305f2c5125aSPablo de Lara 		if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
3306d44f8a48SQi Zhang 			port->rx_conf[qid].rx_free_thresh = rx_free_thresh;
3307f2c5125aSPablo de Lara 
3308f2c5125aSPablo de Lara 		if (rx_drop_en != RTE_PMD_PARAM_UNSET)
3309d44f8a48SQi Zhang 			port->rx_conf[qid].rx_drop_en = rx_drop_en;
3310f2c5125aSPablo de Lara 
3311d44f8a48SQi Zhang 		port->nb_rx_desc[qid] = nb_rxd;
3312d44f8a48SQi Zhang 	}
3313d44f8a48SQi Zhang 
3314d44f8a48SQi Zhang 	for (qid = 0; qid < nb_txq; qid++) {
33155e91aeefSWei Zhao 		offloads = port->tx_conf[qid].offloads;
3316d44f8a48SQi Zhang 		port->tx_conf[qid] = port->dev_info.default_txconf;
3317575e0fd1SWei Zhao 		if (offloads != 0)
3318575e0fd1SWei Zhao 			port->tx_conf[qid].offloads = offloads;
3319d44f8a48SQi Zhang 
3320d44f8a48SQi Zhang 		/* Check if any Tx parameters have been passed */
3321f2c5125aSPablo de Lara 		if (tx_pthresh != RTE_PMD_PARAM_UNSET)
3322d44f8a48SQi Zhang 			port->tx_conf[qid].tx_thresh.pthresh = tx_pthresh;
3323f2c5125aSPablo de Lara 
3324f2c5125aSPablo de Lara 		if (tx_hthresh != RTE_PMD_PARAM_UNSET)
3325d44f8a48SQi Zhang 			port->tx_conf[qid].tx_thresh.hthresh = tx_hthresh;
3326f2c5125aSPablo de Lara 
3327f2c5125aSPablo de Lara 		if (tx_wthresh != RTE_PMD_PARAM_UNSET)
3328d44f8a48SQi Zhang 			port->tx_conf[qid].tx_thresh.wthresh = tx_wthresh;
3329f2c5125aSPablo de Lara 
3330f2c5125aSPablo de Lara 		if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
3331d44f8a48SQi Zhang 			port->tx_conf[qid].tx_rs_thresh = tx_rs_thresh;
3332f2c5125aSPablo de Lara 
3333f2c5125aSPablo de Lara 		if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
3334d44f8a48SQi Zhang 			port->tx_conf[qid].tx_free_thresh = tx_free_thresh;
3335d44f8a48SQi Zhang 
3336d44f8a48SQi Zhang 		port->nb_tx_desc[qid] = nb_txd;
3337d44f8a48SQi Zhang 	}
3338f2c5125aSPablo de Lara }
3339f2c5125aSPablo de Lara 
3340013af9b6SIntel void
3341013af9b6SIntel init_port_config(void)
3342013af9b6SIntel {
3343013af9b6SIntel 	portid_t pid;
3344013af9b6SIntel 	struct rte_port *port;
33456f51deb9SIvan Ilchenko 	int ret;
3346013af9b6SIntel 
33477d89b261SGaetan Rivet 	RTE_ETH_FOREACH_DEV(pid) {
3348013af9b6SIntel 		port = &ports[pid];
3349013af9b6SIntel 		port->dev_conf.fdir_conf = fdir_conf;
33506f51deb9SIvan Ilchenko 
33516f51deb9SIvan Ilchenko 		ret = eth_dev_info_get_print_err(pid, &port->dev_info);
33526f51deb9SIvan Ilchenko 		if (ret != 0)
33536f51deb9SIvan Ilchenko 			return;
33546f51deb9SIvan Ilchenko 
33553ce690d3SBruce Richardson 		if (nb_rxq > 1) {
3356013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
335790892962SQi Zhang 			port->dev_conf.rx_adv_conf.rss_conf.rss_hf =
3358422515b9SAdrien Mazarguil 				rss_hf & port->dev_info.flow_type_rss_offloads;
3359af75078fSIntel 		} else {
3360013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
3361013af9b6SIntel 			port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
3362af75078fSIntel 		}
33633ce690d3SBruce Richardson 
33645f592039SJingjing Wu 		if (port->dcb_flag == 0) {
33653ce690d3SBruce Richardson 			if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0)
3366f9295aa2SXiaoyu Min 				port->dev_conf.rxmode.mq_mode =
3367f9295aa2SXiaoyu Min 					(enum rte_eth_rx_mq_mode)
3368f9295aa2SXiaoyu Min 						(rx_mq_mode & ETH_MQ_RX_RSS);
33693ce690d3SBruce Richardson 			else
33703ce690d3SBruce Richardson 				port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
33713ce690d3SBruce Richardson 		}
33723ce690d3SBruce Richardson 
3373f2c5125aSPablo de Lara 		rxtx_port_config(port);
3374013af9b6SIntel 
3375a5279d25SIgor Romanov 		ret = eth_macaddr_get_print_err(pid, &port->eth_addr);
3376a5279d25SIgor Romanov 		if (ret != 0)
3377a5279d25SIgor Romanov 			return;
3378013af9b6SIntel 
3379a8d0d473SBruce Richardson #if defined RTE_NET_IXGBE && defined RTE_LIBRTE_IXGBE_BYPASS
3380e261265eSRadu Nicolau 		rte_pmd_ixgbe_bypass_init(pid);
33817b7e5ba7SIntel #endif
33828ea656f8SGaetan Rivet 
33838ea656f8SGaetan Rivet 		if (lsc_interrupt &&
33848ea656f8SGaetan Rivet 		    (rte_eth_devices[pid].data->dev_flags &
33858ea656f8SGaetan Rivet 		     RTE_ETH_DEV_INTR_LSC))
33868ea656f8SGaetan Rivet 			port->dev_conf.intr_conf.lsc = 1;
3387284c908cSGaetan Rivet 		if (rmv_interrupt &&
3388284c908cSGaetan Rivet 		    (rte_eth_devices[pid].data->dev_flags &
3389284c908cSGaetan Rivet 		     RTE_ETH_DEV_INTR_RMV))
3390284c908cSGaetan Rivet 			port->dev_conf.intr_conf.rmv = 1;
3391013af9b6SIntel 	}
3392013af9b6SIntel }
3393013af9b6SIntel 
339441b05095SBernard Iremonger void set_port_slave_flag(portid_t slave_pid)
339541b05095SBernard Iremonger {
339641b05095SBernard Iremonger 	struct rte_port *port;
339741b05095SBernard Iremonger 
339841b05095SBernard Iremonger 	port = &ports[slave_pid];
339941b05095SBernard Iremonger 	port->slave_flag = 1;
340041b05095SBernard Iremonger }
340141b05095SBernard Iremonger 
340241b05095SBernard Iremonger void clear_port_slave_flag(portid_t slave_pid)
340341b05095SBernard Iremonger {
340441b05095SBernard Iremonger 	struct rte_port *port;
340541b05095SBernard Iremonger 
340641b05095SBernard Iremonger 	port = &ports[slave_pid];
340741b05095SBernard Iremonger 	port->slave_flag = 0;
340841b05095SBernard Iremonger }
340941b05095SBernard Iremonger 
34100e545d30SBernard Iremonger uint8_t port_is_bonding_slave(portid_t slave_pid)
34110e545d30SBernard Iremonger {
34120e545d30SBernard Iremonger 	struct rte_port *port;
34130e545d30SBernard Iremonger 
34140e545d30SBernard Iremonger 	port = &ports[slave_pid];
3415b8b8b344SMatan Azrad 	if ((rte_eth_devices[slave_pid].data->dev_flags &
3416b8b8b344SMatan Azrad 	    RTE_ETH_DEV_BONDED_SLAVE) || (port->slave_flag == 1))
3417b8b8b344SMatan Azrad 		return 1;
3418b8b8b344SMatan Azrad 	return 0;
34190e545d30SBernard Iremonger }
34200e545d30SBernard Iremonger 
3421013af9b6SIntel const uint16_t vlan_tags[] = {
3422013af9b6SIntel 		0,  1,  2,  3,  4,  5,  6,  7,
3423013af9b6SIntel 		8,  9, 10, 11,  12, 13, 14, 15,
3424013af9b6SIntel 		16, 17, 18, 19, 20, 21, 22, 23,
3425013af9b6SIntel 		24, 25, 26, 27, 28, 29, 30, 31
3426013af9b6SIntel };
3427013af9b6SIntel 
3428013af9b6SIntel static  int
3429ac7c491cSKonstantin Ananyev get_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf,
34301a572499SJingjing Wu 		 enum dcb_mode_enable dcb_mode,
34311a572499SJingjing Wu 		 enum rte_eth_nb_tcs num_tcs,
34321a572499SJingjing Wu 		 uint8_t pfc_en)
3433013af9b6SIntel {
3434013af9b6SIntel 	uint8_t i;
3435ac7c491cSKonstantin Ananyev 	int32_t rc;
3436ac7c491cSKonstantin Ananyev 	struct rte_eth_rss_conf rss_conf;
3437af75078fSIntel 
3438af75078fSIntel 	/*
3439013af9b6SIntel 	 * Builds up the correct configuration for dcb+vt based on the vlan tags array
3440013af9b6SIntel 	 * given above, and the number of traffic classes available for use.
3441af75078fSIntel 	 */
34421a572499SJingjing Wu 	if (dcb_mode == DCB_VT_ENABLED) {
34431a572499SJingjing Wu 		struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
34441a572499SJingjing Wu 				&eth_conf->rx_adv_conf.vmdq_dcb_conf;
34451a572499SJingjing Wu 		struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
34461a572499SJingjing Wu 				&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf;
3447013af9b6SIntel 
3448547d946cSNirmoy Das 		/* VMDQ+DCB RX and TX configurations */
34491a572499SJingjing Wu 		vmdq_rx_conf->enable_default_pool = 0;
34501a572499SJingjing Wu 		vmdq_rx_conf->default_pool = 0;
34511a572499SJingjing Wu 		vmdq_rx_conf->nb_queue_pools =
34521a572499SJingjing Wu 			(num_tcs ==  ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
34531a572499SJingjing Wu 		vmdq_tx_conf->nb_queue_pools =
34541a572499SJingjing Wu 			(num_tcs ==  ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
3455013af9b6SIntel 
34561a572499SJingjing Wu 		vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
34571a572499SJingjing Wu 		for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
34581a572499SJingjing Wu 			vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i];
34591a572499SJingjing Wu 			vmdq_rx_conf->pool_map[i].pools =
34601a572499SJingjing Wu 				1 << (i % vmdq_rx_conf->nb_queue_pools);
3461af75078fSIntel 		}
3462013af9b6SIntel 		for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
3463f59908feSWei Dai 			vmdq_rx_conf->dcb_tc[i] = i % num_tcs;
3464f59908feSWei Dai 			vmdq_tx_conf->dcb_tc[i] = i % num_tcs;
3465013af9b6SIntel 		}
3466013af9b6SIntel 
3467013af9b6SIntel 		/* set DCB mode of RX and TX of multiple queues */
3468f9295aa2SXiaoyu Min 		eth_conf->rxmode.mq_mode =
3469f9295aa2SXiaoyu Min 				(enum rte_eth_rx_mq_mode)
3470f9295aa2SXiaoyu Min 					(rx_mq_mode & ETH_MQ_RX_VMDQ_DCB);
347132e7aa0bSIntel 		eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB;
34721a572499SJingjing Wu 	} else {
34731a572499SJingjing Wu 		struct rte_eth_dcb_rx_conf *rx_conf =
34741a572499SJingjing Wu 				&eth_conf->rx_adv_conf.dcb_rx_conf;
34751a572499SJingjing Wu 		struct rte_eth_dcb_tx_conf *tx_conf =
34761a572499SJingjing Wu 				&eth_conf->tx_adv_conf.dcb_tx_conf;
3477013af9b6SIntel 
34785139bc12STing Xu 		memset(&rss_conf, 0, sizeof(struct rte_eth_rss_conf));
34795139bc12STing Xu 
3480ac7c491cSKonstantin Ananyev 		rc = rte_eth_dev_rss_hash_conf_get(pid, &rss_conf);
3481ac7c491cSKonstantin Ananyev 		if (rc != 0)
3482ac7c491cSKonstantin Ananyev 			return rc;
3483ac7c491cSKonstantin Ananyev 
34841a572499SJingjing Wu 		rx_conf->nb_tcs = num_tcs;
34851a572499SJingjing Wu 		tx_conf->nb_tcs = num_tcs;
34861a572499SJingjing Wu 
3487bcd0e432SJingjing Wu 		for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
3488bcd0e432SJingjing Wu 			rx_conf->dcb_tc[i] = i % num_tcs;
3489bcd0e432SJingjing Wu 			tx_conf->dcb_tc[i] = i % num_tcs;
3490013af9b6SIntel 		}
3491ac7c491cSKonstantin Ananyev 
3492f9295aa2SXiaoyu Min 		eth_conf->rxmode.mq_mode =
3493f9295aa2SXiaoyu Min 				(enum rte_eth_rx_mq_mode)
3494f9295aa2SXiaoyu Min 					(rx_mq_mode & ETH_MQ_RX_DCB_RSS);
3495ac7c491cSKonstantin Ananyev 		eth_conf->rx_adv_conf.rss_conf = rss_conf;
349632e7aa0bSIntel 		eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
34971a572499SJingjing Wu 	}
34981a572499SJingjing Wu 
34991a572499SJingjing Wu 	if (pfc_en)
35001a572499SJingjing Wu 		eth_conf->dcb_capability_en =
35011a572499SJingjing Wu 				ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT;
3502013af9b6SIntel 	else
3503013af9b6SIntel 		eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
3504013af9b6SIntel 
3505013af9b6SIntel 	return 0;
3506013af9b6SIntel }
3507013af9b6SIntel 
3508013af9b6SIntel int
35091a572499SJingjing Wu init_port_dcb_config(portid_t pid,
35101a572499SJingjing Wu 		     enum dcb_mode_enable dcb_mode,
35111a572499SJingjing Wu 		     enum rte_eth_nb_tcs num_tcs,
35121a572499SJingjing Wu 		     uint8_t pfc_en)
3513013af9b6SIntel {
3514013af9b6SIntel 	struct rte_eth_conf port_conf;
3515013af9b6SIntel 	struct rte_port *rte_port;
3516013af9b6SIntel 	int retval;
3517013af9b6SIntel 	uint16_t i;
3518013af9b6SIntel 
35192a977b89SWenzhuo Lu 	rte_port = &ports[pid];
3520013af9b6SIntel 
3521013af9b6SIntel 	memset(&port_conf, 0, sizeof(struct rte_eth_conf));
3522013af9b6SIntel 	/* Enter DCB configuration status */
3523013af9b6SIntel 	dcb_config = 1;
3524013af9b6SIntel 
3525d5354e89SYanglong Wu 	port_conf.rxmode = rte_port->dev_conf.rxmode;
3526d5354e89SYanglong Wu 	port_conf.txmode = rte_port->dev_conf.txmode;
3527d5354e89SYanglong Wu 
3528013af9b6SIntel 	/*set configuration of DCB in vt mode and DCB in non-vt mode*/
3529ac7c491cSKonstantin Ananyev 	retval = get_eth_dcb_conf(pid, &port_conf, dcb_mode, num_tcs, pfc_en);
3530013af9b6SIntel 	if (retval < 0)
3531013af9b6SIntel 		return retval;
35320074d02fSShahaf Shuler 	port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
3533013af9b6SIntel 
35342f203d44SQi Zhang 	/* re-configure the device . */
35352b0e0ebaSChenbo Xia 	retval = rte_eth_dev_configure(pid, nb_rxq, nb_rxq, &port_conf);
35362b0e0ebaSChenbo Xia 	if (retval < 0)
35372b0e0ebaSChenbo Xia 		return retval;
35386f51deb9SIvan Ilchenko 
35396f51deb9SIvan Ilchenko 	retval = eth_dev_info_get_print_err(pid, &rte_port->dev_info);
35406f51deb9SIvan Ilchenko 	if (retval != 0)
35416f51deb9SIvan Ilchenko 		return retval;
35422a977b89SWenzhuo Lu 
35432a977b89SWenzhuo Lu 	/* If dev_info.vmdq_pool_base is greater than 0,
35442a977b89SWenzhuo Lu 	 * the queue id of vmdq pools is started after pf queues.
35452a977b89SWenzhuo Lu 	 */
35462a977b89SWenzhuo Lu 	if (dcb_mode == DCB_VT_ENABLED &&
35472a977b89SWenzhuo Lu 	    rte_port->dev_info.vmdq_pool_base > 0) {
35482a977b89SWenzhuo Lu 		printf("VMDQ_DCB multi-queue mode is nonsensical"
35492a977b89SWenzhuo Lu 			" for port %d.", pid);
35502a977b89SWenzhuo Lu 		return -1;
35512a977b89SWenzhuo Lu 	}
35522a977b89SWenzhuo Lu 
35532a977b89SWenzhuo Lu 	/* Assume the ports in testpmd have the same dcb capability
35542a977b89SWenzhuo Lu 	 * and has the same number of rxq and txq in dcb mode
35552a977b89SWenzhuo Lu 	 */
35562a977b89SWenzhuo Lu 	if (dcb_mode == DCB_VT_ENABLED) {
355786ef65eeSBernard Iremonger 		if (rte_port->dev_info.max_vfs > 0) {
355886ef65eeSBernard Iremonger 			nb_rxq = rte_port->dev_info.nb_rx_queues;
355986ef65eeSBernard Iremonger 			nb_txq = rte_port->dev_info.nb_tx_queues;
356086ef65eeSBernard Iremonger 		} else {
35612a977b89SWenzhuo Lu 			nb_rxq = rte_port->dev_info.max_rx_queues;
35622a977b89SWenzhuo Lu 			nb_txq = rte_port->dev_info.max_tx_queues;
356386ef65eeSBernard Iremonger 		}
35642a977b89SWenzhuo Lu 	} else {
35652a977b89SWenzhuo Lu 		/*if vt is disabled, use all pf queues */
35662a977b89SWenzhuo Lu 		if (rte_port->dev_info.vmdq_pool_base == 0) {
35672a977b89SWenzhuo Lu 			nb_rxq = rte_port->dev_info.max_rx_queues;
35682a977b89SWenzhuo Lu 			nb_txq = rte_port->dev_info.max_tx_queues;
35692a977b89SWenzhuo Lu 		} else {
35702a977b89SWenzhuo Lu 			nb_rxq = (queueid_t)num_tcs;
35712a977b89SWenzhuo Lu 			nb_txq = (queueid_t)num_tcs;
35722a977b89SWenzhuo Lu 
35732a977b89SWenzhuo Lu 		}
35742a977b89SWenzhuo Lu 	}
35752a977b89SWenzhuo Lu 	rx_free_thresh = 64;
35762a977b89SWenzhuo Lu 
3577013af9b6SIntel 	memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
3578013af9b6SIntel 
3579f2c5125aSPablo de Lara 	rxtx_port_config(rte_port);
3580013af9b6SIntel 	/* VLAN filter */
35810074d02fSShahaf Shuler 	rte_port->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
35821a572499SJingjing Wu 	for (i = 0; i < RTE_DIM(vlan_tags); i++)
3583013af9b6SIntel 		rx_vft_set(pid, vlan_tags[i], 1);
3584013af9b6SIntel 
3585a5279d25SIgor Romanov 	retval = eth_macaddr_get_print_err(pid, &rte_port->eth_addr);
3586a5279d25SIgor Romanov 	if (retval != 0)
3587a5279d25SIgor Romanov 		return retval;
3588a5279d25SIgor Romanov 
35897741e4cfSIntel 	rte_port->dcb_flag = 1;
35907741e4cfSIntel 
3591013af9b6SIntel 	return 0;
3592af75078fSIntel }
3593af75078fSIntel 
3594ffc468ffSTetsuya Mukawa static void
3595ffc468ffSTetsuya Mukawa init_port(void)
3596ffc468ffSTetsuya Mukawa {
35971b9f2746SGregory Etelson 	int i;
35981b9f2746SGregory Etelson 
3599ffc468ffSTetsuya Mukawa 	/* Configuration of Ethernet ports. */
3600ffc468ffSTetsuya Mukawa 	ports = rte_zmalloc("testpmd: ports",
3601ffc468ffSTetsuya Mukawa 			    sizeof(struct rte_port) * RTE_MAX_ETHPORTS,
3602ffc468ffSTetsuya Mukawa 			    RTE_CACHE_LINE_SIZE);
3603ffc468ffSTetsuya Mukawa 	if (ports == NULL) {
3604ffc468ffSTetsuya Mukawa 		rte_exit(EXIT_FAILURE,
3605ffc468ffSTetsuya Mukawa 				"rte_zmalloc(%d struct rte_port) failed\n",
3606ffc468ffSTetsuya Mukawa 				RTE_MAX_ETHPORTS);
3607ffc468ffSTetsuya Mukawa 	}
36081b9f2746SGregory Etelson 	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
36091b9f2746SGregory Etelson 		LIST_INIT(&ports[i].flow_tunnel_list);
361029841336SPhil Yang 	/* Initialize ports NUMA structures */
361129841336SPhil Yang 	memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
361229841336SPhil Yang 	memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
361329841336SPhil Yang 	memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
3614ffc468ffSTetsuya Mukawa }
3615ffc468ffSTetsuya Mukawa 
3616d3a274ceSZhihong Wang static void
3617d3a274ceSZhihong Wang force_quit(void)
3618d3a274ceSZhihong Wang {
3619d3a274ceSZhihong Wang 	pmd_test_exit();
3620d3a274ceSZhihong Wang 	prompt_exit();
3621d3a274ceSZhihong Wang }
3622d3a274ceSZhihong Wang 
3623d3a274ceSZhihong Wang static void
3624cfea1f30SPablo de Lara print_stats(void)
3625cfea1f30SPablo de Lara {
3626cfea1f30SPablo de Lara 	uint8_t i;
3627cfea1f30SPablo de Lara 	const char clr[] = { 27, '[', '2', 'J', '\0' };
3628cfea1f30SPablo de Lara 	const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' };
3629cfea1f30SPablo de Lara 
3630cfea1f30SPablo de Lara 	/* Clear screen and move to top left */
3631cfea1f30SPablo de Lara 	printf("%s%s", clr, top_left);
3632cfea1f30SPablo de Lara 
3633cfea1f30SPablo de Lara 	printf("\nPort statistics ====================================");
3634cfea1f30SPablo de Lara 	for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
3635cfea1f30SPablo de Lara 		nic_stats_display(fwd_ports_ids[i]);
3636683d1e82SIgor Romanov 
3637683d1e82SIgor Romanov 	fflush(stdout);
3638cfea1f30SPablo de Lara }
3639cfea1f30SPablo de Lara 
3640cfea1f30SPablo de Lara static void
3641d3a274ceSZhihong Wang signal_handler(int signum)
3642d3a274ceSZhihong Wang {
3643d3a274ceSZhihong Wang 	if (signum == SIGINT || signum == SIGTERM) {
3644d3a274ceSZhihong Wang 		printf("\nSignal %d received, preparing to exit...\n",
3645d3a274ceSZhihong Wang 				signum);
3646a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
3647102b7329SReshma Pattan 		/* uninitialize packet capture framework */
3648102b7329SReshma Pattan 		rte_pdump_uninit();
3649102b7329SReshma Pattan #endif
3650a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
36518b36297dSAmit Gupta 		if (latencystats_enabled != 0)
365262d3216dSReshma Pattan 			rte_latencystats_uninit();
365362d3216dSReshma Pattan #endif
3654d3a274ceSZhihong Wang 		force_quit();
3655d9a191a0SPhil Yang 		/* Set flag to indicate the force termination. */
3656d9a191a0SPhil Yang 		f_quit = 1;
3657d3a274ceSZhihong Wang 		/* exit with the expected status */
3658d3a274ceSZhihong Wang 		signal(signum, SIG_DFL);
3659d3a274ceSZhihong Wang 		kill(getpid(), signum);
3660d3a274ceSZhihong Wang 	}
3661d3a274ceSZhihong Wang }
3662d3a274ceSZhihong Wang 
3663af75078fSIntel int
3664af75078fSIntel main(int argc, char** argv)
3665af75078fSIntel {
3666af75078fSIntel 	int diag;
3667f8244c63SZhiyong Yang 	portid_t port_id;
36684918a357SXiaoyun Li 	uint16_t count;
3669fb73e096SJeff Guo 	int ret;
3670af75078fSIntel 
3671d3a274ceSZhihong Wang 	signal(SIGINT, signal_handler);
3672d3a274ceSZhihong Wang 	signal(SIGTERM, signal_handler);
3673d3a274ceSZhihong Wang 
3674285fd101SOlivier Matz 	testpmd_logtype = rte_log_register("testpmd");
3675285fd101SOlivier Matz 	if (testpmd_logtype < 0)
367616267ceeSStephen Hemminger 		rte_exit(EXIT_FAILURE, "Cannot register log type");
3677285fd101SOlivier Matz 	rte_log_set_level(testpmd_logtype, RTE_LOG_DEBUG);
3678285fd101SOlivier Matz 
36799201806eSStephen Hemminger 	diag = rte_eal_init(argc, argv);
36809201806eSStephen Hemminger 	if (diag < 0)
368116267ceeSStephen Hemminger 		rte_exit(EXIT_FAILURE, "Cannot init EAL: %s\n",
368216267ceeSStephen Hemminger 			 rte_strerror(rte_errno));
36839201806eSStephen Hemminger 
3684a87ab9f7SStephen Hemminger 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
368516267ceeSStephen Hemminger 		rte_exit(EXIT_FAILURE,
368616267ceeSStephen Hemminger 			 "Secondary process type not supported.\n");
3687a87ab9f7SStephen Hemminger 
368897b5d8b5SThomas Monjalon 	ret = register_eth_event_callback();
368997b5d8b5SThomas Monjalon 	if (ret != 0)
369016267ceeSStephen Hemminger 		rte_exit(EXIT_FAILURE, "Cannot register for ethdev events");
369197b5d8b5SThomas Monjalon 
3692a8d0d473SBruce Richardson #ifdef RTE_LIB_PDUMP
36934aa0d012SAnatoly Burakov 	/* initialize packet capture framework */
3694e9436f54STiwei Bie 	rte_pdump_init();
36954aa0d012SAnatoly Burakov #endif
36964aa0d012SAnatoly Burakov 
36974918a357SXiaoyun Li 	count = 0;
36984918a357SXiaoyun Li 	RTE_ETH_FOREACH_DEV(port_id) {
36994918a357SXiaoyun Li 		ports_ids[count] = port_id;
37004918a357SXiaoyun Li 		count++;
37014918a357SXiaoyun Li 	}
37024918a357SXiaoyun Li 	nb_ports = (portid_t) count;
37034aa0d012SAnatoly Burakov 	if (nb_ports == 0)
37044aa0d012SAnatoly Burakov 		TESTPMD_LOG(WARNING, "No probed ethernet devices\n");
37054aa0d012SAnatoly Burakov 
37064aa0d012SAnatoly Burakov 	/* allocate port structures, and init them */
37074aa0d012SAnatoly Burakov 	init_port();
37084aa0d012SAnatoly Burakov 
37094aa0d012SAnatoly Burakov 	set_def_fwd_config();
37104aa0d012SAnatoly Burakov 	if (nb_lcores == 0)
371116267ceeSStephen Hemminger 		rte_exit(EXIT_FAILURE, "No cores defined for forwarding\n"
371216267ceeSStephen Hemminger 			 "Check the core mask argument\n");
37134aa0d012SAnatoly Burakov 
3714e505d84cSAnatoly Burakov 	/* Bitrate/latency stats disabled by default */
3715a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
3716e505d84cSAnatoly Burakov 	bitrate_enabled = 0;
3717e505d84cSAnatoly Burakov #endif
3718a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
3719e505d84cSAnatoly Burakov 	latencystats_enabled = 0;
3720e505d84cSAnatoly Burakov #endif
3721e505d84cSAnatoly Burakov 
3722fb7b8b32SAnatoly Burakov 	/* on FreeBSD, mlockall() is disabled by default */
37235fbc1d49SBruce Richardson #ifdef RTE_EXEC_ENV_FREEBSD
3724fb7b8b32SAnatoly Burakov 	do_mlockall = 0;
3725fb7b8b32SAnatoly Burakov #else
3726fb7b8b32SAnatoly Burakov 	do_mlockall = 1;
3727fb7b8b32SAnatoly Burakov #endif
3728fb7b8b32SAnatoly Burakov 
3729e505d84cSAnatoly Burakov 	argc -= diag;
3730e505d84cSAnatoly Burakov 	argv += diag;
3731e505d84cSAnatoly Burakov 	if (argc > 1)
3732e505d84cSAnatoly Burakov 		launch_args_parse(argc, argv);
3733e505d84cSAnatoly Burakov 
3734e505d84cSAnatoly Burakov 	if (do_mlockall && mlockall(MCL_CURRENT | MCL_FUTURE)) {
3735285fd101SOlivier Matz 		TESTPMD_LOG(NOTICE, "mlockall() failed with error \"%s\"\n",
37361c036b16SEelco Chaudron 			strerror(errno));
37371c036b16SEelco Chaudron 	}
37381c036b16SEelco Chaudron 
373999cabef0SPablo de Lara 	if (tx_first && interactive)
374099cabef0SPablo de Lara 		rte_exit(EXIT_FAILURE, "--tx-first cannot be used on "
374199cabef0SPablo de Lara 				"interactive mode.\n");
37428820cba4SDavid Hunt 
37438820cba4SDavid Hunt 	if (tx_first && lsc_interrupt) {
37448820cba4SDavid Hunt 		printf("Warning: lsc_interrupt needs to be off when "
37458820cba4SDavid Hunt 				" using tx_first. Disabling.\n");
37468820cba4SDavid Hunt 		lsc_interrupt = 0;
37478820cba4SDavid Hunt 	}
37488820cba4SDavid Hunt 
37495a8fb55cSReshma Pattan 	if (!nb_rxq && !nb_txq)
37505a8fb55cSReshma Pattan 		printf("Warning: Either rx or tx queues should be non-zero\n");
37515a8fb55cSReshma Pattan 
37525a8fb55cSReshma Pattan 	if (nb_rxq > 1 && nb_rxq > nb_txq)
3753af75078fSIntel 		printf("Warning: nb_rxq=%d enables RSS configuration, "
3754af75078fSIntel 		       "but nb_txq=%d will prevent to fully test it.\n",
3755af75078fSIntel 		       nb_rxq, nb_txq);
3756af75078fSIntel 
3757af75078fSIntel 	init_config();
3758fb73e096SJeff Guo 
3759fb73e096SJeff Guo 	if (hot_plug) {
37602049c511SJeff Guo 		ret = rte_dev_hotplug_handle_enable();
3761fb73e096SJeff Guo 		if (ret) {
37622049c511SJeff Guo 			RTE_LOG(ERR, EAL,
37632049c511SJeff Guo 				"fail to enable hotplug handling.");
3764fb73e096SJeff Guo 			return -1;
3765fb73e096SJeff Guo 		}
3766fb73e096SJeff Guo 
37672049c511SJeff Guo 		ret = rte_dev_event_monitor_start();
37682049c511SJeff Guo 		if (ret) {
37692049c511SJeff Guo 			RTE_LOG(ERR, EAL,
37702049c511SJeff Guo 				"fail to start device event monitoring.");
37712049c511SJeff Guo 			return -1;
37722049c511SJeff Guo 		}
37732049c511SJeff Guo 
37742049c511SJeff Guo 		ret = rte_dev_event_callback_register(NULL,
3775cc1bf307SJeff Guo 			dev_event_callback, NULL);
37762049c511SJeff Guo 		if (ret) {
37772049c511SJeff Guo 			RTE_LOG(ERR, EAL,
37782049c511SJeff Guo 				"fail  to register device event callback\n");
37792049c511SJeff Guo 			return -1;
37802049c511SJeff Guo 		}
3781fb73e096SJeff Guo 	}
3782fb73e096SJeff Guo 
37836937d210SStephen Hemminger 	if (!no_device_start && start_port(RTE_PORT_ALL) != 0)
3784148f963fSBruce Richardson 		rte_exit(EXIT_FAILURE, "Start ports failed\n");
3785af75078fSIntel 
3786ce8d5614SIntel 	/* set all ports to promiscuous mode by default */
378734fc1051SIvan Ilchenko 	RTE_ETH_FOREACH_DEV(port_id) {
378834fc1051SIvan Ilchenko 		ret = rte_eth_promiscuous_enable(port_id);
378934fc1051SIvan Ilchenko 		if (ret != 0)
379034fc1051SIvan Ilchenko 			printf("Error during enabling promiscuous mode for port %u: %s - ignore\n",
379134fc1051SIvan Ilchenko 				port_id, rte_strerror(-ret));
379234fc1051SIvan Ilchenko 	}
3793af75078fSIntel 
37947e4441c8SRemy Horton 	/* Init metrics library */
37957e4441c8SRemy Horton 	rte_metrics_init(rte_socket_id());
37967e4441c8SRemy Horton 
3797a8d0d473SBruce Richardson #ifdef RTE_LIB_LATENCYSTATS
379862d3216dSReshma Pattan 	if (latencystats_enabled != 0) {
379962d3216dSReshma Pattan 		int ret = rte_latencystats_init(1, NULL);
380062d3216dSReshma Pattan 		if (ret)
380162d3216dSReshma Pattan 			printf("Warning: latencystats init()"
380262d3216dSReshma Pattan 				" returned error %d\n",	ret);
380362d3216dSReshma Pattan 		printf("Latencystats running on lcore %d\n",
380462d3216dSReshma Pattan 			latencystats_lcore_id);
380562d3216dSReshma Pattan 	}
380662d3216dSReshma Pattan #endif
380762d3216dSReshma Pattan 
38087e4441c8SRemy Horton 	/* Setup bitrate stats */
3809a8d0d473SBruce Richardson #ifdef RTE_LIB_BITRATESTATS
3810e25e6c70SRemy Horton 	if (bitrate_enabled != 0) {
38117e4441c8SRemy Horton 		bitrate_data = rte_stats_bitrate_create();
38127e4441c8SRemy Horton 		if (bitrate_data == NULL)
3813e25e6c70SRemy Horton 			rte_exit(EXIT_FAILURE,
3814e25e6c70SRemy Horton 				"Could not allocate bitrate data.\n");
38157e4441c8SRemy Horton 		rte_stats_bitrate_reg(bitrate_data);
3816e25e6c70SRemy Horton 	}
38177e4441c8SRemy Horton #endif
38187e4441c8SRemy Horton 
3819a8d0d473SBruce Richardson #ifdef RTE_LIB_CMDLINE
382081ef862bSAllain Legacy 	if (strlen(cmdline_filename) != 0)
382181ef862bSAllain Legacy 		cmdline_read_from_file(cmdline_filename);
382281ef862bSAllain Legacy 
3823ca7feb22SCyril Chemparathy 	if (interactive == 1) {
3824ca7feb22SCyril Chemparathy 		if (auto_start) {
3825ca7feb22SCyril Chemparathy 			printf("Start automatic packet forwarding\n");
3826ca7feb22SCyril Chemparathy 			start_packet_forwarding(0);
3827ca7feb22SCyril Chemparathy 		}
3828af75078fSIntel 		prompt();
38290de738cfSJiayu Hu 		pmd_test_exit();
3830ca7feb22SCyril Chemparathy 	} else
38310d56cb81SThomas Monjalon #endif
38320d56cb81SThomas Monjalon 	{
3833af75078fSIntel 		char c;
3834af75078fSIntel 		int rc;
3835af75078fSIntel 
3836d9a191a0SPhil Yang 		f_quit = 0;
3837d9a191a0SPhil Yang 
3838af75078fSIntel 		printf("No commandline core given, start packet forwarding\n");
383999cabef0SPablo de Lara 		start_packet_forwarding(tx_first);
3840cfea1f30SPablo de Lara 		if (stats_period != 0) {
3841cfea1f30SPablo de Lara 			uint64_t prev_time = 0, cur_time, diff_time = 0;
3842cfea1f30SPablo de Lara 			uint64_t timer_period;
3843cfea1f30SPablo de Lara 
3844cfea1f30SPablo de Lara 			/* Convert to number of cycles */
3845cfea1f30SPablo de Lara 			timer_period = stats_period * rte_get_timer_hz();
3846cfea1f30SPablo de Lara 
3847d9a191a0SPhil Yang 			while (f_quit == 0) {
3848cfea1f30SPablo de Lara 				cur_time = rte_get_timer_cycles();
3849cfea1f30SPablo de Lara 				diff_time += cur_time - prev_time;
3850cfea1f30SPablo de Lara 
3851cfea1f30SPablo de Lara 				if (diff_time >= timer_period) {
3852cfea1f30SPablo de Lara 					print_stats();
3853cfea1f30SPablo de Lara 					/* Reset the timer */
3854cfea1f30SPablo de Lara 					diff_time = 0;
3855cfea1f30SPablo de Lara 				}
3856cfea1f30SPablo de Lara 				/* Sleep to avoid unnecessary checks */
3857cfea1f30SPablo de Lara 				prev_time = cur_time;
3858cfea1f30SPablo de Lara 				sleep(1);
3859cfea1f30SPablo de Lara 			}
3860cfea1f30SPablo de Lara 		}
3861cfea1f30SPablo de Lara 
3862af75078fSIntel 		printf("Press enter to exit\n");
3863af75078fSIntel 		rc = read(0, &c, 1);
3864d3a274ceSZhihong Wang 		pmd_test_exit();
3865af75078fSIntel 		if (rc < 0)
3866af75078fSIntel 			return 1;
3867af75078fSIntel 	}
3868af75078fSIntel 
38695e516c89SStephen Hemminger 	ret = rte_eal_cleanup();
38705e516c89SStephen Hemminger 	if (ret != 0)
38715e516c89SStephen Hemminger 		rte_exit(EXIT_FAILURE,
38725e516c89SStephen Hemminger 			 "EAL cleanup failed: %s\n", strerror(-ret));
38735e516c89SStephen Hemminger 
38745e516c89SStephen Hemminger 	return EXIT_SUCCESS;
3875af75078fSIntel }
3876