xref: /dpdk/examples/l3fwd-power/main.c (revision 7f2a987ca852a45bdb4520edc7ad7e02c4efd269)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2f88e7c17SRadu Nicolau  * Copyright(c) 2010-2018 Intel Corporation
3d7937e2eSIntel  */
4d7937e2eSIntel 
5d7937e2eSIntel #include <stdio.h>
6d7937e2eSIntel #include <stdlib.h>
7d7937e2eSIntel #include <stdint.h>
8d7937e2eSIntel #include <inttypes.h>
9d7937e2eSIntel #include <sys/types.h>
10d7937e2eSIntel #include <string.h>
11d7937e2eSIntel #include <sys/queue.h>
12d7937e2eSIntel #include <stdarg.h>
13d7937e2eSIntel #include <errno.h>
14d7937e2eSIntel #include <getopt.h>
15d7937e2eSIntel #include <unistd.h>
16d7937e2eSIntel #include <signal.h>
17609e7984SReshma Pattan #include <math.h>
18d7937e2eSIntel 
19d7937e2eSIntel #include <rte_common.h>
20d7937e2eSIntel #include <rte_byteorder.h>
21d7937e2eSIntel #include <rte_log.h>
22e2366e74STomasz Kulasek #include <rte_malloc.h>
23d7937e2eSIntel #include <rte_memory.h>
24d7937e2eSIntel #include <rte_memcpy.h>
25d7937e2eSIntel #include <rte_eal.h>
26d7937e2eSIntel #include <rte_launch.h>
27d7937e2eSIntel #include <rte_cycles.h>
28d7937e2eSIntel #include <rte_prefetch.h>
29d7937e2eSIntel #include <rte_lcore.h>
30d7937e2eSIntel #include <rte_per_lcore.h>
31d7937e2eSIntel #include <rte_branch_prediction.h>
32d7937e2eSIntel #include <rte_interrupts.h>
33d7937e2eSIntel #include <rte_random.h>
34d7937e2eSIntel #include <rte_debug.h>
35d7937e2eSIntel #include <rte_ether.h>
36d7937e2eSIntel #include <rte_ethdev.h>
37d7937e2eSIntel #include <rte_mempool.h>
38d7937e2eSIntel #include <rte_mbuf.h>
39d7937e2eSIntel #include <rte_ip.h>
40d7937e2eSIntel #include <rte_tcp.h>
41d7937e2eSIntel #include <rte_udp.h>
42d7937e2eSIntel #include <rte_string_fns.h>
43d7937e2eSIntel #include <rte_timer.h>
44f30a1bbdSSivaprasad Tummala #include <rte_power_cpufreq.h>
45aee3bc79SCunming Liang #include <rte_spinlock.h>
46609e7984SReshma Pattan #include <rte_metrics.h>
47a35919a1SCiara Power #include <rte_telemetry.h>
4826fe454eSLiang Ma #include <rte_power_pmd_mgmt.h>
49ac1edcb6SSivaprasad Tummala #include <rte_power_uncore.h>
504d23d39fSHuisong Li #include <rte_power_qos.h>
51d7937e2eSIntel 
52f88e7c17SRadu Nicolau #include "perf_core.h"
53f88e7c17SRadu Nicolau #include "main.h"
54f88e7c17SRadu Nicolau 
558bae59edSStephen Hemminger RTE_LOG_REGISTER(l3fwd_power_logtype, l3fwd.power, INFO);
568bae59edSStephen Hemminger #define RTE_LOGTYPE_L3FWD_POWER l3fwd_power_logtype
57d7937e2eSIntel 
58d7937e2eSIntel #define MAX_PKT_BURST 32
59d7937e2eSIntel 
60aee3bc79SCunming Liang #define MIN_ZERO_POLL_COUNT 10
61d7937e2eSIntel 
62d7937e2eSIntel /* 100 ms interval */
63d7937e2eSIntel #define TIMER_NUMBER_PER_SECOND           10
64a137d012SLiang Ma /* (10ms) */
65a137d012SLiang Ma #define INTERVALS_PER_SECOND             100
66d7937e2eSIntel /* 100000 us */
67d7937e2eSIntel #define SCALING_PERIOD                    (1000000/TIMER_NUMBER_PER_SECOND)
68d7937e2eSIntel #define SCALING_DOWN_TIME_RATIO_THRESHOLD 0.25
69d7937e2eSIntel 
70d7937e2eSIntel #define APP_LOOKUP_EXACT_MATCH          0
71d7937e2eSIntel #define APP_LOOKUP_LPM                  1
72d7937e2eSIntel #define DO_RFC_1812_CHECKS
73d7937e2eSIntel 
74d7937e2eSIntel #ifndef APP_LOOKUP_METHOD
75d7937e2eSIntel #define APP_LOOKUP_METHOD             APP_LOOKUP_LPM
76d7937e2eSIntel #endif
77d7937e2eSIntel 
78d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
79d7937e2eSIntel #include <rte_hash.h>
80d7937e2eSIntel #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
81d7937e2eSIntel #include <rte_lpm.h>
82d7937e2eSIntel #else
83d7937e2eSIntel #error "APP_LOOKUP_METHOD set to incorrect value"
84d7937e2eSIntel #endif
85d7937e2eSIntel 
86d7937e2eSIntel #ifndef IPv6_BYTES
87d7937e2eSIntel #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\
88d7937e2eSIntel                        "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
89d7937e2eSIntel #define IPv6_BYTES(addr) \
90d7937e2eSIntel 	addr[0],  addr[1], addr[2],  addr[3], \
91d7937e2eSIntel 	addr[4],  addr[5], addr[6],  addr[7], \
92d7937e2eSIntel 	addr[8],  addr[9], addr[10], addr[11],\
93d7937e2eSIntel 	addr[12], addr[13],addr[14], addr[15]
94d7937e2eSIntel #endif
95d7937e2eSIntel 
96d7937e2eSIntel #define MAX_JUMBO_PKT_LEN  9600
97d7937e2eSIntel 
98d7937e2eSIntel #define IPV6_ADDR_LEN 16
99d7937e2eSIntel 
100d7937e2eSIntel #define MEMPOOL_CACHE_SIZE 256
101d7937e2eSIntel 
102d7937e2eSIntel /*
103d7937e2eSIntel  * This expression is used to calculate the number of mbufs needed depending on
104d7937e2eSIntel  * user input, taking into account memory for rx and tx hardware rings, cache
105d7937e2eSIntel  * per lcore and mtable per port per lcore. RTE_MAX is used to ensure that
106d7937e2eSIntel  * NB_MBUF never goes below a minimum value of 8192.
107d7937e2eSIntel  */
108d7937e2eSIntel 
109d7937e2eSIntel #define NB_MBUF RTE_MAX	( \
11060efb44fSRoman Zhukov 	(nb_ports*nb_rx_queue*nb_rxd + \
111d7937e2eSIntel 	nb_ports*nb_lcores*MAX_PKT_BURST + \
11260efb44fSRoman Zhukov 	nb_ports*n_tx_queue*nb_txd + \
113d7937e2eSIntel 	nb_lcores*MEMPOOL_CACHE_SIZE), \
114d7937e2eSIntel 	(unsigned)8192)
115d7937e2eSIntel 
116d7937e2eSIntel #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
117d7937e2eSIntel 
118d7937e2eSIntel #define NB_SOCKETS 8
119d7937e2eSIntel 
120d7937e2eSIntel /* Configure how many packets ahead to prefetch, when reading packets */
121d7937e2eSIntel #define PREFETCH_OFFSET	3
122d7937e2eSIntel 
123d7937e2eSIntel /*
124d7937e2eSIntel  * Configurable number of RX/TX ring descriptors
125d7937e2eSIntel  */
1264ed89049SDavid Marchand #define RX_DESC_DEFAULT 1024
1274ed89049SDavid Marchand #define TX_DESC_DEFAULT 1024
128a137d012SLiang Ma 
129a35919a1SCiara Power #define NUM_TELSTATS RTE_DIM(telstats_strings)
130a137d012SLiang Ma 
1314ed89049SDavid Marchand static uint16_t nb_rxd = RX_DESC_DEFAULT;
1324ed89049SDavid Marchand static uint16_t nb_txd = TX_DESC_DEFAULT;
133d7937e2eSIntel 
134d7937e2eSIntel /* ethernet addresses of ports */
1356d13ea8eSOlivier Matz static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
136d7937e2eSIntel 
137aee3bc79SCunming Liang /* ethernet addresses of ports */
138aee3bc79SCunming Liang static rte_spinlock_t locks[RTE_MAX_ETHPORTS];
139aee3bc79SCunming Liang 
140d7937e2eSIntel /* mask of enabled ports */
141d7937e2eSIntel static uint32_t enabled_port_mask = 0;
142d7937e2eSIntel /* Ports set in promiscuous mode off by default. */
143d7937e2eSIntel static int promiscuous_on = 0;
144d7937e2eSIntel /* NUMA is enabled by default. */
145d7937e2eSIntel static int numa_on = 1;
146609e7984SReshma Pattan volatile bool quit_signal;
147609e7984SReshma Pattan /* timer to update telemetry every 500ms */
148609e7984SReshma Pattan static struct rte_timer telemetry_timer;
149609e7984SReshma Pattan 
150609e7984SReshma Pattan /* stats index returned by metrics lib */
151609e7984SReshma Pattan int telstats_index;
152609e7984SReshma Pattan 
15310db2a5bSTadhg Kearney /* flag to check if uncore option enabled */
15410db2a5bSTadhg Kearney int enabled_uncore = -1;
15510db2a5bSTadhg Kearney 
156609e7984SReshma Pattan struct telstats_name {
157609e7984SReshma Pattan 	char name[RTE_ETH_XSTATS_NAME_SIZE];
158609e7984SReshma Pattan };
159609e7984SReshma Pattan 
160609e7984SReshma Pattan /* telemetry stats to be reported */
161609e7984SReshma Pattan const struct telstats_name telstats_strings[] = {
162609e7984SReshma Pattan 	{"empty_poll"},
163609e7984SReshma Pattan 	{"full_poll"},
164609e7984SReshma Pattan 	{"busy_percent"}
165609e7984SReshma Pattan };
166609e7984SReshma Pattan 
167609e7984SReshma Pattan /* core busyness in percentage */
168609e7984SReshma Pattan enum busy_rate {
169609e7984SReshma Pattan 	ZERO = 0,
170609e7984SReshma Pattan 	PARTIAL = 50,
171609e7984SReshma Pattan 	FULL = 100
172609e7984SReshma Pattan };
173609e7984SReshma Pattan 
17410db2a5bSTadhg Kearney enum uncore_choice {
17510db2a5bSTadhg Kearney 	UNCORE_MIN = 0,
17610db2a5bSTadhg Kearney 	UNCORE_MAX = 1,
17710db2a5bSTadhg Kearney 	UNCORE_IDX = 2
17810db2a5bSTadhg Kearney };
17910db2a5bSTadhg Kearney 
180609e7984SReshma Pattan /* reference poll count to measure core busyness */
181609e7984SReshma Pattan #define DEFAULT_COUNT 10000
182609e7984SReshma Pattan /*
183609e7984SReshma Pattan  * reference CYCLES to be used to
184609e7984SReshma Pattan  * measure core busyness based on poll count
185609e7984SReshma Pattan  */
186609e7984SReshma Pattan #define MIN_CYCLES  1500000ULL
187b55d8fecSDavid Hunt #define MAX_CYCLES 22000000ULL
188609e7984SReshma Pattan 
189609e7984SReshma Pattan /* (500ms) */
190609e7984SReshma Pattan #define TELEMETRY_INTERVALS_PER_SEC 2
191a137d012SLiang Ma 
19282bea466SJianfeng Tan static int parse_ptype; /**< Parse packet type using rx callback, and */
19382bea466SJianfeng Tan 			/**< disabled by default */
194d7937e2eSIntel 
195609e7984SReshma Pattan enum appmode {
1962a0e2e2dSAnatoly Burakov 	APP_MODE_DEFAULT = 0,
1972a0e2e2dSAnatoly Burakov 	APP_MODE_LEGACY,
198e0194febSAnatoly Burakov 	APP_MODE_TELEMETRY,
19926fe454eSLiang Ma 	APP_MODE_INTERRUPT,
20026fe454eSLiang Ma 	APP_MODE_PMD_MGMT
201609e7984SReshma Pattan };
202609e7984SReshma Pattan 
203609e7984SReshma Pattan enum appmode app_mode;
204609e7984SReshma Pattan 
20526fe454eSLiang Ma static enum rte_power_pmd_mgmt_type pmgmt_type;
206a9ea6070SDavid Hunt bool baseline_enabled;
20726fe454eSLiang Ma 
208d7937e2eSIntel enum freq_scale_hint_t
209d7937e2eSIntel {
210d7937e2eSIntel 	FREQ_LOWER    =      -1,
211d7937e2eSIntel 	FREQ_CURRENT  =       0,
212d7937e2eSIntel 	FREQ_HIGHER   =       1,
213d7937e2eSIntel 	FREQ_HIGHEST  =       2
214d7937e2eSIntel };
215d7937e2eSIntel 
2167e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_rx_queue {
217f8244c63SZhiyong Yang 	uint16_t port_id;
218b23c5bd7SSivaprasad Tummala 	uint16_t queue_id;
219d7937e2eSIntel 	enum freq_scale_hint_t freq_up_hint;
220d7937e2eSIntel 	uint32_t zero_rx_packet_count;
221d7937e2eSIntel 	uint32_t idle_hint;
2227e06c0deSTyler Retzlaff };
223d7937e2eSIntel 
224d7937e2eSIntel #define MAX_RX_QUEUE_PER_LCORE 16
225d7937e2eSIntel #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
226d7937e2eSIntel #define MAX_RX_QUEUE_PER_PORT 128
227d7937e2eSIntel 
228aee3bc79SCunming Liang #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16
229aee3bc79SCunming Liang 
230aee3bc79SCunming Liang 
231f88e7c17SRadu Nicolau struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];
232d7937e2eSIntel static struct lcore_params lcore_params_array_default[] = {
233d7937e2eSIntel 	{0, 0, 2},
234d7937e2eSIntel 	{0, 1, 2},
235d7937e2eSIntel 	{0, 2, 2},
236d7937e2eSIntel 	{1, 0, 2},
237d7937e2eSIntel 	{1, 1, 2},
238d7937e2eSIntel 	{1, 2, 2},
239d7937e2eSIntel 	{2, 0, 2},
240d7937e2eSIntel 	{3, 0, 3},
241d7937e2eSIntel 	{3, 1, 3},
242d7937e2eSIntel };
243d7937e2eSIntel 
244f88e7c17SRadu Nicolau struct lcore_params *lcore_params = lcore_params_array_default;
2457efe28bdSPavan Nikhilesh uint16_t nb_lcore_params = RTE_DIM(lcore_params_array_default);
246d7937e2eSIntel 
247d7937e2eSIntel static struct rte_eth_conf port_conf = {
248d7937e2eSIntel 	.rxmode = {
249295968d1SFerruh Yigit 		.mq_mode        = RTE_ETH_MQ_RX_RSS,
250295968d1SFerruh Yigit 		.offloads = RTE_ETH_RX_OFFLOAD_CHECKSUM,
251d7937e2eSIntel 	},
252d7937e2eSIntel 	.rx_adv_conf = {
253d7937e2eSIntel 		.rss_conf = {
254d7937e2eSIntel 			.rss_key = NULL,
255295968d1SFerruh Yigit 			.rss_hf = RTE_ETH_RSS_UDP,
256d7937e2eSIntel 		},
257d7937e2eSIntel 	},
258d7937e2eSIntel 	.txmode = {
259295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_TX_NONE,
260f06493adSAnatoly Burakov 	}
261d7937e2eSIntel };
262d7937e2eSIntel 
2631bb4a528SFerruh Yigit static uint32_t max_pkt_len;
26459f2853cSKevin Laatz static uint32_t max_empty_polls = 512;
26559f2853cSKevin Laatz static uint32_t pause_duration = 1;
26659f2853cSKevin Laatz static uint32_t scale_freq_min;
26759f2853cSKevin Laatz static uint32_t scale_freq_max;
2681bb4a528SFerruh Yigit 
2694d23d39fSHuisong Li static int cpu_resume_latency = -1;
2704d23d39fSHuisong Li static int resume_latency_bk[RTE_MAX_LCORE];
2714d23d39fSHuisong Li 
272d7937e2eSIntel static struct rte_mempool * pktmbuf_pool[NB_SOCKETS];
273d7937e2eSIntel 
274d7937e2eSIntel 
275d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
276d7937e2eSIntel 
277193f9ec5SBruce Richardson #ifdef RTE_ARCH_X86
278d7937e2eSIntel #include <rte_hash_crc.h>
279d7937e2eSIntel #define DEFAULT_HASH_FUNC       rte_hash_crc
280d7937e2eSIntel #else
281d7937e2eSIntel #include <rte_jhash.h>
282d7937e2eSIntel #define DEFAULT_HASH_FUNC       rte_jhash
283d7937e2eSIntel #endif
284d7937e2eSIntel 
285*7f2a987cSAndre Muezerie struct __rte_packed_begin ipv4_5tuple {
286d7937e2eSIntel 	uint32_t ip_dst;
287d7937e2eSIntel 	uint32_t ip_src;
288d7937e2eSIntel 	uint16_t port_dst;
289d7937e2eSIntel 	uint16_t port_src;
290d7937e2eSIntel 	uint8_t  proto;
291*7f2a987cSAndre Muezerie } __rte_packed_end;
292d7937e2eSIntel 
293*7f2a987cSAndre Muezerie struct __rte_packed_begin ipv6_5tuple {
294d7937e2eSIntel 	uint8_t  ip_dst[IPV6_ADDR_LEN];
295d7937e2eSIntel 	uint8_t  ip_src[IPV6_ADDR_LEN];
296d7937e2eSIntel 	uint16_t port_dst;
297d7937e2eSIntel 	uint16_t port_src;
298d7937e2eSIntel 	uint8_t  proto;
299*7f2a987cSAndre Muezerie } __rte_packed_end;
300d7937e2eSIntel 
301d7937e2eSIntel struct ipv4_l3fwd_route {
302d7937e2eSIntel 	struct ipv4_5tuple key;
303d7937e2eSIntel 	uint8_t if_out;
304d7937e2eSIntel };
305d7937e2eSIntel 
306d7937e2eSIntel struct ipv6_l3fwd_route {
307d7937e2eSIntel 	struct ipv6_5tuple key;
308d7937e2eSIntel 	uint8_t if_out;
309d7937e2eSIntel };
310d7937e2eSIntel 
311d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = {
3120c9da755SDavid Marchand 	{{RTE_IPV4(100,10,0,1), RTE_IPV4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0},
3130c9da755SDavid Marchand 	{{RTE_IPV4(100,20,0,2), RTE_IPV4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1},
3140c9da755SDavid Marchand 	{{RTE_IPV4(100,30,0,3), RTE_IPV4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2},
3150c9da755SDavid Marchand 	{{RTE_IPV4(100,40,0,4), RTE_IPV4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3},
316d7937e2eSIntel };
317d7937e2eSIntel 
318d7937e2eSIntel static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
319d7937e2eSIntel 	{
320d7937e2eSIntel 		{
321d7937e2eSIntel 			{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322d7937e2eSIntel 			 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05},
323d7937e2eSIntel 			{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324d7937e2eSIntel 			 0x02, 0x1e, 0x67, 0xff, 0xfe, 0x0d, 0xb6, 0x0a},
325d7937e2eSIntel 			 1, 10, IPPROTO_UDP
326d7937e2eSIntel 		}, 4
327d7937e2eSIntel 	},
328d7937e2eSIntel };
329d7937e2eSIntel 
330d7937e2eSIntel typedef struct rte_hash lookup_struct_t;
331d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS];
332d7937e2eSIntel static lookup_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS];
333d7937e2eSIntel 
334d7937e2eSIntel #define L3FWD_HASH_ENTRIES	1024
335d7937e2eSIntel 
3367e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) uint16_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES];
3377e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) uint16_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES];
338d7937e2eSIntel #endif
339d7937e2eSIntel 
340d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
341d7937e2eSIntel struct ipv4_l3fwd_route {
342d7937e2eSIntel 	uint32_t ip;
343d7937e2eSIntel 	uint8_t  depth;
344d7937e2eSIntel 	uint8_t  if_out;
345d7937e2eSIntel };
346d7937e2eSIntel 
347d7937e2eSIntel static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = {
3480c9da755SDavid Marchand 	{RTE_IPV4(1,1,1,0), 24, 0},
3490c9da755SDavid Marchand 	{RTE_IPV4(2,1,1,0), 24, 1},
3500c9da755SDavid Marchand 	{RTE_IPV4(3,1,1,0), 24, 2},
3510c9da755SDavid Marchand 	{RTE_IPV4(4,1,1,0), 24, 3},
3520c9da755SDavid Marchand 	{RTE_IPV4(5,1,1,0), 24, 4},
3530c9da755SDavid Marchand 	{RTE_IPV4(6,1,1,0), 24, 5},
3540c9da755SDavid Marchand 	{RTE_IPV4(7,1,1,0), 24, 6},
3550c9da755SDavid Marchand 	{RTE_IPV4(8,1,1,0), 24, 7},
356d7937e2eSIntel };
357d7937e2eSIntel 
358d7937e2eSIntel #define IPV4_L3FWD_LPM_MAX_RULES     1024
359d7937e2eSIntel 
360d7937e2eSIntel typedef struct rte_lpm lookup_struct_t;
361d7937e2eSIntel static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS];
362d7937e2eSIntel #endif
363d7937e2eSIntel 
3647e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_conf {
365d7937e2eSIntel 	uint16_t n_rx_queue;
366d7937e2eSIntel 	struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
367e2366e74STomasz Kulasek 	uint16_t n_tx_port;
368e2366e74STomasz Kulasek 	uint16_t tx_port_id[RTE_MAX_ETHPORTS];
369d7937e2eSIntel 	uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
370e2366e74STomasz Kulasek 	struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
371d7937e2eSIntel 	lookup_struct_t * ipv4_lookup_struct;
372d7937e2eSIntel 	lookup_struct_t * ipv6_lookup_struct;
3737e06c0deSTyler Retzlaff };
374d7937e2eSIntel 
3757e06c0deSTyler Retzlaff struct __rte_cache_aligned lcore_stats {
376d7937e2eSIntel 	/* total sleep time in ms since last frequency scaling down */
377d7937e2eSIntel 	uint32_t sleep_time;
378d7937e2eSIntel 	/* number of long sleep recently */
379d7937e2eSIntel 	uint32_t nb_long_sleep;
380d7937e2eSIntel 	/* freq. scaling up trend */
381d7937e2eSIntel 	uint32_t trend;
382d7937e2eSIntel 	/* total packet processed recently */
383d7937e2eSIntel 	uint64_t nb_rx_processed;
384d7937e2eSIntel 	/* total iterations looped recently */
385d7937e2eSIntel 	uint64_t nb_iteration_looped;
386609e7984SReshma Pattan 	/*
387609e7984SReshma Pattan 	 * Represents empty and non empty polls
388609e7984SReshma Pattan 	 * of rte_eth_rx_burst();
389609e7984SReshma Pattan 	 * ep_nep[0] holds non empty polls
390609e7984SReshma Pattan 	 * i.e. 0 < nb_rx <= MAX_BURST
391609e7984SReshma Pattan 	 * ep_nep[1] holds empty polls.
392609e7984SReshma Pattan 	 * i.e. nb_rx == 0
393609e7984SReshma Pattan 	 */
394609e7984SReshma Pattan 	uint64_t ep_nep[2];
395609e7984SReshma Pattan 	/*
396609e7984SReshma Pattan 	 * Represents full and empty+partial
397609e7984SReshma Pattan 	 * polls of rte_eth_rx_burst();
398609e7984SReshma Pattan 	 * ep_nep[0] holds empty+partial polls.
399609e7984SReshma Pattan 	 * i.e. 0 <= nb_rx < MAX_BURST
400609e7984SReshma Pattan 	 * ep_nep[1] holds full polls
401609e7984SReshma Pattan 	 * i.e. nb_rx == MAX_BURST
402609e7984SReshma Pattan 	 */
403609e7984SReshma Pattan 	uint64_t fp_nfp[2];
404609e7984SReshma Pattan 	enum busy_rate br;
405609e7984SReshma Pattan 	rte_spinlock_t telemetry_lock;
4067e06c0deSTyler Retzlaff };
407d7937e2eSIntel 
4087e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) struct lcore_conf lcore_conf[RTE_MAX_LCORE];
4097e06c0deSTyler Retzlaff static alignas(RTE_CACHE_LINE_SIZE) struct lcore_stats stats[RTE_MAX_LCORE];
410d7937e2eSIntel static struct rte_timer power_timers[RTE_MAX_LCORE];
411d7937e2eSIntel 
412d7937e2eSIntel static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count);
413d7937e2eSIntel static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \
414f8244c63SZhiyong Yang 		unsigned int lcore_id, uint16_t port_id, uint16_t queue_id);
415d7937e2eSIntel 
416a137d012SLiang Ma static int is_done(void)
417a137d012SLiang Ma {
418609e7984SReshma Pattan 	return quit_signal;
419a137d012SLiang Ma }
420a137d012SLiang Ma 
421d7937e2eSIntel /* exit signal handler */
422d7937e2eSIntel static void
423d7937e2eSIntel signal_exit_now(int sigtype)
424d7937e2eSIntel {
425d7937e2eSIntel 
426613ce669SAnatoly Burakov 	if (sigtype == SIGINT)
427609e7984SReshma Pattan 		quit_signal = true;
428a137d012SLiang Ma 
429d7937e2eSIntel }
430d7937e2eSIntel 
4317be78d02SJosh Soref /*  Frequency scale down timer callback */
432d7937e2eSIntel static void
433f2fc83b4SThomas Monjalon power_timer_cb(__rte_unused struct rte_timer *tim,
434f2fc83b4SThomas Monjalon 			  __rte_unused void *arg)
435d7937e2eSIntel {
436d7937e2eSIntel 	uint64_t hz;
437d7937e2eSIntel 	float sleep_time_ratio;
438d7937e2eSIntel 	unsigned lcore_id = rte_lcore_id();
439d7937e2eSIntel 
440d7937e2eSIntel 	/* accumulate total execution time in us when callback is invoked */
441d7937e2eSIntel 	sleep_time_ratio = (float)(stats[lcore_id].sleep_time) /
442d7937e2eSIntel 					(float)SCALING_PERIOD;
443d7937e2eSIntel 	/**
444d7937e2eSIntel 	 * check whether need to scale down frequency a step if it sleep a lot.
445d7937e2eSIntel 	 */
446aee3bc79SCunming Liang 	if (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) {
447d7937e2eSIntel 		rte_power_freq_down(lcore_id);
448aee3bc79SCunming Liang 	}
449d7937e2eSIntel 	else if ( (unsigned)(stats[lcore_id].nb_rx_processed /
450aee3bc79SCunming Liang 		stats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) {
451d7937e2eSIntel 		/**
452d7937e2eSIntel 		 * scale down a step if average packet per iteration less
453d7937e2eSIntel 		 * than expectation.
454d7937e2eSIntel 		 */
455d7937e2eSIntel 		rte_power_freq_down(lcore_id);
456aee3bc79SCunming Liang 	}
457d7937e2eSIntel 
458d7937e2eSIntel 	/**
459d7937e2eSIntel 	 * initialize another timer according to current frequency to ensure
460d7937e2eSIntel 	 * timer interval is relatively fixed.
461d7937e2eSIntel 	 */
462d7937e2eSIntel 	hz = rte_get_timer_hz();
463d7937e2eSIntel 	rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND,
464d7937e2eSIntel 				SINGLE, lcore_id, power_timer_cb, NULL);
465d7937e2eSIntel 
466d7937e2eSIntel 	stats[lcore_id].nb_rx_processed = 0;
467d7937e2eSIntel 	stats[lcore_id].nb_iteration_looped = 0;
468d7937e2eSIntel 
469d7937e2eSIntel 	stats[lcore_id].sleep_time = 0;
470d7937e2eSIntel }
471d7937e2eSIntel 
472d7937e2eSIntel /* Enqueue a single packet, and send burst if queue is filled */
473d7937e2eSIntel static inline int
47447523597SZhiyong Yang send_single_packet(struct rte_mbuf *m, uint16_t port)
475d7937e2eSIntel {
476d7937e2eSIntel 	uint32_t lcore_id;
477d7937e2eSIntel 	struct lcore_conf *qconf;
478d7937e2eSIntel 
479d7937e2eSIntel 	lcore_id = rte_lcore_id();
480d7937e2eSIntel 	qconf = &lcore_conf[lcore_id];
481d7937e2eSIntel 
482e2366e74STomasz Kulasek 	rte_eth_tx_buffer(port, qconf->tx_queue_id[port],
483e2366e74STomasz Kulasek 			qconf->tx_buffer[port], m);
484d7937e2eSIntel 
485d7937e2eSIntel 	return 0;
486d7937e2eSIntel }
487d7937e2eSIntel 
488d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS
489d7937e2eSIntel static inline int
490a7c528e5SOlivier Matz is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
491d7937e2eSIntel {
492d7937e2eSIntel 	/* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */
493d7937e2eSIntel 	/*
494d7937e2eSIntel 	 * 1. The packet length reported by the Link Layer must be large
495d7937e2eSIntel 	 * enough to hold the minimum length legal IP datagram (20 bytes).
496d7937e2eSIntel 	 */
497a7c528e5SOlivier Matz 	if (link_len < sizeof(struct rte_ipv4_hdr))
498d7937e2eSIntel 		return -1;
499d7937e2eSIntel 
500d7937e2eSIntel 	/* 2. The IP checksum must be correct. */
501f0b00d98SMiao Li 	/* if this is not checked in H/W, check it. */
502f0b00d98SMiao Li 	if ((port_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) == 0) {
503f0b00d98SMiao Li 		uint16_t actual_cksum, expected_cksum;
504f0b00d98SMiao Li 		actual_cksum = pkt->hdr_checksum;
505f0b00d98SMiao Li 		pkt->hdr_checksum = 0;
506f0b00d98SMiao Li 		expected_cksum = rte_ipv4_cksum(pkt);
507f0b00d98SMiao Li 		if (actual_cksum != expected_cksum)
508f0b00d98SMiao Li 			return -2;
509f0b00d98SMiao Li 	}
510d7937e2eSIntel 
511d7937e2eSIntel 	/*
512d7937e2eSIntel 	 * 3. The IP version number must be 4. If the version number is not 4
513d7937e2eSIntel 	 * then the packet may be another version of IP, such as IPng or
514d7937e2eSIntel 	 * ST-II.
515d7937e2eSIntel 	 */
516d7937e2eSIntel 	if (((pkt->version_ihl) >> 4) != 4)
517d7937e2eSIntel 		return -3;
518d7937e2eSIntel 	/*
519d7937e2eSIntel 	 * 4. The IP header length field must be large enough to hold the
520d7937e2eSIntel 	 * minimum length legal IP datagram (20 bytes = 5 words).
521d7937e2eSIntel 	 */
522d7937e2eSIntel 	if ((pkt->version_ihl & 0xf) < 5)
523d7937e2eSIntel 		return -4;
524d7937e2eSIntel 
525d7937e2eSIntel 	/*
526d7937e2eSIntel 	 * 5. The IP total length field must be large enough to hold the IP
527d7937e2eSIntel 	 * datagram header, whose length is specified in the IP header length
528d7937e2eSIntel 	 * field.
529d7937e2eSIntel 	 */
530a7c528e5SOlivier Matz 	if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr))
531d7937e2eSIntel 		return -5;
532d7937e2eSIntel 
533d7937e2eSIntel 	return 0;
534d7937e2eSIntel }
535d7937e2eSIntel #endif
536d7937e2eSIntel 
537d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
538d7937e2eSIntel static void
539d7937e2eSIntel print_ipv4_key(struct ipv4_5tuple key)
540d7937e2eSIntel {
541d7937e2eSIntel 	printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, "
542d7937e2eSIntel 		"proto = %d\n", (unsigned)key.ip_dst, (unsigned)key.ip_src,
543d7937e2eSIntel 				key.port_dst, key.port_src, key.proto);
544d7937e2eSIntel }
545d7937e2eSIntel static void
546d7937e2eSIntel print_ipv6_key(struct ipv6_5tuple key)
547d7937e2eSIntel {
548d7937e2eSIntel 	printf( "IP dst = " IPv6_BYTES_FMT ", IP src = " IPv6_BYTES_FMT ", "
549d7937e2eSIntel 	        "port dst = %d, port src = %d, proto = %d\n",
550d7937e2eSIntel 	        IPv6_BYTES(key.ip_dst), IPv6_BYTES(key.ip_src),
551d7937e2eSIntel 	        key.port_dst, key.port_src, key.proto);
552d7937e2eSIntel }
553d7937e2eSIntel 
554f8244c63SZhiyong Yang static inline uint16_t
555a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid,
556d7937e2eSIntel 		lookup_struct_t * ipv4_l3fwd_lookup_struct)
557d7937e2eSIntel {
558d7937e2eSIntel 	struct ipv4_5tuple key;
559f41b5156SOlivier Matz 	struct rte_tcp_hdr *tcp;
560e73e3547SOlivier Matz 	struct rte_udp_hdr *udp;
561d7937e2eSIntel 	int ret = 0;
562d7937e2eSIntel 
563d7937e2eSIntel 	key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
564d7937e2eSIntel 	key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr);
565d7937e2eSIntel 	key.proto = ipv4_hdr->next_proto_id;
566d7937e2eSIntel 
567d7937e2eSIntel 	switch (ipv4_hdr->next_proto_id) {
568d7937e2eSIntel 	case IPPROTO_TCP:
569f41b5156SOlivier Matz 		tcp = (struct rte_tcp_hdr *)((unsigned char *)ipv4_hdr +
570a7c528e5SOlivier Matz 					sizeof(struct rte_ipv4_hdr));
571d7937e2eSIntel 		key.port_dst = rte_be_to_cpu_16(tcp->dst_port);
572d7937e2eSIntel 		key.port_src = rte_be_to_cpu_16(tcp->src_port);
573d7937e2eSIntel 		break;
574d7937e2eSIntel 
575d7937e2eSIntel 	case IPPROTO_UDP:
576e73e3547SOlivier Matz 		udp = (struct rte_udp_hdr *)((unsigned char *)ipv4_hdr +
577a7c528e5SOlivier Matz 					sizeof(struct rte_ipv4_hdr));
578d7937e2eSIntel 		key.port_dst = rte_be_to_cpu_16(udp->dst_port);
579d7937e2eSIntel 		key.port_src = rte_be_to_cpu_16(udp->src_port);
580d7937e2eSIntel 		break;
581d7937e2eSIntel 
582d7937e2eSIntel 	default:
583d7937e2eSIntel 		key.port_dst = 0;
584d7937e2eSIntel 		key.port_src = 0;
585d7937e2eSIntel 		break;
586d7937e2eSIntel 	}
587d7937e2eSIntel 
588d7937e2eSIntel 	/* Find destination port */
589d7937e2eSIntel 	ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key);
590f8244c63SZhiyong Yang 	return ((ret < 0) ? portid : ipv4_l3fwd_out_if[ret]);
591d7937e2eSIntel }
592d7937e2eSIntel 
593f8244c63SZhiyong Yang static inline uint16_t
594a7c528e5SOlivier Matz get_ipv6_dst_port(struct rte_ipv6_hdr *ipv6_hdr, uint16_t portid,
595d7937e2eSIntel 			lookup_struct_t *ipv6_l3fwd_lookup_struct)
596d7937e2eSIntel {
597d7937e2eSIntel 	struct ipv6_5tuple key;
598f41b5156SOlivier Matz 	struct rte_tcp_hdr *tcp;
599e73e3547SOlivier Matz 	struct rte_udp_hdr *udp;
600d7937e2eSIntel 	int ret = 0;
601d7937e2eSIntel 
602d7937e2eSIntel 	memcpy(key.ip_dst, ipv6_hdr->dst_addr, IPV6_ADDR_LEN);
603d7937e2eSIntel 	memcpy(key.ip_src, ipv6_hdr->src_addr, IPV6_ADDR_LEN);
604d7937e2eSIntel 
605d7937e2eSIntel 	key.proto = ipv6_hdr->proto;
606d7937e2eSIntel 
607d7937e2eSIntel 	switch (ipv6_hdr->proto) {
608d7937e2eSIntel 	case IPPROTO_TCP:
609f41b5156SOlivier Matz 		tcp = (struct rte_tcp_hdr *)((unsigned char *) ipv6_hdr +
610a7c528e5SOlivier Matz 					sizeof(struct rte_ipv6_hdr));
611d7937e2eSIntel 		key.port_dst = rte_be_to_cpu_16(tcp->dst_port);
612d7937e2eSIntel 		key.port_src = rte_be_to_cpu_16(tcp->src_port);
613d7937e2eSIntel 		break;
614d7937e2eSIntel 
615d7937e2eSIntel 	case IPPROTO_UDP:
616e73e3547SOlivier Matz 		udp = (struct rte_udp_hdr *)((unsigned char *) ipv6_hdr +
617a7c528e5SOlivier Matz 					sizeof(struct rte_ipv6_hdr));
618d7937e2eSIntel 		key.port_dst = rte_be_to_cpu_16(udp->dst_port);
619d7937e2eSIntel 		key.port_src = rte_be_to_cpu_16(udp->src_port);
620d7937e2eSIntel 		break;
621d7937e2eSIntel 
622d7937e2eSIntel 	default:
623d7937e2eSIntel 		key.port_dst = 0;
624d7937e2eSIntel 		key.port_src = 0;
625d7937e2eSIntel 		break;
626d7937e2eSIntel 	}
627d7937e2eSIntel 
628d7937e2eSIntel 	/* Find destination port */
629d7937e2eSIntel 	ret = rte_hash_lookup(ipv6_l3fwd_lookup_struct, (const void *)&key);
630f8244c63SZhiyong Yang 	return ((ret < 0) ? portid : ipv6_l3fwd_out_if[ret]);
631d7937e2eSIntel }
632d7937e2eSIntel #endif
633d7937e2eSIntel 
634d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
635f8244c63SZhiyong Yang static inline uint16_t
636a7c528e5SOlivier Matz get_ipv4_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid,
637d7937e2eSIntel 		lookup_struct_t *ipv4_l3fwd_lookup_struct)
638d7937e2eSIntel {
639dc81ebbaSMichal Kobylinski 	uint32_t next_hop;
640d7937e2eSIntel 
641f8244c63SZhiyong Yang 	return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct,
642d7937e2eSIntel 			rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)?
643d7937e2eSIntel 			next_hop : portid);
644d7937e2eSIntel }
645d7937e2eSIntel #endif
646d7937e2eSIntel 
647d7937e2eSIntel static inline void
64882bea466SJianfeng Tan parse_ptype_one(struct rte_mbuf *m)
64982bea466SJianfeng Tan {
6506d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
65182bea466SJianfeng Tan 	uint32_t packet_type = RTE_PTYPE_UNKNOWN;
65282bea466SJianfeng Tan 	uint16_t ether_type;
65382bea466SJianfeng Tan 
6546d13ea8eSOlivier Matz 	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
65582bea466SJianfeng Tan 	ether_type = eth_hdr->ether_type;
6560c9da755SDavid Marchand 	if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
65782bea466SJianfeng Tan 		packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
6580c9da755SDavid Marchand 	else if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6))
65982bea466SJianfeng Tan 		packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
66082bea466SJianfeng Tan 
66182bea466SJianfeng Tan 	m->packet_type = packet_type;
66282bea466SJianfeng Tan }
66382bea466SJianfeng Tan 
66482bea466SJianfeng Tan static uint16_t
665f8244c63SZhiyong Yang cb_parse_ptype(uint16_t port __rte_unused, uint16_t queue __rte_unused,
66682bea466SJianfeng Tan 	       struct rte_mbuf *pkts[], uint16_t nb_pkts,
66782bea466SJianfeng Tan 	       uint16_t max_pkts __rte_unused,
66882bea466SJianfeng Tan 	       void *user_param __rte_unused)
66982bea466SJianfeng Tan {
67082bea466SJianfeng Tan 	unsigned int i;
67182bea466SJianfeng Tan 
67282bea466SJianfeng Tan 	for (i = 0; i < nb_pkts; ++i)
67382bea466SJianfeng Tan 		parse_ptype_one(pkts[i]);
67482bea466SJianfeng Tan 
67582bea466SJianfeng Tan 	return nb_pkts;
67682bea466SJianfeng Tan }
67782bea466SJianfeng Tan 
67882bea466SJianfeng Tan static int
679f8244c63SZhiyong Yang add_cb_parse_ptype(uint16_t portid, uint16_t queueid)
68082bea466SJianfeng Tan {
68182bea466SJianfeng Tan 	printf("Port %d: softly parse packet type info\n", portid);
68282bea466SJianfeng Tan 	if (rte_eth_add_rx_callback(portid, queueid, cb_parse_ptype, NULL))
68382bea466SJianfeng Tan 		return 0;
68482bea466SJianfeng Tan 
68582bea466SJianfeng Tan 	printf("Failed to add rx callback: port=%d\n", portid);
68682bea466SJianfeng Tan 	return -1;
68782bea466SJianfeng Tan }
68882bea466SJianfeng Tan 
68982bea466SJianfeng Tan static inline void
69047523597SZhiyong Yang l3fwd_simple_forward(struct rte_mbuf *m, uint16_t portid,
691d7937e2eSIntel 				struct lcore_conf *qconf)
692d7937e2eSIntel {
6936d13ea8eSOlivier Matz 	struct rte_ether_hdr *eth_hdr;
694a7c528e5SOlivier Matz 	struct rte_ipv4_hdr *ipv4_hdr;
695d7937e2eSIntel 	void *d_addr_bytes;
696f8244c63SZhiyong Yang 	uint16_t dst_port;
697d7937e2eSIntel 
6986d13ea8eSOlivier Matz 	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
699d7937e2eSIntel 
7003c0184ccSHelin Zhang 	if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
701d7937e2eSIntel 		/* Handle IPv4 headers.*/
702d7937e2eSIntel 		ipv4_hdr =
703a7c528e5SOlivier Matz 			rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
7046d13ea8eSOlivier Matz 						sizeof(struct rte_ether_hdr));
705d7937e2eSIntel 
706d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS
707d7937e2eSIntel 		/* Check to make sure the packet is valid (RFC1812) */
708ea672a8bSOlivier Matz 		if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) {
709d7937e2eSIntel 			rte_pktmbuf_free(m);
710d7937e2eSIntel 			return;
711d7937e2eSIntel 		}
712d7937e2eSIntel #endif
713d7937e2eSIntel 
714d7937e2eSIntel 		dst_port = get_ipv4_dst_port(ipv4_hdr, portid,
715d7937e2eSIntel 					qconf->ipv4_lookup_struct);
716d7937e2eSIntel 		if (dst_port >= RTE_MAX_ETHPORTS ||
717d7937e2eSIntel 				(enabled_port_mask & 1 << dst_port) == 0)
718d7937e2eSIntel 			dst_port = portid;
719d7937e2eSIntel 
720d7937e2eSIntel 		/* 02:00:00:00:00:xx */
72104d43857SDmitry Kozlyuk 		d_addr_bytes = &eth_hdr->dst_addr.addr_bytes[0];
722d7937e2eSIntel 		*((uint64_t *)d_addr_bytes) =
723d7937e2eSIntel 			0x000000000002 + ((uint64_t)dst_port << 40);
724d7937e2eSIntel 
725d7937e2eSIntel #ifdef DO_RFC_1812_CHECKS
726d7937e2eSIntel 		/* Update time to live and header checksum */
727d7937e2eSIntel 		--(ipv4_hdr->time_to_live);
728d7937e2eSIntel 		++(ipv4_hdr->hdr_checksum);
729d7937e2eSIntel #endif
730d7937e2eSIntel 
731d7937e2eSIntel 		/* src addr */
732538da7a1SOlivier Matz 		rte_ether_addr_copy(&ports_eth_addr[dst_port],
73304d43857SDmitry Kozlyuk 				&eth_hdr->src_addr);
734d7937e2eSIntel 
735d7937e2eSIntel 		send_single_packet(m, dst_port);
7363c0184ccSHelin Zhang 	} else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
737d7937e2eSIntel 		/* Handle IPv6 headers.*/
738d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
739a7c528e5SOlivier Matz 		struct rte_ipv6_hdr *ipv6_hdr;
740d7937e2eSIntel 
741d7937e2eSIntel 		ipv6_hdr =
742a7c528e5SOlivier Matz 			rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
7436d13ea8eSOlivier Matz 						sizeof(struct rte_ether_hdr));
744d7937e2eSIntel 
745d7937e2eSIntel 		dst_port = get_ipv6_dst_port(ipv6_hdr, portid,
746d7937e2eSIntel 					qconf->ipv6_lookup_struct);
747d7937e2eSIntel 
748d7937e2eSIntel 		if (dst_port >= RTE_MAX_ETHPORTS ||
749d7937e2eSIntel 				(enabled_port_mask & 1 << dst_port) == 0)
750d7937e2eSIntel 			dst_port = portid;
751d7937e2eSIntel 
752d7937e2eSIntel 		/* 02:00:00:00:00:xx */
75304d43857SDmitry Kozlyuk 		d_addr_bytes = &eth_hdr->dst_addr.addr_bytes[0];
754d7937e2eSIntel 		*((uint64_t *)d_addr_bytes) =
755d7937e2eSIntel 			0x000000000002 + ((uint64_t)dst_port << 40);
756d7937e2eSIntel 
757d7937e2eSIntel 		/* src addr */
758538da7a1SOlivier Matz 		rte_ether_addr_copy(&ports_eth_addr[dst_port],
75904d43857SDmitry Kozlyuk 				&eth_hdr->src_addr);
760d7937e2eSIntel 
761d7937e2eSIntel 		send_single_packet(m, dst_port);
762d7937e2eSIntel #else
763d7937e2eSIntel 		/* We don't currently handle IPv6 packets in LPM mode. */
764d7937e2eSIntel 		rte_pktmbuf_free(m);
765d7937e2eSIntel #endif
766bec2f7dfSShaopeng He 	} else
767bec2f7dfSShaopeng He 		rte_pktmbuf_free(m);
768d7937e2eSIntel 
769d7937e2eSIntel }
770d7937e2eSIntel 
771aee3bc79SCunming Liang #define MINIMUM_SLEEP_TIME         1
772aee3bc79SCunming Liang #define SUSPEND_THRESHOLD          300
773d7937e2eSIntel 
774d7937e2eSIntel static inline uint32_t
775d7937e2eSIntel power_idle_heuristic(uint32_t zero_rx_packet_count)
776d7937e2eSIntel {
777aee3bc79SCunming Liang 	/* If zero count is less than 100,  sleep 1us */
778aee3bc79SCunming Liang 	if (zero_rx_packet_count < SUSPEND_THRESHOLD)
779aee3bc79SCunming Liang 		return MINIMUM_SLEEP_TIME;
780aee3bc79SCunming Liang 	/* If zero count is less than 1000, sleep 100 us which is the
781aee3bc79SCunming Liang 		minimum latency switching from C3/C6 to C0
782aee3bc79SCunming Liang 	*/
783aee3bc79SCunming Liang 	else
784aee3bc79SCunming Liang 		return SUSPEND_THRESHOLD;
785d7937e2eSIntel }
786d7937e2eSIntel 
787d7937e2eSIntel static inline enum freq_scale_hint_t
788b451aa39SIntel power_freq_scaleup_heuristic(unsigned lcore_id,
789f8244c63SZhiyong Yang 			     uint16_t port_id,
790b451aa39SIntel 			     uint16_t queue_id)
791d7937e2eSIntel {
79247d834baSNikhil Agarwal 	uint32_t rxq_count = rte_eth_rx_queue_count(port_id, queue_id);
793d7937e2eSIntel /**
794d7937e2eSIntel  * HW Rx queue size is 128 by default, Rx burst read at maximum 32 entries
795d7937e2eSIntel  * per iteration
796d7937e2eSIntel  */
797d7937e2eSIntel #define FREQ_GEAR1_RX_PACKET_THRESHOLD             MAX_PKT_BURST
798b451aa39SIntel #define FREQ_GEAR2_RX_PACKET_THRESHOLD             (MAX_PKT_BURST*2)
799b451aa39SIntel #define FREQ_GEAR3_RX_PACKET_THRESHOLD             (MAX_PKT_BURST*3)
800d7937e2eSIntel #define FREQ_UP_TREND1_ACC   1
801d7937e2eSIntel #define FREQ_UP_TREND2_ACC   100
802d7937e2eSIntel #define FREQ_UP_THRESHOLD    10000
803d7937e2eSIntel 
80447d834baSNikhil Agarwal 	if (likely(rxq_count > FREQ_GEAR3_RX_PACKET_THRESHOLD)) {
805d7937e2eSIntel 		stats[lcore_id].trend = 0;
806d7937e2eSIntel 		return FREQ_HIGHEST;
80747d834baSNikhil Agarwal 	} else if (likely(rxq_count > FREQ_GEAR2_RX_PACKET_THRESHOLD))
808d7937e2eSIntel 		stats[lcore_id].trend += FREQ_UP_TREND2_ACC;
80947d834baSNikhil Agarwal 	else if (likely(rxq_count > FREQ_GEAR1_RX_PACKET_THRESHOLD))
810d7937e2eSIntel 		stats[lcore_id].trend += FREQ_UP_TREND1_ACC;
811d7937e2eSIntel 
812b451aa39SIntel 	if (likely(stats[lcore_id].trend > FREQ_UP_THRESHOLD)) {
813d7937e2eSIntel 		stats[lcore_id].trend = 0;
814d7937e2eSIntel 		return FREQ_HIGHER;
815d7937e2eSIntel 	}
816d7937e2eSIntel 
817d7937e2eSIntel 	return FREQ_CURRENT;
818d7937e2eSIntel }
819d7937e2eSIntel 
820aee3bc79SCunming Liang /**
821aee3bc79SCunming Liang  * force polling thread sleep until one-shot rx interrupt triggers
822aee3bc79SCunming Liang  * @param port_id
823aee3bc79SCunming Liang  *  Port id.
824aee3bc79SCunming Liang  * @param queue_id
825aee3bc79SCunming Liang  *  Rx queue id.
826aee3bc79SCunming Liang  * @return
827aee3bc79SCunming Liang  *  0 on success
828aee3bc79SCunming Liang  */
829aee3bc79SCunming Liang static int
830317a1da8SAnatoly Burakov sleep_until_rx_interrupt(int num, int lcore)
831aee3bc79SCunming Liang {
832f4d1e19cSAnatoly Burakov 	/*
833f4d1e19cSAnatoly Burakov 	 * we want to track when we are woken up by traffic so that we can go
834317a1da8SAnatoly Burakov 	 * back to sleep again without log spamming. Avoid cache line sharing
835317a1da8SAnatoly Burakov 	 * to prevent threads stepping on each others' toes.
836f4d1e19cSAnatoly Burakov 	 */
8377e06c0deSTyler Retzlaff 	static alignas(RTE_CACHE_LINE_SIZE) struct {
838317a1da8SAnatoly Burakov 		bool wakeup;
8397e06c0deSTyler Retzlaff 	} status[RTE_MAX_LCORE];
840aee3bc79SCunming Liang 	struct rte_epoll_event event[num];
841aee3bc79SCunming Liang 	int n, i;
842f8244c63SZhiyong Yang 	uint16_t port_id;
843b23c5bd7SSivaprasad Tummala 	uint16_t queue_id;
844aee3bc79SCunming Liang 	void *data;
845aee3bc79SCunming Liang 
846317a1da8SAnatoly Burakov 	if (status[lcore].wakeup) {
847aee3bc79SCunming Liang 		RTE_LOG(INFO, L3FWD_POWER,
848aee3bc79SCunming Liang 				"lcore %u sleeps until interrupt triggers\n",
849aee3bc79SCunming Liang 				rte_lcore_id());
850f4d1e19cSAnatoly Burakov 	}
851aee3bc79SCunming Liang 
852f4d1e19cSAnatoly Burakov 	n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, 10);
853aee3bc79SCunming Liang 	for (i = 0; i < n; i++) {
854aee3bc79SCunming Liang 		data = event[i].epdata.data;
855b23c5bd7SSivaprasad Tummala 		port_id = ((uintptr_t)data) >> (sizeof(uint16_t) * CHAR_BIT);
856aee3bc79SCunming Liang 		queue_id = ((uintptr_t)data) &
857b23c5bd7SSivaprasad Tummala 			RTE_LEN2MASK((sizeof(uint16_t) * CHAR_BIT), uint16_t);
858aee3bc79SCunming Liang 		RTE_LOG(INFO, L3FWD_POWER,
859aee3bc79SCunming Liang 			"lcore %u is waked up from rx interrupt on"
860aee3bc79SCunming Liang 			" port %d queue %d\n",
861aee3bc79SCunming Liang 			rte_lcore_id(), port_id, queue_id);
862aee3bc79SCunming Liang 	}
863317a1da8SAnatoly Burakov 	status[lcore].wakeup = n != 0;
864aee3bc79SCunming Liang 
865aee3bc79SCunming Liang 	return 0;
866aee3bc79SCunming Liang }
867aee3bc79SCunming Liang 
86849dcf7b9SXiao Wang static void turn_on_off_intr(struct lcore_conf *qconf, bool on)
869aee3bc79SCunming Liang {
870aee3bc79SCunming Liang 	int i;
871aee3bc79SCunming Liang 	struct lcore_rx_queue *rx_queue;
872b23c5bd7SSivaprasad Tummala 	uint16_t queue_id;
873f8244c63SZhiyong Yang 	uint16_t port_id;
874aee3bc79SCunming Liang 
875aee3bc79SCunming Liang 	for (i = 0; i < qconf->n_rx_queue; ++i) {
876aee3bc79SCunming Liang 		rx_queue = &(qconf->rx_queue_list[i]);
877aee3bc79SCunming Liang 		port_id = rx_queue->port_id;
878aee3bc79SCunming Liang 		queue_id = rx_queue->queue_id;
879aee3bc79SCunming Liang 
880aee3bc79SCunming Liang 		rte_spinlock_lock(&(locks[port_id]));
88149dcf7b9SXiao Wang 		if (on)
882aee3bc79SCunming Liang 			rte_eth_dev_rx_intr_enable(port_id, queue_id);
88349dcf7b9SXiao Wang 		else
88449dcf7b9SXiao Wang 			rte_eth_dev_rx_intr_disable(port_id, queue_id);
885aee3bc79SCunming Liang 		rte_spinlock_unlock(&(locks[port_id]));
886aee3bc79SCunming Liang 	}
887aee3bc79SCunming Liang }
888aee3bc79SCunming Liang 
889aee3bc79SCunming Liang static int event_register(struct lcore_conf *qconf)
890aee3bc79SCunming Liang {
891aee3bc79SCunming Liang 	struct lcore_rx_queue *rx_queue;
892b23c5bd7SSivaprasad Tummala 	uint16_t queueid;
893f8244c63SZhiyong Yang 	uint16_t portid;
894aee3bc79SCunming Liang 	uint32_t data;
895aee3bc79SCunming Liang 	int ret;
896aee3bc79SCunming Liang 	int i;
897aee3bc79SCunming Liang 
898aee3bc79SCunming Liang 	for (i = 0; i < qconf->n_rx_queue; ++i) {
899aee3bc79SCunming Liang 		rx_queue = &(qconf->rx_queue_list[i]);
900aee3bc79SCunming Liang 		portid = rx_queue->port_id;
901aee3bc79SCunming Liang 		queueid = rx_queue->queue_id;
902b23c5bd7SSivaprasad Tummala 		data = portid << (sizeof(uint16_t) * CHAR_BIT) | queueid;
903aee3bc79SCunming Liang 
904aee3bc79SCunming Liang 		ret = rte_eth_dev_rx_intr_ctl_q(portid, queueid,
905aee3bc79SCunming Liang 						RTE_EPOLL_PER_THREAD,
906aee3bc79SCunming Liang 						RTE_INTR_EVENT_ADD,
907aee3bc79SCunming Liang 						(void *)((uintptr_t)data));
908aee3bc79SCunming Liang 		if (ret)
909aee3bc79SCunming Liang 			return ret;
910aee3bc79SCunming Liang 	}
911aee3bc79SCunming Liang 
912aee3bc79SCunming Liang 	return 0;
913aee3bc79SCunming Liang }
914e0194febSAnatoly Burakov 
9159a212dc0SConor Fogarty /* Main processing loop. 8< */
916e0194febSAnatoly Burakov static int main_intr_loop(__rte_unused void *dummy)
917e0194febSAnatoly Burakov {
918e0194febSAnatoly Burakov 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
919e0194febSAnatoly Burakov 	unsigned int lcore_id;
920e0194febSAnatoly Burakov 	uint64_t prev_tsc, diff_tsc, cur_tsc;
921e0194febSAnatoly Burakov 	int i, j, nb_rx;
922b23c5bd7SSivaprasad Tummala 	uint16_t portid, queueid;
923e0194febSAnatoly Burakov 	struct lcore_conf *qconf;
924e0194febSAnatoly Burakov 	struct lcore_rx_queue *rx_queue;
925e0194febSAnatoly Burakov 	uint32_t lcore_rx_idle_count = 0;
926e0194febSAnatoly Burakov 	uint32_t lcore_idle_hint = 0;
927e0194febSAnatoly Burakov 	int intr_en = 0;
928e0194febSAnatoly Burakov 
929e0194febSAnatoly Burakov 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
930e0194febSAnatoly Burakov 				   US_PER_S * BURST_TX_DRAIN_US;
931e0194febSAnatoly Burakov 
932e0194febSAnatoly Burakov 	prev_tsc = 0;
933e0194febSAnatoly Burakov 
934e0194febSAnatoly Burakov 	lcore_id = rte_lcore_id();
935e0194febSAnatoly Burakov 	qconf = &lcore_conf[lcore_id];
936e0194febSAnatoly Burakov 
937e0194febSAnatoly Burakov 	if (qconf->n_rx_queue == 0) {
938e0194febSAnatoly Burakov 		RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n",
939e0194febSAnatoly Burakov 				lcore_id);
940e0194febSAnatoly Burakov 		return 0;
941e0194febSAnatoly Burakov 	}
942e0194febSAnatoly Burakov 
943e0194febSAnatoly Burakov 	RTE_LOG(INFO, L3FWD_POWER, "entering main interrupt loop on lcore %u\n",
944e0194febSAnatoly Burakov 			lcore_id);
945e0194febSAnatoly Burakov 
946e0194febSAnatoly Burakov 	for (i = 0; i < qconf->n_rx_queue; i++) {
947e0194febSAnatoly Burakov 		portid = qconf->rx_queue_list[i].port_id;
948e0194febSAnatoly Burakov 		queueid = qconf->rx_queue_list[i].queue_id;
949e0194febSAnatoly Burakov 		RTE_LOG(INFO, L3FWD_POWER,
950b23c5bd7SSivaprasad Tummala 				" -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n",
951e0194febSAnatoly Burakov 				lcore_id, portid, queueid);
952e0194febSAnatoly Burakov 	}
953e0194febSAnatoly Burakov 
954e0194febSAnatoly Burakov 	/* add into event wait list */
955e0194febSAnatoly Burakov 	if (event_register(qconf) == 0)
956e0194febSAnatoly Burakov 		intr_en = 1;
957e0194febSAnatoly Burakov 	else
958e0194febSAnatoly Burakov 		RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n");
959e0194febSAnatoly Burakov 
960e0194febSAnatoly Burakov 	while (!is_done()) {
961e0194febSAnatoly Burakov 		stats[lcore_id].nb_iteration_looped++;
962e0194febSAnatoly Burakov 
963e0194febSAnatoly Burakov 		cur_tsc = rte_rdtsc();
964e0194febSAnatoly Burakov 
965e0194febSAnatoly Burakov 		/*
966e0194febSAnatoly Burakov 		 * TX burst queue drain
967e0194febSAnatoly Burakov 		 */
968e0194febSAnatoly Burakov 		diff_tsc = cur_tsc - prev_tsc;
969e0194febSAnatoly Burakov 		if (unlikely(diff_tsc > drain_tsc)) {
970e0194febSAnatoly Burakov 			for (i = 0; i < qconf->n_tx_port; ++i) {
971e0194febSAnatoly Burakov 				portid = qconf->tx_port_id[i];
972e0194febSAnatoly Burakov 				rte_eth_tx_buffer_flush(portid,
973e0194febSAnatoly Burakov 						qconf->tx_queue_id[portid],
974e0194febSAnatoly Burakov 						qconf->tx_buffer[portid]);
975e0194febSAnatoly Burakov 			}
976e0194febSAnatoly Burakov 			prev_tsc = cur_tsc;
977e0194febSAnatoly Burakov 		}
978e0194febSAnatoly Burakov 
979e0194febSAnatoly Burakov start_rx:
980e0194febSAnatoly Burakov 		/*
981e0194febSAnatoly Burakov 		 * Read packet from RX queues
982e0194febSAnatoly Burakov 		 */
983e0194febSAnatoly Burakov 		lcore_rx_idle_count = 0;
984e0194febSAnatoly Burakov 		for (i = 0; i < qconf->n_rx_queue; ++i) {
985e0194febSAnatoly Burakov 			rx_queue = &(qconf->rx_queue_list[i]);
986e0194febSAnatoly Burakov 			rx_queue->idle_hint = 0;
987e0194febSAnatoly Burakov 			portid = rx_queue->port_id;
988e0194febSAnatoly Burakov 			queueid = rx_queue->queue_id;
989e0194febSAnatoly Burakov 
990e0194febSAnatoly Burakov 			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
991e0194febSAnatoly Burakov 					MAX_PKT_BURST);
992e0194febSAnatoly Burakov 
993e0194febSAnatoly Burakov 			stats[lcore_id].nb_rx_processed += nb_rx;
994e0194febSAnatoly Burakov 			if (unlikely(nb_rx == 0)) {
995e0194febSAnatoly Burakov 				/**
996e0194febSAnatoly Burakov 				 * no packet received from rx queue, try to
997e0194febSAnatoly Burakov 				 * sleep for a while forcing CPU enter deeper
998e0194febSAnatoly Burakov 				 * C states.
999e0194febSAnatoly Burakov 				 */
1000e0194febSAnatoly Burakov 				rx_queue->zero_rx_packet_count++;
1001e0194febSAnatoly Burakov 
1002e0194febSAnatoly Burakov 				if (rx_queue->zero_rx_packet_count <=
1003e0194febSAnatoly Burakov 						MIN_ZERO_POLL_COUNT)
1004e0194febSAnatoly Burakov 					continue;
1005e0194febSAnatoly Burakov 
1006e0194febSAnatoly Burakov 				rx_queue->idle_hint = power_idle_heuristic(
1007e0194febSAnatoly Burakov 						rx_queue->zero_rx_packet_count);
1008e0194febSAnatoly Burakov 				lcore_rx_idle_count++;
1009e0194febSAnatoly Burakov 			} else {
1010e0194febSAnatoly Burakov 				rx_queue->zero_rx_packet_count = 0;
1011e0194febSAnatoly Burakov 			}
1012e0194febSAnatoly Burakov 
1013e0194febSAnatoly Burakov 			/* Prefetch first packets */
1014e0194febSAnatoly Burakov 			for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
1015e0194febSAnatoly Burakov 				rte_prefetch0(rte_pktmbuf_mtod(
1016e0194febSAnatoly Burakov 						pkts_burst[j], void *));
1017e0194febSAnatoly Burakov 			}
1018e0194febSAnatoly Burakov 
1019e0194febSAnatoly Burakov 			/* Prefetch and forward already prefetched packets */
1020e0194febSAnatoly Burakov 			for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
1021e0194febSAnatoly Burakov 				rte_prefetch0(rte_pktmbuf_mtod(
1022e0194febSAnatoly Burakov 						pkts_burst[j + PREFETCH_OFFSET],
1023e0194febSAnatoly Burakov 						void *));
1024e0194febSAnatoly Burakov 				l3fwd_simple_forward(
1025e0194febSAnatoly Burakov 						pkts_burst[j], portid, qconf);
1026e0194febSAnatoly Burakov 			}
1027e0194febSAnatoly Burakov 
1028e0194febSAnatoly Burakov 			/* Forward remaining prefetched packets */
1029e0194febSAnatoly Burakov 			for (; j < nb_rx; j++) {
1030e0194febSAnatoly Burakov 				l3fwd_simple_forward(
1031e0194febSAnatoly Burakov 						pkts_burst[j], portid, qconf);
1032e0194febSAnatoly Burakov 			}
1033e0194febSAnatoly Burakov 		}
1034e0194febSAnatoly Burakov 
1035e0194febSAnatoly Burakov 		if (unlikely(lcore_rx_idle_count == qconf->n_rx_queue)) {
1036e0194febSAnatoly Burakov 			/**
1037e0194febSAnatoly Burakov 			 * All Rx queues empty in recent consecutive polls,
1038e0194febSAnatoly Burakov 			 * sleep in a conservative manner, meaning sleep as
1039e0194febSAnatoly Burakov 			 * less as possible.
1040e0194febSAnatoly Burakov 			 */
1041e0194febSAnatoly Burakov 			for (i = 1,
1042e0194febSAnatoly Burakov 			    lcore_idle_hint = qconf->rx_queue_list[0].idle_hint;
1043e0194febSAnatoly Burakov 					i < qconf->n_rx_queue; ++i) {
1044e0194febSAnatoly Burakov 				rx_queue = &(qconf->rx_queue_list[i]);
1045e0194febSAnatoly Burakov 				if (rx_queue->idle_hint < lcore_idle_hint)
1046e0194febSAnatoly Burakov 					lcore_idle_hint = rx_queue->idle_hint;
1047e0194febSAnatoly Burakov 			}
1048e0194febSAnatoly Burakov 
1049e0194febSAnatoly Burakov 			if (lcore_idle_hint < SUSPEND_THRESHOLD)
1050e0194febSAnatoly Burakov 				/**
1051e0194febSAnatoly Burakov 				 * execute "pause" instruction to avoid context
1052e0194febSAnatoly Burakov 				 * switch which generally take hundred of
1053e0194febSAnatoly Burakov 				 * microseconds for short sleep.
1054e0194febSAnatoly Burakov 				 */
1055e0194febSAnatoly Burakov 				rte_delay_us(lcore_idle_hint);
1056e0194febSAnatoly Burakov 			else {
1057e0194febSAnatoly Burakov 				/* suspend until rx interrupt triggers */
1058e0194febSAnatoly Burakov 				if (intr_en) {
1059e0194febSAnatoly Burakov 					turn_on_off_intr(qconf, 1);
1060e0194febSAnatoly Burakov 					sleep_until_rx_interrupt(
1061317a1da8SAnatoly Burakov 							qconf->n_rx_queue,
1062317a1da8SAnatoly Burakov 							lcore_id);
1063e0194febSAnatoly Burakov 					turn_on_off_intr(qconf, 0);
1064e0194febSAnatoly Burakov 					/**
1065e0194febSAnatoly Burakov 					 * start receiving packets immediately
1066e0194febSAnatoly Burakov 					 */
1067e0194febSAnatoly Burakov 					if (likely(!is_done()))
1068e0194febSAnatoly Burakov 						goto start_rx;
1069e0194febSAnatoly Burakov 				}
1070e0194febSAnatoly Burakov 			}
1071e0194febSAnatoly Burakov 			stats[lcore_id].sleep_time += lcore_idle_hint;
1072e0194febSAnatoly Burakov 		}
1073e0194febSAnatoly Burakov 	}
1074e0194febSAnatoly Burakov 
1075e0194febSAnatoly Burakov 	return 0;
1076e0194febSAnatoly Burakov }
10779a212dc0SConor Fogarty /* >8 End of main processing loop. */
1078e0194febSAnatoly Burakov 
1079a137d012SLiang Ma /* main processing loop */
1080a137d012SLiang Ma static int
1081f2fc83b4SThomas Monjalon main_telemetry_loop(__rte_unused void *dummy)
1082609e7984SReshma Pattan {
1083609e7984SReshma Pattan 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1084609e7984SReshma Pattan 	unsigned int lcore_id;
1085609e7984SReshma Pattan 	uint64_t prev_tsc, diff_tsc, cur_tsc, prev_tel_tsc;
1086609e7984SReshma Pattan 	int i, j, nb_rx;
1087b23c5bd7SSivaprasad Tummala 	uint16_t portid, queueid;
1088609e7984SReshma Pattan 	struct lcore_conf *qconf;
1089609e7984SReshma Pattan 	struct lcore_rx_queue *rx_queue;
1090609e7984SReshma Pattan 	uint64_t ep_nep[2] = {0}, fp_nfp[2] = {0};
1091609e7984SReshma Pattan 	uint64_t poll_count;
1092609e7984SReshma Pattan 	enum busy_rate br;
1093609e7984SReshma Pattan 
1094609e7984SReshma Pattan 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
1095609e7984SReshma Pattan 					US_PER_S * BURST_TX_DRAIN_US;
1096609e7984SReshma Pattan 
1097609e7984SReshma Pattan 	poll_count = 0;
1098609e7984SReshma Pattan 	prev_tsc = 0;
1099609e7984SReshma Pattan 	prev_tel_tsc = 0;
1100609e7984SReshma Pattan 
1101609e7984SReshma Pattan 	lcore_id = rte_lcore_id();
1102609e7984SReshma Pattan 	qconf = &lcore_conf[lcore_id];
1103609e7984SReshma Pattan 
1104609e7984SReshma Pattan 	if (qconf->n_rx_queue == 0) {
1105609e7984SReshma Pattan 		RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n",
1106609e7984SReshma Pattan 			lcore_id);
1107609e7984SReshma Pattan 		return 0;
1108609e7984SReshma Pattan 	}
1109609e7984SReshma Pattan 
1110609e7984SReshma Pattan 	RTE_LOG(INFO, L3FWD_POWER, "entering main telemetry loop on lcore %u\n",
1111609e7984SReshma Pattan 		lcore_id);
1112609e7984SReshma Pattan 
1113609e7984SReshma Pattan 	for (i = 0; i < qconf->n_rx_queue; i++) {
1114609e7984SReshma Pattan 		portid = qconf->rx_queue_list[i].port_id;
1115609e7984SReshma Pattan 		queueid = qconf->rx_queue_list[i].queue_id;
1116609e7984SReshma Pattan 		RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u "
1117b23c5bd7SSivaprasad Tummala 			"rxqueueid=%" PRIu16 "\n", lcore_id, portid, queueid);
1118609e7984SReshma Pattan 	}
1119609e7984SReshma Pattan 
1120609e7984SReshma Pattan 	while (!is_done()) {
1121609e7984SReshma Pattan 
1122609e7984SReshma Pattan 		cur_tsc = rte_rdtsc();
1123609e7984SReshma Pattan 		/*
1124609e7984SReshma Pattan 		 * TX burst queue drain
1125609e7984SReshma Pattan 		 */
1126609e7984SReshma Pattan 		diff_tsc = cur_tsc - prev_tsc;
1127609e7984SReshma Pattan 		if (unlikely(diff_tsc > drain_tsc)) {
1128609e7984SReshma Pattan 			for (i = 0; i < qconf->n_tx_port; ++i) {
1129609e7984SReshma Pattan 				portid = qconf->tx_port_id[i];
1130609e7984SReshma Pattan 				rte_eth_tx_buffer_flush(portid,
1131609e7984SReshma Pattan 						qconf->tx_queue_id[portid],
1132609e7984SReshma Pattan 						qconf->tx_buffer[portid]);
1133609e7984SReshma Pattan 			}
1134609e7984SReshma Pattan 			prev_tsc = cur_tsc;
1135609e7984SReshma Pattan 		}
1136609e7984SReshma Pattan 
1137609e7984SReshma Pattan 		/*
1138609e7984SReshma Pattan 		 * Read packet from RX queues
1139609e7984SReshma Pattan 		 */
1140609e7984SReshma Pattan 		for (i = 0; i < qconf->n_rx_queue; ++i) {
1141609e7984SReshma Pattan 			rx_queue = &(qconf->rx_queue_list[i]);
1142609e7984SReshma Pattan 			portid = rx_queue->port_id;
1143609e7984SReshma Pattan 			queueid = rx_queue->queue_id;
1144609e7984SReshma Pattan 
1145609e7984SReshma Pattan 			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
1146609e7984SReshma Pattan 								MAX_PKT_BURST);
1147609e7984SReshma Pattan 			ep_nep[nb_rx == 0]++;
1148609e7984SReshma Pattan 			fp_nfp[nb_rx == MAX_PKT_BURST]++;
1149609e7984SReshma Pattan 			poll_count++;
1150609e7984SReshma Pattan 			if (unlikely(nb_rx == 0))
1151609e7984SReshma Pattan 				continue;
1152609e7984SReshma Pattan 
1153609e7984SReshma Pattan 			/* Prefetch first packets */
1154609e7984SReshma Pattan 			for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
1155609e7984SReshma Pattan 				rte_prefetch0(rte_pktmbuf_mtod(
1156609e7984SReshma Pattan 						pkts_burst[j], void *));
1157609e7984SReshma Pattan 			}
1158609e7984SReshma Pattan 
1159609e7984SReshma Pattan 			/* Prefetch and forward already prefetched packets */
1160609e7984SReshma Pattan 			for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
1161609e7984SReshma Pattan 				rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
1162609e7984SReshma Pattan 						j + PREFETCH_OFFSET], void *));
1163609e7984SReshma Pattan 				l3fwd_simple_forward(pkts_burst[j], portid,
1164609e7984SReshma Pattan 								qconf);
1165609e7984SReshma Pattan 			}
1166609e7984SReshma Pattan 
1167609e7984SReshma Pattan 			/* Forward remaining prefetched packets */
1168609e7984SReshma Pattan 			for (; j < nb_rx; j++) {
1169609e7984SReshma Pattan 				l3fwd_simple_forward(pkts_burst[j], portid,
1170609e7984SReshma Pattan 								qconf);
1171609e7984SReshma Pattan 			}
1172609e7984SReshma Pattan 		}
1173609e7984SReshma Pattan 		if (unlikely(poll_count >= DEFAULT_COUNT)) {
1174609e7984SReshma Pattan 			diff_tsc = cur_tsc - prev_tel_tsc;
1175609e7984SReshma Pattan 			if (diff_tsc >= MAX_CYCLES) {
1176609e7984SReshma Pattan 				br = FULL;
1177609e7984SReshma Pattan 			} else if (diff_tsc > MIN_CYCLES &&
1178609e7984SReshma Pattan 					diff_tsc < MAX_CYCLES) {
1179b55d8fecSDavid Hunt 				br = (diff_tsc * 100) / MAX_CYCLES;
1180609e7984SReshma Pattan 			} else {
1181609e7984SReshma Pattan 				br = ZERO;
1182609e7984SReshma Pattan 			}
1183609e7984SReshma Pattan 			poll_count = 0;
1184609e7984SReshma Pattan 			prev_tel_tsc = cur_tsc;
1185609e7984SReshma Pattan 			/* update stats for telemetry */
1186609e7984SReshma Pattan 			rte_spinlock_lock(&stats[lcore_id].telemetry_lock);
1187609e7984SReshma Pattan 			stats[lcore_id].ep_nep[0] = ep_nep[0];
1188609e7984SReshma Pattan 			stats[lcore_id].ep_nep[1] = ep_nep[1];
1189609e7984SReshma Pattan 			stats[lcore_id].fp_nfp[0] = fp_nfp[0];
1190609e7984SReshma Pattan 			stats[lcore_id].fp_nfp[1] = fp_nfp[1];
1191609e7984SReshma Pattan 			stats[lcore_id].br = br;
1192609e7984SReshma Pattan 			rte_spinlock_unlock(&stats[lcore_id].telemetry_lock);
1193609e7984SReshma Pattan 		}
1194609e7984SReshma Pattan 	}
1195609e7984SReshma Pattan 
1196609e7984SReshma Pattan 	return 0;
1197609e7984SReshma Pattan }
1198aee3bc79SCunming Liang 
1199d7937e2eSIntel /* main processing loop */
1200d7937e2eSIntel static int
12015b41ab35SAnatoly Burakov main_legacy_loop(__rte_unused void *dummy)
1202d7937e2eSIntel {
1203d7937e2eSIntel 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
1204d7937e2eSIntel 	unsigned lcore_id;
120563de7e6eSNikhil Agarwal 	uint64_t prev_tsc, diff_tsc, cur_tsc, tim_res_tsc, hz;
1206d7937e2eSIntel 	uint64_t prev_tsc_power = 0, cur_tsc_power, diff_tsc_power;
1207d7937e2eSIntel 	int i, j, nb_rx;
1208b23c5bd7SSivaprasad Tummala 	uint16_t portid, queueid;
1209d7937e2eSIntel 	struct lcore_conf *qconf;
1210d7937e2eSIntel 	struct lcore_rx_queue *rx_queue;
1211d7937e2eSIntel 	enum freq_scale_hint_t lcore_scaleup_hint;
1212d7937e2eSIntel 	uint32_t lcore_rx_idle_count = 0;
1213d7937e2eSIntel 	uint32_t lcore_idle_hint = 0;
1214aee3bc79SCunming Liang 	int intr_en = 0;
1215d7937e2eSIntel 
1216d7937e2eSIntel 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
1217d7937e2eSIntel 
1218d7937e2eSIntel 	prev_tsc = 0;
121963de7e6eSNikhil Agarwal 	hz = rte_get_timer_hz();
122063de7e6eSNikhil Agarwal 	tim_res_tsc = hz/TIMER_NUMBER_PER_SECOND;
1221d7937e2eSIntel 
1222d7937e2eSIntel 	lcore_id = rte_lcore_id();
1223d7937e2eSIntel 	qconf = &lcore_conf[lcore_id];
1224d7937e2eSIntel 
1225d7937e2eSIntel 	if (qconf->n_rx_queue == 0) {
1226d7937e2eSIntel 		RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", lcore_id);
1227d7937e2eSIntel 		return 0;
1228d7937e2eSIntel 	}
1229d7937e2eSIntel 
1230d7937e2eSIntel 	RTE_LOG(INFO, L3FWD_POWER, "entering main loop on lcore %u\n", lcore_id);
1231d7937e2eSIntel 
1232d7937e2eSIntel 	for (i = 0; i < qconf->n_rx_queue; i++) {
1233d7937e2eSIntel 		portid = qconf->rx_queue_list[i].port_id;
1234d7937e2eSIntel 		queueid = qconf->rx_queue_list[i].queue_id;
1235f8244c63SZhiyong Yang 		RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u "
1236b23c5bd7SSivaprasad Tummala 			"rxqueueid=%" PRIu16 "\n", lcore_id, portid, queueid);
1237d7937e2eSIntel 	}
1238d7937e2eSIntel 
1239aee3bc79SCunming Liang 	/* add into event wait list */
1240aee3bc79SCunming Liang 	if (event_register(qconf) == 0)
1241aee3bc79SCunming Liang 		intr_en = 1;
1242aee3bc79SCunming Liang 	else
1243aee3bc79SCunming Liang 		RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n");
1244aee3bc79SCunming Liang 
1245613ce669SAnatoly Burakov 	while (!is_done()) {
1246d7937e2eSIntel 		stats[lcore_id].nb_iteration_looped++;
1247d7937e2eSIntel 
1248d7937e2eSIntel 		cur_tsc = rte_rdtsc();
1249d7937e2eSIntel 		cur_tsc_power = cur_tsc;
1250d7937e2eSIntel 
1251d7937e2eSIntel 		/*
1252d7937e2eSIntel 		 * TX burst queue drain
1253d7937e2eSIntel 		 */
1254d7937e2eSIntel 		diff_tsc = cur_tsc - prev_tsc;
1255d7937e2eSIntel 		if (unlikely(diff_tsc > drain_tsc)) {
1256e2366e74STomasz Kulasek 			for (i = 0; i < qconf->n_tx_port; ++i) {
1257e2366e74STomasz Kulasek 				portid = qconf->tx_port_id[i];
1258e2366e74STomasz Kulasek 				rte_eth_tx_buffer_flush(portid,
1259e2366e74STomasz Kulasek 						qconf->tx_queue_id[portid],
1260e2366e74STomasz Kulasek 						qconf->tx_buffer[portid]);
1261d7937e2eSIntel 			}
1262d7937e2eSIntel 			prev_tsc = cur_tsc;
1263d7937e2eSIntel 		}
1264d7937e2eSIntel 
1265d7937e2eSIntel 		diff_tsc_power = cur_tsc_power - prev_tsc_power;
126663de7e6eSNikhil Agarwal 		if (diff_tsc_power > tim_res_tsc) {
1267d7937e2eSIntel 			rte_timer_manage();
1268d7937e2eSIntel 			prev_tsc_power = cur_tsc_power;
1269d7937e2eSIntel 		}
1270d7937e2eSIntel 
1271aee3bc79SCunming Liang start_rx:
1272d7937e2eSIntel 		/*
1273d7937e2eSIntel 		 * Read packet from RX queues
1274d7937e2eSIntel 		 */
1275d7937e2eSIntel 		lcore_scaleup_hint = FREQ_CURRENT;
1276d7937e2eSIntel 		lcore_rx_idle_count = 0;
1277d7937e2eSIntel 		for (i = 0; i < qconf->n_rx_queue; ++i) {
1278d7937e2eSIntel 			rx_queue = &(qconf->rx_queue_list[i]);
1279d7937e2eSIntel 			rx_queue->idle_hint = 0;
1280d7937e2eSIntel 			portid = rx_queue->port_id;
1281d7937e2eSIntel 			queueid = rx_queue->queue_id;
1282d7937e2eSIntel 
1283d7937e2eSIntel 			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
1284d7937e2eSIntel 								MAX_PKT_BURST);
1285aee3bc79SCunming Liang 
1286d7937e2eSIntel 			stats[lcore_id].nb_rx_processed += nb_rx;
1287d7937e2eSIntel 			if (unlikely(nb_rx == 0)) {
1288d7937e2eSIntel 				/**
1289d7937e2eSIntel 				 * no packet received from rx queue, try to
1290d7937e2eSIntel 				 * sleep for a while forcing CPU enter deeper
1291d7937e2eSIntel 				 * C states.
1292d7937e2eSIntel 				 */
1293d7937e2eSIntel 				rx_queue->zero_rx_packet_count++;
1294d7937e2eSIntel 
1295d7937e2eSIntel 				if (rx_queue->zero_rx_packet_count <=
1296d7937e2eSIntel 							MIN_ZERO_POLL_COUNT)
1297d7937e2eSIntel 					continue;
1298d7937e2eSIntel 
1299d7937e2eSIntel 				rx_queue->idle_hint = power_idle_heuristic(\
1300d7937e2eSIntel 					rx_queue->zero_rx_packet_count);
1301d7937e2eSIntel 				lcore_rx_idle_count++;
1302d7937e2eSIntel 			} else {
1303d7937e2eSIntel 				rx_queue->zero_rx_packet_count = 0;
1304d7937e2eSIntel 
1305d7937e2eSIntel 				/**
1306d7937e2eSIntel 				 * do not scale up frequency immediately as
1307d7937e2eSIntel 				 * user to kernel space communication is costly
1308d7937e2eSIntel 				 * which might impact packet I/O for received
1309d7937e2eSIntel 				 * packets.
1310d7937e2eSIntel 				 */
1311d7937e2eSIntel 				rx_queue->freq_up_hint =
1312d7937e2eSIntel 					power_freq_scaleup_heuristic(lcore_id,
1313b451aa39SIntel 							portid, queueid);
1314d7937e2eSIntel 			}
1315d7937e2eSIntel 
1316d7937e2eSIntel 			/* Prefetch first packets */
1317d7937e2eSIntel 			for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
1318d7937e2eSIntel 				rte_prefetch0(rte_pktmbuf_mtod(
1319d7937e2eSIntel 						pkts_burst[j], void *));
1320d7937e2eSIntel 			}
1321d7937e2eSIntel 
1322d7937e2eSIntel 			/* Prefetch and forward already prefetched packets */
1323d7937e2eSIntel 			for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
1324d7937e2eSIntel 				rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
1325d7937e2eSIntel 						j + PREFETCH_OFFSET], void *));
1326d7937e2eSIntel 				l3fwd_simple_forward(pkts_burst[j], portid,
1327d7937e2eSIntel 								qconf);
1328d7937e2eSIntel 			}
1329d7937e2eSIntel 
1330d7937e2eSIntel 			/* Forward remaining prefetched packets */
1331d7937e2eSIntel 			for (; j < nb_rx; j++) {
1332d7937e2eSIntel 				l3fwd_simple_forward(pkts_burst[j], portid,
1333d7937e2eSIntel 								qconf);
1334d7937e2eSIntel 			}
1335d7937e2eSIntel 		}
1336d7937e2eSIntel 
1337d7937e2eSIntel 		if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) {
1338d7937e2eSIntel 			for (i = 1, lcore_scaleup_hint =
1339d7937e2eSIntel 				qconf->rx_queue_list[0].freq_up_hint;
1340d7937e2eSIntel 					i < qconf->n_rx_queue; ++i) {
1341d7937e2eSIntel 				rx_queue = &(qconf->rx_queue_list[i]);
1342d7937e2eSIntel 				if (rx_queue->freq_up_hint >
1343d7937e2eSIntel 						lcore_scaleup_hint)
1344d7937e2eSIntel 					lcore_scaleup_hint =
1345d7937e2eSIntel 						rx_queue->freq_up_hint;
1346d7937e2eSIntel 			}
1347d7937e2eSIntel 
1348aee3bc79SCunming Liang 			if (lcore_scaleup_hint == FREQ_HIGHEST) {
1349d7937e2eSIntel 				rte_power_freq_max(lcore_id);
1350aee3bc79SCunming Liang 			} else if (lcore_scaleup_hint == FREQ_HIGHER) {
1351d7937e2eSIntel 				rte_power_freq_up(lcore_id);
1352aee3bc79SCunming Liang 			}
1353d7937e2eSIntel 		} else {
1354d7937e2eSIntel 			/**
1355d7937e2eSIntel 			 * All Rx queues empty in recent consecutive polls,
1356d7937e2eSIntel 			 * sleep in a conservative manner, meaning sleep as
1357d7937e2eSIntel 			 * less as possible.
1358d7937e2eSIntel 			 */
1359d7937e2eSIntel 			for (i = 1, lcore_idle_hint =
1360d7937e2eSIntel 				qconf->rx_queue_list[0].idle_hint;
1361d7937e2eSIntel 					i < qconf->n_rx_queue; ++i) {
1362d7937e2eSIntel 				rx_queue = &(qconf->rx_queue_list[i]);
1363d7937e2eSIntel 				if (rx_queue->idle_hint < lcore_idle_hint)
1364d7937e2eSIntel 					lcore_idle_hint = rx_queue->idle_hint;
1365d7937e2eSIntel 			}
1366d7937e2eSIntel 
1367aee3bc79SCunming Liang 			if (lcore_idle_hint < SUSPEND_THRESHOLD)
1368d7937e2eSIntel 				/**
1369d7937e2eSIntel 				 * execute "pause" instruction to avoid context
1370aee3bc79SCunming Liang 				 * switch which generally take hundred of
1371aee3bc79SCunming Liang 				 * microseconds for short sleep.
1372d7937e2eSIntel 				 */
1373d7937e2eSIntel 				rte_delay_us(lcore_idle_hint);
1374aee3bc79SCunming Liang 			else {
1375dd22d317SXiao Wang 				/* suspend until rx interrupt triggers */
1376aee3bc79SCunming Liang 				if (intr_en) {
137749dcf7b9SXiao Wang 					turn_on_off_intr(qconf, 1);
1378aee3bc79SCunming Liang 					sleep_until_rx_interrupt(
1379317a1da8SAnatoly Burakov 							qconf->n_rx_queue,
1380317a1da8SAnatoly Burakov 							lcore_id);
138149dcf7b9SXiao Wang 					turn_on_off_intr(qconf, 0);
13824ffc0a88SNikhil Agarwal 					/**
13834ffc0a88SNikhil Agarwal 					 * start receiving packets immediately
13844ffc0a88SNikhil Agarwal 					 */
1385f4d1e19cSAnatoly Burakov 					if (likely(!is_done()))
1386aee3bc79SCunming Liang 						goto start_rx;
1387aee3bc79SCunming Liang 				}
13884ffc0a88SNikhil Agarwal 			}
1389d7937e2eSIntel 			stats[lcore_id].sleep_time += lcore_idle_hint;
1390d7937e2eSIntel 		}
1391d7937e2eSIntel 	}
1392613ce669SAnatoly Burakov 
1393613ce669SAnatoly Burakov 	return 0;
1394d7937e2eSIntel }
1395d7937e2eSIntel 
1396d7937e2eSIntel static int
1397d7937e2eSIntel check_lcore_params(void)
1398d7937e2eSIntel {
1399b23c5bd7SSivaprasad Tummala 	uint16_t queue, i;
14004b978938SSivaprasad Tummala 	uint32_t lcore;
1401d7937e2eSIntel 	int socketid;
1402d7937e2eSIntel 
1403d7937e2eSIntel 	for (i = 0; i < nb_lcore_params; ++i) {
1404d7937e2eSIntel 		queue = lcore_params[i].queue_id;
1405d7937e2eSIntel 		if (queue >= MAX_RX_QUEUE_PER_PORT) {
1406b23c5bd7SSivaprasad Tummala 			printf("invalid queue number: %" PRIu16 "\n", queue);
1407d7937e2eSIntel 			return -1;
1408d7937e2eSIntel 		}
1409d7937e2eSIntel 		lcore = lcore_params[i].lcore_id;
1410d7937e2eSIntel 		if (!rte_lcore_is_enabled(lcore)) {
14114b978938SSivaprasad Tummala 			printf("error: lcore %u is not enabled in lcore "
1412d7937e2eSIntel 							"mask\n", lcore);
1413d7937e2eSIntel 			return -1;
1414d7937e2eSIntel 		}
1415d7937e2eSIntel 		if ((socketid = rte_lcore_to_socket_id(lcore) != 0) &&
1416d7937e2eSIntel 							(numa_on == 0)) {
14174b978938SSivaprasad Tummala 			printf("warning: lcore %u is on socket %d with numa "
1418d7937e2eSIntel 						"off\n", lcore, socketid);
1419d7937e2eSIntel 		}
1420609e7984SReshma Pattan 		if (app_mode == APP_MODE_TELEMETRY && lcore == rte_lcore_id()) {
1421cb056611SStephen Hemminger 			printf("cannot enable main core %d in config for telemetry mode\n",
1422609e7984SReshma Pattan 				rte_lcore_id());
1423609e7984SReshma Pattan 			return -1;
1424609e7984SReshma Pattan 		}
1425d7937e2eSIntel 	}
1426d7937e2eSIntel 	return 0;
1427d7937e2eSIntel }
1428d7937e2eSIntel 
1429d7937e2eSIntel static int
1430a9dbe180SThomas Monjalon check_port_config(void)
1431d7937e2eSIntel {
1432d7937e2eSIntel 	unsigned portid;
1433d7937e2eSIntel 	uint16_t i;
1434d7937e2eSIntel 
1435d7937e2eSIntel 	for (i = 0; i < nb_lcore_params; ++i) {
1436d7937e2eSIntel 		portid = lcore_params[i].port_id;
1437d7937e2eSIntel 		if ((enabled_port_mask & (1 << portid)) == 0) {
1438d7937e2eSIntel 			printf("port %u is not enabled in port mask\n",
1439d7937e2eSIntel 								portid);
1440d7937e2eSIntel 			return -1;
1441d7937e2eSIntel 		}
1442a9dbe180SThomas Monjalon 		if (!rte_eth_dev_is_valid_port(portid)) {
1443d7937e2eSIntel 			printf("port %u is not present on the board\n",
1444d7937e2eSIntel 								portid);
1445d7937e2eSIntel 			return -1;
1446d7937e2eSIntel 		}
1447d7937e2eSIntel 	}
1448d7937e2eSIntel 	return 0;
1449d7937e2eSIntel }
1450d7937e2eSIntel 
1451b23c5bd7SSivaprasad Tummala static uint16_t
145247523597SZhiyong Yang get_port_n_rx_queues(const uint16_t port)
1453d7937e2eSIntel {
1454d7937e2eSIntel 	int queue = -1;
1455d7937e2eSIntel 	uint16_t i;
1456d7937e2eSIntel 
1457d7937e2eSIntel 	for (i = 0; i < nb_lcore_params; ++i) {
1458d7937e2eSIntel 		if (lcore_params[i].port_id == port &&
1459d7937e2eSIntel 				lcore_params[i].queue_id > queue)
1460d7937e2eSIntel 			queue = lcore_params[i].queue_id;
1461d7937e2eSIntel 	}
1462b23c5bd7SSivaprasad Tummala 	return (uint16_t)(++queue);
1463d7937e2eSIntel }
1464d7937e2eSIntel 
1465d7937e2eSIntel static int
1466d7937e2eSIntel init_lcore_rx_queues(void)
1467d7937e2eSIntel {
1468d7937e2eSIntel 	uint16_t i, nb_rx_queue;
14694b978938SSivaprasad Tummala 	uint32_t lcore;
1470d7937e2eSIntel 
1471d7937e2eSIntel 	for (i = 0; i < nb_lcore_params; ++i) {
1472d7937e2eSIntel 		lcore = lcore_params[i].lcore_id;
1473d7937e2eSIntel 		nb_rx_queue = lcore_conf[lcore].n_rx_queue;
1474d7937e2eSIntel 		if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) {
1475d7937e2eSIntel 			printf("error: too many queues (%u) for lcore: %u\n",
14764b978938SSivaprasad Tummala 				(unsigned int)nb_rx_queue + 1, lcore);
1477d7937e2eSIntel 			return -1;
1478d7937e2eSIntel 		} else {
1479d7937e2eSIntel 			lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id =
1480d7937e2eSIntel 				lcore_params[i].port_id;
1481d7937e2eSIntel 			lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id =
1482d7937e2eSIntel 				lcore_params[i].queue_id;
1483d7937e2eSIntel 			lcore_conf[lcore].n_rx_queue++;
1484d7937e2eSIntel 		}
1485d7937e2eSIntel 	}
1486d7937e2eSIntel 	return 0;
1487d7937e2eSIntel }
1488d7937e2eSIntel 
1489d7937e2eSIntel /* display usage */
1490d7937e2eSIntel static void
1491d7937e2eSIntel print_usage(const char *prgname)
1492d7937e2eSIntel {
1493d7937e2eSIntel 	printf ("%s [EAL options] -- -p PORTMASK -P"
1494d7937e2eSIntel 		"  [--config (port,queue,lcore)[,(port,queue,lcore]]"
1495f88e7c17SRadu Nicolau 		"  [--high-perf-cores CORELIST"
1496f88e7c17SRadu Nicolau 		"  [--perf-config (port,queue,hi_perf,lcore_index)[,(port,queue,hi_perf,lcore_index]]"
14971bb4a528SFerruh Yigit 		"  [--max-pkt-len PKTLEN]\n"
1498d7937e2eSIntel 		"  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
1499d7937e2eSIntel 		"  -P: enable promiscuous mode\n"
150010db2a5bSTadhg Kearney 		"  -u: set min/max frequency for uncore to minimum value\n"
150110db2a5bSTadhg Kearney 		"  -U: set min/max frequency for uncore to maximum value\n"
150210db2a5bSTadhg Kearney 		"  -i (frequency index): set min/max frequency for uncore to specified frequency index\n"
1503d7937e2eSIntel 		"  --config (port,queue,lcore): rx queues configuration\n"
15044d23d39fSHuisong Li 		"  --cpu-resume-latency LATENCY: set CPU resume latency to control C-state selection,"
15054d23d39fSHuisong Li 		" 0 : just allow to enter C0-state\n"
1506f88e7c17SRadu Nicolau 		"  --high-perf-cores CORELIST: list of high performance cores\n"
1507f88e7c17SRadu Nicolau 		"  --perf-config: similar as config, cores specified as indices"
1508f88e7c17SRadu Nicolau 		" for bins containing high or regular performance cores\n"
1509d7937e2eSIntel 		"  --no-numa: optional, disable numa awareness\n"
15101bb4a528SFerruh Yigit 		"  --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n"
1511a137d012SLiang Ma 		"  --parse-ptype: parse packet type by software\n"
15122a0e2e2dSAnatoly Burakov 		"  --legacy: use legacy interrupt-based scaling\n"
1513609e7984SReshma Pattan 		" --telemetry: enable telemetry mode, to update"
1514e0194febSAnatoly Burakov 		" empty polls, full polls, and core busyness to telemetry\n"
151526fe454eSLiang Ma 		" --interrupt-only: enable interrupt-only mode\n"
151626fe454eSLiang Ma 		" --pmd-mgmt MODE: enable PMD power management mode. "
151759f2853cSKevin Laatz 		"Currently supported modes: baseline, monitor, pause, scale\n"
151859f2853cSKevin Laatz 		"  --max-empty-polls MAX_EMPTY_POLLS: number of empty polls to"
151959f2853cSKevin Laatz 		" wait before entering sleep state\n"
152059f2853cSKevin Laatz 		"  --pause-duration DURATION: set the duration, in microseconds,"
152159f2853cSKevin Laatz 		" of the pause callback\n"
152259f2853cSKevin Laatz 		"  --scale-freq-min FREQ_MIN: set minimum frequency for scaling mode for"
152359f2853cSKevin Laatz 		" all application lcores (FREQ_MIN must be in kHz, in increments of 100MHz)\n"
152459f2853cSKevin Laatz 		"  --scale-freq-max FREQ_MAX: set maximum frequency for scaling mode for"
152559f2853cSKevin Laatz 		" all application lcores (FREQ_MAX must be in kHz, in increments of 100MHz)\n",
1526d7937e2eSIntel 		prgname);
1527d7937e2eSIntel }
1528d7937e2eSIntel 
15290bc4795dSHuisong Li /*
15300bc4795dSHuisong Li  * Caller must give the right upper limit so as to ensure receiver variable
15310bc4795dSHuisong Li  * doesn't overflow.
15320bc4795dSHuisong Li  */
153359f2853cSKevin Laatz static int
15340bc4795dSHuisong Li parse_uint(const char *opt, uint32_t max, uint32_t *res)
153559f2853cSKevin Laatz {
153659f2853cSKevin Laatz 	char *end = NULL;
153759f2853cSKevin Laatz 	unsigned long val;
153859f2853cSKevin Laatz 
153959f2853cSKevin Laatz 	/* parse integer string */
154059f2853cSKevin Laatz 	val = strtoul(opt, &end, 10);
154159f2853cSKevin Laatz 	if ((opt[0] == '\0') || (end == NULL) || (*end != '\0'))
154259f2853cSKevin Laatz 		return -1;
154359f2853cSKevin Laatz 
15440bc4795dSHuisong Li 	if (val > max) {
15450bc4795dSHuisong Li 		RTE_LOG(ERR, L3FWD_POWER, "%s parameter shouldn't exceed %u.\n",
15460bc4795dSHuisong Li 			opt, max);
15470bc4795dSHuisong Li 		return -1;
154859f2853cSKevin Laatz 	}
154959f2853cSKevin Laatz 
15500bc4795dSHuisong Li 	*res = val;
1551d7937e2eSIntel 
15520bc4795dSHuisong Li 	return 0;
1553d7937e2eSIntel }
1554d7937e2eSIntel 
1555d7937e2eSIntel static int
155610db2a5bSTadhg Kearney parse_uncore_options(enum uncore_choice choice, const char *argument)
155710db2a5bSTadhg Kearney {
155810db2a5bSTadhg Kearney 	unsigned int die, pkg, max_pkg, max_die;
155910db2a5bSTadhg Kearney 	int ret = 0;
15603b3af56dSSivaprasad Tummala 	ret = rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_AUTO_DETECT);
15613b3af56dSSivaprasad Tummala 	if (ret < 0) {
15623b3af56dSSivaprasad Tummala 		RTE_LOG(INFO, L3FWD_POWER, "Failed to set uncore env\n");
15633b3af56dSSivaprasad Tummala 		return ret;
15643b3af56dSSivaprasad Tummala 	}
15653b3af56dSSivaprasad Tummala 
156610db2a5bSTadhg Kearney 	max_pkg = rte_power_uncore_get_num_pkgs();
156710db2a5bSTadhg Kearney 	if (max_pkg == 0)
156810db2a5bSTadhg Kearney 		return -1;
156910db2a5bSTadhg Kearney 
157010db2a5bSTadhg Kearney 	for (pkg = 0; pkg < max_pkg; pkg++) {
157110db2a5bSTadhg Kearney 		max_die = rte_power_uncore_get_num_dies(pkg);
157210db2a5bSTadhg Kearney 		if (max_die == 0)
157310db2a5bSTadhg Kearney 			return -1;
157410db2a5bSTadhg Kearney 		for (die = 0; die < max_die; die++) {
157510db2a5bSTadhg Kearney 			ret = rte_power_uncore_init(pkg, die);
157610db2a5bSTadhg Kearney 			if (ret == -1) {
157710db2a5bSTadhg Kearney 				RTE_LOG(INFO, L3FWD_POWER, "Unable to initialize uncore for pkg %02u die %02u\n"
157810db2a5bSTadhg Kearney 				, pkg, die);
157910db2a5bSTadhg Kearney 				return ret;
158010db2a5bSTadhg Kearney 			}
158110db2a5bSTadhg Kearney 			if (choice == UNCORE_MIN) {
158210db2a5bSTadhg Kearney 				ret = rte_power_uncore_freq_min(pkg, die);
158310db2a5bSTadhg Kearney 				if (ret == -1) {
158410db2a5bSTadhg Kearney 					RTE_LOG(INFO, L3FWD_POWER,
158510db2a5bSTadhg Kearney 					"Unable to set the uncore min/max to minimum uncore frequency value for pkg %02u die %02u\n"
158610db2a5bSTadhg Kearney 					, pkg, die);
158710db2a5bSTadhg Kearney 					return ret;
158810db2a5bSTadhg Kearney 				}
158910db2a5bSTadhg Kearney 			} else if (choice == UNCORE_MAX) {
159010db2a5bSTadhg Kearney 				ret = rte_power_uncore_freq_max(pkg, die);
159110db2a5bSTadhg Kearney 				if (ret == -1) {
159210db2a5bSTadhg Kearney 					RTE_LOG(INFO, L3FWD_POWER,
159310db2a5bSTadhg Kearney 					"Unable to set uncore min/max to maximum uncore frequency value for pkg %02u die %02u\n"
159410db2a5bSTadhg Kearney 					, pkg, die);
159510db2a5bSTadhg Kearney 					return ret;
159610db2a5bSTadhg Kearney 				}
159710db2a5bSTadhg Kearney 			} else if (choice == UNCORE_IDX) {
159810db2a5bSTadhg Kearney 				char *ptr = NULL;
159910db2a5bSTadhg Kearney 				int frequency_index = strtol(argument, &ptr, 10);
160010db2a5bSTadhg Kearney 				if (argument == ptr) {
160110db2a5bSTadhg Kearney 					RTE_LOG(INFO, L3FWD_POWER, "Index given is not a valid number.");
160210db2a5bSTadhg Kearney 					return -1;
160310db2a5bSTadhg Kearney 				}
160410db2a5bSTadhg Kearney 				int freq_array_len = rte_power_uncore_get_num_freqs(pkg, die);
160510db2a5bSTadhg Kearney 				if (frequency_index > freq_array_len - 1) {
160610db2a5bSTadhg Kearney 					RTE_LOG(INFO, L3FWD_POWER,
160710db2a5bSTadhg Kearney 					"Frequency index given out of range, please choose a value from 0 to %d.\n",
160810db2a5bSTadhg Kearney 					freq_array_len);
160910db2a5bSTadhg Kearney 					return -1;
161010db2a5bSTadhg Kearney 				}
161110db2a5bSTadhg Kearney 				ret = rte_power_set_uncore_freq(pkg, die, frequency_index);
161210db2a5bSTadhg Kearney 				if (ret == -1) {
161310db2a5bSTadhg Kearney 					RTE_LOG(INFO, L3FWD_POWER,
161410db2a5bSTadhg Kearney 					"Unable to set min/max uncore index value for pkg %02u die %02u\n",
161510db2a5bSTadhg Kearney 					pkg, die);
161610db2a5bSTadhg Kearney 					return ret;
161710db2a5bSTadhg Kearney 				}
161810db2a5bSTadhg Kearney 			} else {
161910db2a5bSTadhg Kearney 				RTE_LOG(INFO, L3FWD_POWER, "Uncore choice provided invalid\n");
162010db2a5bSTadhg Kearney 				return -1;
162110db2a5bSTadhg Kearney 			}
162210db2a5bSTadhg Kearney 		}
162310db2a5bSTadhg Kearney 	}
162410db2a5bSTadhg Kearney 
162510db2a5bSTadhg Kearney 	RTE_LOG(INFO, L3FWD_POWER, "Successfully set max/min/index uncore frequency.\n");
162610db2a5bSTadhg Kearney 	return ret;
162710db2a5bSTadhg Kearney }
162810db2a5bSTadhg Kearney 
162910db2a5bSTadhg Kearney static int
1630d7937e2eSIntel parse_portmask(const char *portmask)
1631d7937e2eSIntel {
1632d7937e2eSIntel 	char *end = NULL;
1633d7937e2eSIntel 	unsigned long pm;
1634d7937e2eSIntel 
1635d7937e2eSIntel 	/* parse hexadecimal string */
1636d7937e2eSIntel 	pm = strtoul(portmask, &end, 16);
1637d7937e2eSIntel 	if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
1638ce6b8c31SSarosh Arif 		return 0;
1639d7937e2eSIntel 
1640d7937e2eSIntel 	return pm;
1641d7937e2eSIntel }
1642d7937e2eSIntel 
1643d7937e2eSIntel static int
1644d7937e2eSIntel parse_config(const char *q_arg)
1645d7937e2eSIntel {
1646d7937e2eSIntel 	char s[256];
1647d7937e2eSIntel 	const char *p, *p0 = q_arg;
1648d7937e2eSIntel 	char *end;
1649d7937e2eSIntel 	enum fieldnames {
1650d7937e2eSIntel 		FLD_PORT = 0,
1651d7937e2eSIntel 		FLD_QUEUE,
1652d7937e2eSIntel 		FLD_LCORE,
1653d7937e2eSIntel 		_NUM_FLD
1654d7937e2eSIntel 	};
1655d7937e2eSIntel 	unsigned long int_fld[_NUM_FLD];
1656d7937e2eSIntel 	char *str_fld[_NUM_FLD];
1657d7937e2eSIntel 	int i;
1658d7937e2eSIntel 	unsigned size;
16594b978938SSivaprasad Tummala 	unsigned int max_fld[_NUM_FLD] = {
1660548de909SSivaprasad Tummala 		RTE_MAX_ETHPORTS,
16614b978938SSivaprasad Tummala 		RTE_MAX_QUEUES_PER_PORT,
16624b978938SSivaprasad Tummala 		RTE_MAX_LCORE
16634b978938SSivaprasad Tummala 	};
1664d7937e2eSIntel 
1665d7937e2eSIntel 	nb_lcore_params = 0;
1666d7937e2eSIntel 
1667d7937e2eSIntel 	while ((p = strchr(p0,'(')) != NULL) {
1668d7937e2eSIntel 		++p;
1669d7937e2eSIntel 		if((p0 = strchr(p,')')) == NULL)
1670d7937e2eSIntel 			return -1;
1671d7937e2eSIntel 
1672d7937e2eSIntel 		size = p0 - p;
1673d7937e2eSIntel 		if(size >= sizeof(s))
1674d7937e2eSIntel 			return -1;
1675d7937e2eSIntel 
16766f41fe75SStephen Hemminger 		snprintf(s, sizeof(s), "%.*s", size, p);
1677d7937e2eSIntel 		if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') !=
1678d7937e2eSIntel 								_NUM_FLD)
1679d7937e2eSIntel 			return -1;
1680d7937e2eSIntel 		for (i = 0; i < _NUM_FLD; i++){
1681d7937e2eSIntel 			errno = 0;
1682d7937e2eSIntel 			int_fld[i] = strtoul(str_fld[i], &end, 0);
1683b23c5bd7SSivaprasad Tummala 			if (errno != 0 || end == str_fld[i] || int_fld[i] > max_fld[i])
1684d7937e2eSIntel 				return -1;
1685d7937e2eSIntel 		}
1686d7937e2eSIntel 		if (nb_lcore_params >= MAX_LCORE_PARAMS) {
1687d7937e2eSIntel 			printf("exceeded max number of lcore params: %hu\n",
1688d7937e2eSIntel 				nb_lcore_params);
1689d7937e2eSIntel 			return -1;
1690d7937e2eSIntel 		}
1691d7937e2eSIntel 		lcore_params_array[nb_lcore_params].port_id =
1692548de909SSivaprasad Tummala 				(uint16_t)int_fld[FLD_PORT];
1693d7937e2eSIntel 		lcore_params_array[nb_lcore_params].queue_id =
1694b23c5bd7SSivaprasad Tummala 				(uint16_t)int_fld[FLD_QUEUE];
1695d7937e2eSIntel 		lcore_params_array[nb_lcore_params].lcore_id =
16964b978938SSivaprasad Tummala 				(uint32_t)int_fld[FLD_LCORE];
1697d7937e2eSIntel 		++nb_lcore_params;
1698d7937e2eSIntel 	}
1699d7937e2eSIntel 	lcore_params = lcore_params_array;
1700d7937e2eSIntel 
1701d7937e2eSIntel 	return 0;
1702d7937e2eSIntel }
170326fe454eSLiang Ma 
170426fe454eSLiang Ma static int
170526fe454eSLiang Ma parse_pmd_mgmt_config(const char *name)
170626fe454eSLiang Ma {
170726fe454eSLiang Ma #define PMD_MGMT_MONITOR "monitor"
170826fe454eSLiang Ma #define PMD_MGMT_PAUSE   "pause"
170926fe454eSLiang Ma #define PMD_MGMT_SCALE   "scale"
1710a9ea6070SDavid Hunt #define PMD_MGMT_BASELINE  "baseline"
171126fe454eSLiang Ma 
171226fe454eSLiang Ma 	if (strncmp(PMD_MGMT_MONITOR, name, sizeof(PMD_MGMT_MONITOR)) == 0) {
171326fe454eSLiang Ma 		pmgmt_type = RTE_POWER_MGMT_TYPE_MONITOR;
171426fe454eSLiang Ma 		return 0;
171526fe454eSLiang Ma 	}
171626fe454eSLiang Ma 
171726fe454eSLiang Ma 	if (strncmp(PMD_MGMT_PAUSE, name, sizeof(PMD_MGMT_PAUSE)) == 0) {
171826fe454eSLiang Ma 		pmgmt_type = RTE_POWER_MGMT_TYPE_PAUSE;
171926fe454eSLiang Ma 		return 0;
172026fe454eSLiang Ma 	}
172126fe454eSLiang Ma 
172226fe454eSLiang Ma 	if (strncmp(PMD_MGMT_SCALE, name, sizeof(PMD_MGMT_SCALE)) == 0) {
172326fe454eSLiang Ma 		pmgmt_type = RTE_POWER_MGMT_TYPE_SCALE;
172426fe454eSLiang Ma 		return 0;
172526fe454eSLiang Ma 	}
1726a9ea6070SDavid Hunt 	if (strncmp(PMD_MGMT_BASELINE, name, sizeof(PMD_MGMT_BASELINE)) == 0) {
1727a9ea6070SDavid Hunt 		baseline_enabled = true;
1728a9ea6070SDavid Hunt 		return 0;
1729a9ea6070SDavid Hunt 	}
173026fe454eSLiang Ma 	/* unknown PMD power management mode */
173126fe454eSLiang Ma 	return -1;
173226fe454eSLiang Ma }
173326fe454eSLiang Ma 
173482bea466SJianfeng Tan #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"
17352a0e2e2dSAnatoly Burakov #define CMD_LINE_OPT_LEGACY "legacy"
1736e0194febSAnatoly Burakov #define CMD_LINE_OPT_INTERRUPT_ONLY "interrupt-only"
1737609e7984SReshma Pattan #define CMD_LINE_OPT_TELEMETRY "telemetry"
173826fe454eSLiang Ma #define CMD_LINE_OPT_PMD_MGMT "pmd-mgmt"
17391bb4a528SFerruh Yigit #define CMD_LINE_OPT_MAX_PKT_LEN "max-pkt-len"
174059f2853cSKevin Laatz #define CMD_LINE_OPT_MAX_EMPTY_POLLS "max-empty-polls"
174159f2853cSKevin Laatz #define CMD_LINE_OPT_PAUSE_DURATION "pause-duration"
174259f2853cSKevin Laatz #define CMD_LINE_OPT_SCALE_FREQ_MIN "scale-freq-min"
174359f2853cSKevin Laatz #define CMD_LINE_OPT_SCALE_FREQ_MAX "scale-freq-max"
17444d23d39fSHuisong Li #define CMD_LINE_OPT_CPU_RESUME_LATENCY "cpu-resume-latency"
174582bea466SJianfeng Tan 
1746d7937e2eSIntel /* Parse the argument given in the command line of the application */
1747d7937e2eSIntel static int
1748d7937e2eSIntel parse_args(int argc, char **argv)
1749d7937e2eSIntel {
1750d7937e2eSIntel 	int opt, ret;
1751d7937e2eSIntel 	char **argvopt;
1752d7937e2eSIntel 	int option_index;
1753d7937e2eSIntel 	char *prgname = argv[0];
1754d7937e2eSIntel 	static struct option lgopts[] = {
1755d7937e2eSIntel 		{"config", 1, 0, 0},
1756f88e7c17SRadu Nicolau 		{"perf-config", 1, 0, 0},
1757f88e7c17SRadu Nicolau 		{"high-perf-cores", 1, 0, 0},
1758d7937e2eSIntel 		{"no-numa", 0, 0, 0},
17594d23d39fSHuisong Li 		{CMD_LINE_OPT_CPU_RESUME_LATENCY, 1, 0, 0},
17601bb4a528SFerruh Yigit 		{CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, 0},
176182bea466SJianfeng Tan 		{CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0},
17622a0e2e2dSAnatoly Burakov 		{CMD_LINE_OPT_LEGACY, 0, 0, 0},
1763609e7984SReshma Pattan 		{CMD_LINE_OPT_TELEMETRY, 0, 0, 0},
1764e0194febSAnatoly Burakov 		{CMD_LINE_OPT_INTERRUPT_ONLY, 0, 0, 0},
176526fe454eSLiang Ma 		{CMD_LINE_OPT_PMD_MGMT, 1, 0, 0},
176659f2853cSKevin Laatz 		{CMD_LINE_OPT_MAX_EMPTY_POLLS, 1, 0, 0},
176759f2853cSKevin Laatz 		{CMD_LINE_OPT_PAUSE_DURATION, 1, 0, 0},
176859f2853cSKevin Laatz 		{CMD_LINE_OPT_SCALE_FREQ_MIN, 1, 0, 0},
176959f2853cSKevin Laatz 		{CMD_LINE_OPT_SCALE_FREQ_MAX, 1, 0, 0},
1770d7937e2eSIntel 		{NULL, 0, 0, 0}
1771d7937e2eSIntel 	};
1772d7937e2eSIntel 
1773d7937e2eSIntel 	argvopt = argv;
1774d7937e2eSIntel 
17759c75ff42SDavid Hunt 	while ((opt = getopt_long(argc, argvopt, "p:PuUi:",
1776d7937e2eSIntel 				lgopts, &option_index)) != EOF) {
1777d7937e2eSIntel 
1778d7937e2eSIntel 		switch (opt) {
1779d7937e2eSIntel 		/* portmask */
1780d7937e2eSIntel 		case 'p':
1781d7937e2eSIntel 			enabled_port_mask = parse_portmask(optarg);
1782d7937e2eSIntel 			if (enabled_port_mask == 0) {
1783d7937e2eSIntel 				printf("invalid portmask\n");
1784d7937e2eSIntel 				print_usage(prgname);
1785d7937e2eSIntel 				return -1;
1786d7937e2eSIntel 			}
1787d7937e2eSIntel 			break;
1788d7937e2eSIntel 		case 'P':
1789d7937e2eSIntel 			printf("Promiscuous mode selected\n");
1790d7937e2eSIntel 			promiscuous_on = 1;
1791d7937e2eSIntel 			break;
179210db2a5bSTadhg Kearney 		case 'u':
179310db2a5bSTadhg Kearney 			enabled_uncore = parse_uncore_options(UNCORE_MIN, NULL);
179410db2a5bSTadhg Kearney 			if (enabled_uncore < 0) {
179510db2a5bSTadhg Kearney 				print_usage(prgname);
179610db2a5bSTadhg Kearney 				return -1;
179710db2a5bSTadhg Kearney 			}
179810db2a5bSTadhg Kearney 			break;
179910db2a5bSTadhg Kearney 		case 'U':
180010db2a5bSTadhg Kearney 			enabled_uncore = parse_uncore_options(UNCORE_MAX, NULL);
180110db2a5bSTadhg Kearney 			if (enabled_uncore < 0) {
180210db2a5bSTadhg Kearney 				print_usage(prgname);
180310db2a5bSTadhg Kearney 				return -1;
180410db2a5bSTadhg Kearney 			}
180510db2a5bSTadhg Kearney 			break;
180610db2a5bSTadhg Kearney 		case 'i':
180710db2a5bSTadhg Kearney 			enabled_uncore = parse_uncore_options(UNCORE_IDX, optarg);
180810db2a5bSTadhg Kearney 			if (enabled_uncore < 0) {
180910db2a5bSTadhg Kearney 				print_usage(prgname);
181010db2a5bSTadhg Kearney 				return -1;
181110db2a5bSTadhg Kearney 			}
181210db2a5bSTadhg Kearney 			break;
1813d7937e2eSIntel 		/* long options */
1814d7937e2eSIntel 		case 0:
1815d7937e2eSIntel 			if (!strncmp(lgopts[option_index].name, "config", 6)) {
1816d7937e2eSIntel 				ret = parse_config(optarg);
1817d7937e2eSIntel 				if (ret) {
1818d7937e2eSIntel 					printf("invalid config\n");
1819d7937e2eSIntel 					print_usage(prgname);
1820d7937e2eSIntel 					return -1;
1821d7937e2eSIntel 				}
1822d7937e2eSIntel 			}
1823d7937e2eSIntel 
1824d7937e2eSIntel 			if (!strncmp(lgopts[option_index].name,
1825f88e7c17SRadu Nicolau 					"perf-config", 11)) {
1826f88e7c17SRadu Nicolau 				ret = parse_perf_config(optarg);
1827f88e7c17SRadu Nicolau 				if (ret) {
1828f88e7c17SRadu Nicolau 					printf("invalid perf-config\n");
1829f88e7c17SRadu Nicolau 					print_usage(prgname);
1830f88e7c17SRadu Nicolau 					return -1;
1831f88e7c17SRadu Nicolau 				}
1832f88e7c17SRadu Nicolau 			}
1833f88e7c17SRadu Nicolau 
1834f88e7c17SRadu Nicolau 			if (!strncmp(lgopts[option_index].name,
1835f88e7c17SRadu Nicolau 					"high-perf-cores", 15)) {
1836f88e7c17SRadu Nicolau 				ret = parse_perf_core_list(optarg);
1837f88e7c17SRadu Nicolau 				if (ret) {
1838f88e7c17SRadu Nicolau 					printf("invalid high-perf-cores\n");
1839f88e7c17SRadu Nicolau 					print_usage(prgname);
1840f88e7c17SRadu Nicolau 					return -1;
1841f88e7c17SRadu Nicolau 				}
1842f88e7c17SRadu Nicolau 			}
1843f88e7c17SRadu Nicolau 
1844f88e7c17SRadu Nicolau 			if (!strncmp(lgopts[option_index].name,
1845d7937e2eSIntel 						"no-numa", 7)) {
1846d7937e2eSIntel 				printf("numa is disabled \n");
1847d7937e2eSIntel 				numa_on = 0;
1848d7937e2eSIntel 			}
1849d7937e2eSIntel 
1850d7937e2eSIntel 			if (!strncmp(lgopts[option_index].name,
18512a0e2e2dSAnatoly Burakov 					CMD_LINE_OPT_LEGACY,
18522a0e2e2dSAnatoly Burakov 					sizeof(CMD_LINE_OPT_LEGACY))) {
18532a0e2e2dSAnatoly Burakov 				if (app_mode != APP_MODE_DEFAULT) {
18542a0e2e2dSAnatoly Burakov 					printf(" legacy mode is mutually exclusive with other modes\n");
18552a0e2e2dSAnatoly Burakov 					return -1;
18562a0e2e2dSAnatoly Burakov 				}
18572a0e2e2dSAnatoly Burakov 				app_mode = APP_MODE_LEGACY;
18582a0e2e2dSAnatoly Burakov 				printf("legacy mode is enabled\n");
18592a0e2e2dSAnatoly Burakov 			}
18602a0e2e2dSAnatoly Burakov 
18612a0e2e2dSAnatoly Burakov 			if (!strncmp(lgopts[option_index].name,
1862609e7984SReshma Pattan 					CMD_LINE_OPT_TELEMETRY,
1863609e7984SReshma Pattan 					sizeof(CMD_LINE_OPT_TELEMETRY))) {
18642a0e2e2dSAnatoly Burakov 				if (app_mode != APP_MODE_DEFAULT) {
18652a0e2e2dSAnatoly Burakov 					printf(" telemetry mode is mutually exclusive with other modes\n");
1866609e7984SReshma Pattan 					return -1;
1867609e7984SReshma Pattan 				}
1868609e7984SReshma Pattan 				app_mode = APP_MODE_TELEMETRY;
1869609e7984SReshma Pattan 				printf("telemetry mode is enabled\n");
1870a137d012SLiang Ma 			}
1871a137d012SLiang Ma 
1872a137d012SLiang Ma 			if (!strncmp(lgopts[option_index].name,
187326fe454eSLiang Ma 					CMD_LINE_OPT_PMD_MGMT,
187426fe454eSLiang Ma 					sizeof(CMD_LINE_OPT_PMD_MGMT))) {
187526fe454eSLiang Ma 				if (app_mode != APP_MODE_DEFAULT) {
187626fe454eSLiang Ma 					printf(" power mgmt mode is mutually exclusive with other modes\n");
187726fe454eSLiang Ma 					return -1;
187826fe454eSLiang Ma 				}
187926fe454eSLiang Ma 				if (parse_pmd_mgmt_config(optarg) < 0) {
188026fe454eSLiang Ma 					printf(" Invalid PMD power management mode: %s\n",
188126fe454eSLiang Ma 							optarg);
188226fe454eSLiang Ma 					return -1;
188326fe454eSLiang Ma 				}
188426fe454eSLiang Ma 				app_mode = APP_MODE_PMD_MGMT;
188526fe454eSLiang Ma 				printf("PMD power mgmt mode is enabled\n");
188626fe454eSLiang Ma 			}
188726fe454eSLiang Ma 			if (!strncmp(lgopts[option_index].name,
1888e0194febSAnatoly Burakov 					CMD_LINE_OPT_INTERRUPT_ONLY,
1889e0194febSAnatoly Burakov 					sizeof(CMD_LINE_OPT_INTERRUPT_ONLY))) {
1890e0194febSAnatoly Burakov 				if (app_mode != APP_MODE_DEFAULT) {
1891e0194febSAnatoly Burakov 					printf(" interrupt-only mode is mutually exclusive with other modes\n");
1892e0194febSAnatoly Burakov 					return -1;
1893e0194febSAnatoly Burakov 				}
1894e0194febSAnatoly Burakov 				app_mode = APP_MODE_INTERRUPT;
1895e0194febSAnatoly Burakov 				printf("interrupt-only mode is enabled\n");
1896e0194febSAnatoly Burakov 			}
1897e0194febSAnatoly Burakov 
1898e0194febSAnatoly Burakov 			if (!strncmp(lgopts[option_index].name,
18991bb4a528SFerruh Yigit 					CMD_LINE_OPT_MAX_PKT_LEN,
19001bb4a528SFerruh Yigit 					sizeof(CMD_LINE_OPT_MAX_PKT_LEN))) {
19010bc4795dSHuisong Li 				if (parse_uint(optarg, UINT32_MAX, &max_pkt_len) != 0)
19020bc4795dSHuisong Li 					return -1;
19031bb4a528SFerruh Yigit 				printf("Custom frame size is configured\n");
1904d7937e2eSIntel 			}
1905d7937e2eSIntel 
190682bea466SJianfeng Tan 			if (!strncmp(lgopts[option_index].name,
190782bea466SJianfeng Tan 				     CMD_LINE_OPT_PARSE_PTYPE,
190882bea466SJianfeng Tan 				     sizeof(CMD_LINE_OPT_PARSE_PTYPE))) {
190982bea466SJianfeng Tan 				printf("soft parse-ptype is enabled\n");
191082bea466SJianfeng Tan 				parse_ptype = 1;
191182bea466SJianfeng Tan 			}
191282bea466SJianfeng Tan 
191359f2853cSKevin Laatz 			if (!strncmp(lgopts[option_index].name,
191459f2853cSKevin Laatz 					CMD_LINE_OPT_MAX_EMPTY_POLLS,
191559f2853cSKevin Laatz 					sizeof(CMD_LINE_OPT_MAX_EMPTY_POLLS))) {
19160bc4795dSHuisong Li 				if (parse_uint(optarg, UINT32_MAX, &max_empty_polls) != 0)
19170bc4795dSHuisong Li 					return -1;
191859f2853cSKevin Laatz 				printf("Maximum empty polls configured\n");
191959f2853cSKevin Laatz 			}
192059f2853cSKevin Laatz 
192159f2853cSKevin Laatz 			if (!strncmp(lgopts[option_index].name,
192259f2853cSKevin Laatz 					CMD_LINE_OPT_PAUSE_DURATION,
192359f2853cSKevin Laatz 					sizeof(CMD_LINE_OPT_PAUSE_DURATION))) {
19240bc4795dSHuisong Li 				if (parse_uint(optarg, UINT32_MAX, &pause_duration) != 0)
19250bc4795dSHuisong Li 					return -1;
192659f2853cSKevin Laatz 				printf("Pause duration configured\n");
192759f2853cSKevin Laatz 			}
192859f2853cSKevin Laatz 
192959f2853cSKevin Laatz 			if (!strncmp(lgopts[option_index].name,
193059f2853cSKevin Laatz 					CMD_LINE_OPT_SCALE_FREQ_MIN,
193159f2853cSKevin Laatz 					sizeof(CMD_LINE_OPT_SCALE_FREQ_MIN))) {
19320bc4795dSHuisong Li 				if (parse_uint(optarg, UINT32_MAX, &scale_freq_min) != 0)
19330bc4795dSHuisong Li 					return -1;
193459f2853cSKevin Laatz 				printf("Scaling frequency minimum configured\n");
193559f2853cSKevin Laatz 			}
193659f2853cSKevin Laatz 
193759f2853cSKevin Laatz 			if (!strncmp(lgopts[option_index].name,
193859f2853cSKevin Laatz 					CMD_LINE_OPT_SCALE_FREQ_MAX,
193959f2853cSKevin Laatz 					sizeof(CMD_LINE_OPT_SCALE_FREQ_MAX))) {
19400bc4795dSHuisong Li 				if (parse_uint(optarg, UINT32_MAX, &scale_freq_max) != 0)
19410bc4795dSHuisong Li 					return -1;
194259f2853cSKevin Laatz 				printf("Scaling frequency maximum configured\n");
194359f2853cSKevin Laatz 			}
194459f2853cSKevin Laatz 
19454d23d39fSHuisong Li 			if (!strncmp(lgopts[option_index].name,
19464d23d39fSHuisong Li 					CMD_LINE_OPT_CPU_RESUME_LATENCY,
19474d23d39fSHuisong Li 					sizeof(CMD_LINE_OPT_CPU_RESUME_LATENCY))) {
19484d23d39fSHuisong Li 				if (parse_uint(optarg, INT_MAX,
19494d23d39fSHuisong Li 						(uint32_t *)&cpu_resume_latency) != 0)
19504d23d39fSHuisong Li 					return -1;
19514d23d39fSHuisong Li 				printf("PM QoS configured\n");
19524d23d39fSHuisong Li 			}
19534d23d39fSHuisong Li 
1954d7937e2eSIntel 			break;
1955d7937e2eSIntel 
1956d7937e2eSIntel 		default:
1957d7937e2eSIntel 			print_usage(prgname);
1958d7937e2eSIntel 			return -1;
1959d7937e2eSIntel 		}
1960d7937e2eSIntel 	}
1961d7937e2eSIntel 
1962d7937e2eSIntel 	if (optind >= 0)
1963d7937e2eSIntel 		argv[optind-1] = prgname;
1964d7937e2eSIntel 
1965d7937e2eSIntel 	ret = optind-1;
19669d5ca532SKeith Wiles 	optind = 1; /* reset getopt lib */
1967d7937e2eSIntel 	return ret;
1968d7937e2eSIntel }
1969d7937e2eSIntel 
1970d7937e2eSIntel static void
19716d13ea8eSOlivier Matz print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
1972d7937e2eSIntel {
197335b2d13fSOlivier Matz 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
197435b2d13fSOlivier Matz 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
1975ec3d82dbSCunming Liang 	printf("%s%s", name, buf);
1976d7937e2eSIntel }
1977d7937e2eSIntel 
1978d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
1979d7937e2eSIntel static void
1980d7937e2eSIntel setup_hash(int socketid)
1981d7937e2eSIntel {
1982d7937e2eSIntel 	struct rte_hash_parameters ipv4_l3fwd_hash_params = {
1983d7937e2eSIntel 		.name = NULL,
1984d7937e2eSIntel 		.entries = L3FWD_HASH_ENTRIES,
1985d7937e2eSIntel 		.key_len = sizeof(struct ipv4_5tuple),
1986d7937e2eSIntel 		.hash_func = DEFAULT_HASH_FUNC,
1987d7937e2eSIntel 		.hash_func_init_val = 0,
1988d7937e2eSIntel 	};
1989d7937e2eSIntel 
1990d7937e2eSIntel 	struct rte_hash_parameters ipv6_l3fwd_hash_params = {
1991d7937e2eSIntel 		.name = NULL,
1992d7937e2eSIntel 		.entries = L3FWD_HASH_ENTRIES,
1993d7937e2eSIntel 		.key_len = sizeof(struct ipv6_5tuple),
1994d7937e2eSIntel 		.hash_func = DEFAULT_HASH_FUNC,
1995d7937e2eSIntel 		.hash_func_init_val = 0,
1996d7937e2eSIntel 	};
1997d7937e2eSIntel 
1998d7937e2eSIntel 	unsigned i;
1999d7937e2eSIntel 	int ret;
2000d7937e2eSIntel 	char s[64];
2001d7937e2eSIntel 
2002d7937e2eSIntel 	/* create ipv4 hash */
2003a5cf3924SThomas Monjalon 	snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid);
2004d7937e2eSIntel 	ipv4_l3fwd_hash_params.name = s;
2005d7937e2eSIntel 	ipv4_l3fwd_hash_params.socket_id = socketid;
2006d7937e2eSIntel 	ipv4_l3fwd_lookup_struct[socketid] =
2007d7937e2eSIntel 		rte_hash_create(&ipv4_l3fwd_hash_params);
2008d7937e2eSIntel 	if (ipv4_l3fwd_lookup_struct[socketid] == NULL)
2009d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on "
2010d7937e2eSIntel 				"socket %d\n", socketid);
2011d7937e2eSIntel 
2012d7937e2eSIntel 	/* create ipv6 hash */
2013a5cf3924SThomas Monjalon 	snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid);
2014d7937e2eSIntel 	ipv6_l3fwd_hash_params.name = s;
2015d7937e2eSIntel 	ipv6_l3fwd_hash_params.socket_id = socketid;
2016d7937e2eSIntel 	ipv6_l3fwd_lookup_struct[socketid] =
2017d7937e2eSIntel 		rte_hash_create(&ipv6_l3fwd_hash_params);
2018d7937e2eSIntel 	if (ipv6_l3fwd_lookup_struct[socketid] == NULL)
2019d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on "
2020d7937e2eSIntel 				"socket %d\n", socketid);
2021d7937e2eSIntel 
2022d7937e2eSIntel 
2023d7937e2eSIntel 	/* populate the ipv4 hash */
20247efe28bdSPavan Nikhilesh 	for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
2025d7937e2eSIntel 		ret = rte_hash_add_key (ipv4_l3fwd_lookup_struct[socketid],
2026d7937e2eSIntel 				(void *) &ipv4_l3fwd_route_array[i].key);
2027d7937e2eSIntel 		if (ret < 0) {
2028d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "Unable to add entry %u to the"
2029d7937e2eSIntel 				"l3fwd hash on socket %d\n", i, socketid);
2030d7937e2eSIntel 		}
2031d7937e2eSIntel 		ipv4_l3fwd_out_if[ret] = ipv4_l3fwd_route_array[i].if_out;
2032d7937e2eSIntel 		printf("Hash: Adding key\n");
2033d7937e2eSIntel 		print_ipv4_key(ipv4_l3fwd_route_array[i].key);
2034d7937e2eSIntel 	}
2035d7937e2eSIntel 
2036d7937e2eSIntel 	/* populate the ipv6 hash */
20377efe28bdSPavan Nikhilesh 	for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
2038d7937e2eSIntel 		ret = rte_hash_add_key (ipv6_l3fwd_lookup_struct[socketid],
2039d7937e2eSIntel 				(void *) &ipv6_l3fwd_route_array[i].key);
2040d7937e2eSIntel 		if (ret < 0) {
2041d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "Unable to add entry %u to the"
2042d7937e2eSIntel 				"l3fwd hash on socket %d\n", i, socketid);
2043d7937e2eSIntel 		}
2044d7937e2eSIntel 		ipv6_l3fwd_out_if[ret] = ipv6_l3fwd_route_array[i].if_out;
2045d7937e2eSIntel 		printf("Hash: Adding key\n");
2046d7937e2eSIntel 		print_ipv6_key(ipv6_l3fwd_route_array[i].key);
2047d7937e2eSIntel 	}
2048d7937e2eSIntel }
2049d7937e2eSIntel #endif
2050d7937e2eSIntel 
2051d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
2052d7937e2eSIntel static void
2053d7937e2eSIntel setup_lpm(int socketid)
2054d7937e2eSIntel {
2055d7937e2eSIntel 	unsigned i;
2056d7937e2eSIntel 	int ret;
2057d7937e2eSIntel 	char s[64];
2058d7937e2eSIntel 
2059d7937e2eSIntel 	/* create the LPM table */
2060f1f72618SMichal Kobylinski 	struct rte_lpm_config lpm_ipv4_config;
2061f1f72618SMichal Kobylinski 
2062f1f72618SMichal Kobylinski 	lpm_ipv4_config.max_rules = IPV4_L3FWD_LPM_MAX_RULES;
2063f1f72618SMichal Kobylinski 	lpm_ipv4_config.number_tbl8s = 256;
2064f1f72618SMichal Kobylinski 	lpm_ipv4_config.flags = 0;
2065f1f72618SMichal Kobylinski 
20666f41fe75SStephen Hemminger 	snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid);
2067f1f72618SMichal Kobylinski 	ipv4_l3fwd_lookup_struct[socketid] =
2068f1f72618SMichal Kobylinski 			rte_lpm_create(s, socketid, &lpm_ipv4_config);
2069d7937e2eSIntel 	if (ipv4_l3fwd_lookup_struct[socketid] == NULL)
2070d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table"
2071d7937e2eSIntel 				" on socket %d\n", socketid);
2072d7937e2eSIntel 
2073d7937e2eSIntel 	/* populate the LPM table */
20747efe28bdSPavan Nikhilesh 	for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
2075d7937e2eSIntel 		ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid],
2076d7937e2eSIntel 			ipv4_l3fwd_route_array[i].ip,
2077d7937e2eSIntel 			ipv4_l3fwd_route_array[i].depth,
2078d7937e2eSIntel 			ipv4_l3fwd_route_array[i].if_out);
2079d7937e2eSIntel 
2080d7937e2eSIntel 		if (ret < 0) {
2081d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "Unable to add entry %u to the "
2082d7937e2eSIntel 				"l3fwd LPM table on socket %d\n",
2083d7937e2eSIntel 				i, socketid);
2084d7937e2eSIntel 		}
2085d7937e2eSIntel 
2086d7937e2eSIntel 		printf("LPM: Adding route 0x%08x / %d (%d)\n",
2087d7937e2eSIntel 			(unsigned)ipv4_l3fwd_route_array[i].ip,
2088d7937e2eSIntel 			ipv4_l3fwd_route_array[i].depth,
2089d7937e2eSIntel 			ipv4_l3fwd_route_array[i].if_out);
2090d7937e2eSIntel 	}
2091d7937e2eSIntel }
2092d7937e2eSIntel #endif
2093d7937e2eSIntel 
2094d7937e2eSIntel static int
2095d7937e2eSIntel init_mem(unsigned nb_mbuf)
2096d7937e2eSIntel {
2097d7937e2eSIntel 	struct lcore_conf *qconf;
2098d7937e2eSIntel 	int socketid;
2099d7937e2eSIntel 	unsigned lcore_id;
2100d7937e2eSIntel 	char s[64];
2101d7937e2eSIntel 
2102d7937e2eSIntel 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2103d7937e2eSIntel 		if (rte_lcore_is_enabled(lcore_id) == 0)
2104d7937e2eSIntel 			continue;
2105d7937e2eSIntel 
2106d7937e2eSIntel 		if (numa_on)
2107d7937e2eSIntel 			socketid = rte_lcore_to_socket_id(lcore_id);
2108d7937e2eSIntel 		else
2109d7937e2eSIntel 			socketid = 0;
2110d7937e2eSIntel 
2111d7937e2eSIntel 		if (socketid >= NB_SOCKETS) {
2112d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is "
2113d7937e2eSIntel 					"out of range %d\n", socketid,
2114d7937e2eSIntel 						lcore_id, NB_SOCKETS);
2115d7937e2eSIntel 		}
2116d7937e2eSIntel 		if (pktmbuf_pool[socketid] == NULL) {
21176f41fe75SStephen Hemminger 			snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
2118d7937e2eSIntel 			pktmbuf_pool[socketid] =
2119ea0c20eaSOlivier Matz 				rte_pktmbuf_pool_create(s, nb_mbuf,
2120824cb29cSKonstantin Ananyev 					MEMPOOL_CACHE_SIZE, 0,
2121824cb29cSKonstantin Ananyev 					RTE_MBUF_DEFAULT_BUF_SIZE,
2122ea0c20eaSOlivier Matz 					socketid);
2123d7937e2eSIntel 			if (pktmbuf_pool[socketid] == NULL)
2124d7937e2eSIntel 				rte_exit(EXIT_FAILURE,
2125d7937e2eSIntel 					"Cannot init mbuf pool on socket %d\n",
2126d7937e2eSIntel 								socketid);
2127d7937e2eSIntel 			else
2128d7937e2eSIntel 				printf("Allocated mbuf pool on socket %d\n",
2129d7937e2eSIntel 								socketid);
2130d7937e2eSIntel 
2131d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
2132d7937e2eSIntel 			setup_lpm(socketid);
2133d7937e2eSIntel #else
2134d7937e2eSIntel 			setup_hash(socketid);
2135d7937e2eSIntel #endif
2136d7937e2eSIntel 		}
2137d7937e2eSIntel 		qconf = &lcore_conf[lcore_id];
2138d7937e2eSIntel 		qconf->ipv4_lookup_struct = ipv4_l3fwd_lookup_struct[socketid];
2139d7937e2eSIntel #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
2140d7937e2eSIntel 		qconf->ipv6_lookup_struct = ipv6_l3fwd_lookup_struct[socketid];
2141d7937e2eSIntel #endif
2142d7937e2eSIntel 	}
2143d7937e2eSIntel 	return 0;
2144d7937e2eSIntel }
2145d7937e2eSIntel 
2146d7937e2eSIntel /* Check the link status of all ports in up to 9s, and print them finally */
2147d7937e2eSIntel static void
21488728ccf3SThomas Monjalon check_all_ports_link_status(uint32_t port_mask)
2149d7937e2eSIntel {
2150d7937e2eSIntel #define CHECK_INTERVAL 100 /* 100ms */
2151d7937e2eSIntel #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
2152f8244c63SZhiyong Yang 	uint8_t count, all_ports_up, print_flag = 0;
2153f8244c63SZhiyong Yang 	uint16_t portid;
2154d7937e2eSIntel 	struct rte_eth_link link;
215522e5c73bSIgor Romanov 	int ret;
2156db4e8135SIvan Dyukov 	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
2157d7937e2eSIntel 
2158d7937e2eSIntel 	printf("\nChecking link status");
2159d7937e2eSIntel 	fflush(stdout);
2160d7937e2eSIntel 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
2161d7937e2eSIntel 		all_ports_up = 1;
21628728ccf3SThomas Monjalon 		RTE_ETH_FOREACH_DEV(portid) {
2163d7937e2eSIntel 			if ((port_mask & (1 << portid)) == 0)
2164d7937e2eSIntel 				continue;
2165d7937e2eSIntel 			memset(&link, 0, sizeof(link));
216622e5c73bSIgor Romanov 			ret = rte_eth_link_get_nowait(portid, &link);
216722e5c73bSIgor Romanov 			if (ret < 0) {
216822e5c73bSIgor Romanov 				all_ports_up = 0;
216922e5c73bSIgor Romanov 				if (print_flag == 1)
217022e5c73bSIgor Romanov 					printf("Port %u link get failed: %s\n",
217122e5c73bSIgor Romanov 						portid, rte_strerror(-ret));
217222e5c73bSIgor Romanov 				continue;
217322e5c73bSIgor Romanov 			}
2174d7937e2eSIntel 			/* print link status if flag set */
2175d7937e2eSIntel 			if (print_flag == 1) {
2176db4e8135SIvan Dyukov 				rte_eth_link_to_str(link_status_text,
2177db4e8135SIvan Dyukov 					sizeof(link_status_text), &link);
2178db4e8135SIvan Dyukov 				printf("Port %d %s\n", portid,
2179db4e8135SIvan Dyukov 				       link_status_text);
2180d7937e2eSIntel 				continue;
2181d7937e2eSIntel 			}
2182d7937e2eSIntel 			/* clear all_ports_up flag if any link down */
2183295968d1SFerruh Yigit 			if (link.link_status == RTE_ETH_LINK_DOWN) {
2184d7937e2eSIntel 				all_ports_up = 0;
2185d7937e2eSIntel 				break;
2186d7937e2eSIntel 			}
2187d7937e2eSIntel 		}
2188d7937e2eSIntel 		/* after finally printing all link status, get out */
2189d7937e2eSIntel 		if (print_flag == 1)
2190d7937e2eSIntel 			break;
2191d7937e2eSIntel 
2192d7937e2eSIntel 		if (all_ports_up == 0) {
2193d7937e2eSIntel 			printf(".");
2194d7937e2eSIntel 			fflush(stdout);
2195d7937e2eSIntel 			rte_delay_ms(CHECK_INTERVAL);
2196d7937e2eSIntel 		}
2197d7937e2eSIntel 
2198d7937e2eSIntel 		/* set the print_flag if all ports up or timeout */
2199d7937e2eSIntel 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
2200d7937e2eSIntel 			print_flag = 1;
2201d7937e2eSIntel 			printf("done\n");
2202d7937e2eSIntel 		}
2203d7937e2eSIntel 	}
2204d7937e2eSIntel }
2205d7937e2eSIntel 
220647523597SZhiyong Yang static int check_ptype(uint16_t portid)
220782bea466SJianfeng Tan {
220882bea466SJianfeng Tan 	int i, ret;
220982bea466SJianfeng Tan 	int ptype_l3_ipv4 = 0;
221082bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
221182bea466SJianfeng Tan 	int ptype_l3_ipv6 = 0;
221282bea466SJianfeng Tan #endif
221382bea466SJianfeng Tan 	uint32_t ptype_mask = RTE_PTYPE_L3_MASK;
221482bea466SJianfeng Tan 
221582bea466SJianfeng Tan 	ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0);
221682bea466SJianfeng Tan 	if (ret <= 0)
221782bea466SJianfeng Tan 		return 0;
221882bea466SJianfeng Tan 
221982bea466SJianfeng Tan 	uint32_t ptypes[ret];
222082bea466SJianfeng Tan 
222182bea466SJianfeng Tan 	ret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, ret);
222282bea466SJianfeng Tan 	for (i = 0; i < ret; ++i) {
222382bea466SJianfeng Tan 		if (ptypes[i] & RTE_PTYPE_L3_IPV4)
222482bea466SJianfeng Tan 			ptype_l3_ipv4 = 1;
222582bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
222682bea466SJianfeng Tan 		if (ptypes[i] & RTE_PTYPE_L3_IPV6)
222782bea466SJianfeng Tan 			ptype_l3_ipv6 = 1;
222882bea466SJianfeng Tan #endif
222982bea466SJianfeng Tan 	}
223082bea466SJianfeng Tan 
223182bea466SJianfeng Tan 	if (ptype_l3_ipv4 == 0)
223282bea466SJianfeng Tan 		printf("port %d cannot parse RTE_PTYPE_L3_IPV4\n", portid);
223382bea466SJianfeng Tan 
223482bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH)
223582bea466SJianfeng Tan 	if (ptype_l3_ipv6 == 0)
223682bea466SJianfeng Tan 		printf("port %d cannot parse RTE_PTYPE_L3_IPV6\n", portid);
223782bea466SJianfeng Tan #endif
223882bea466SJianfeng Tan 
223982bea466SJianfeng Tan #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
224082bea466SJianfeng Tan 	if (ptype_l3_ipv4)
224182bea466SJianfeng Tan #else /* APP_LOOKUP_EXACT_MATCH */
224282bea466SJianfeng Tan 	if (ptype_l3_ipv4 && ptype_l3_ipv6)
224382bea466SJianfeng Tan #endif
224482bea466SJianfeng Tan 		return 1;
224582bea466SJianfeng Tan 
224682bea466SJianfeng Tan 	return 0;
224782bea466SJianfeng Tan 
224882bea466SJianfeng Tan }
224982bea466SJianfeng Tan 
2250f88e7c17SRadu Nicolau static int
2251f88e7c17SRadu Nicolau init_power_library(void)
2252f88e7c17SRadu Nicolau {
22539b133b42SAnatoly Burakov 	enum power_management_env env;
2254a163130bSAnatoly Burakov 	unsigned int lcore_id;
2255a163130bSAnatoly Burakov 	int ret = 0;
2256a163130bSAnatoly Burakov 
2257a163130bSAnatoly Burakov 	RTE_LCORE_FOREACH(lcore_id) {
2258f88e7c17SRadu Nicolau 		/* init power management library */
2259f88e7c17SRadu Nicolau 		ret = rte_power_init(lcore_id);
2260a163130bSAnatoly Burakov 		if (ret) {
22618bae59edSStephen Hemminger 			RTE_LOG(ERR, L3FWD_POWER,
2262f88e7c17SRadu Nicolau 				"Library initialization failed on core %u\n",
2263f88e7c17SRadu Nicolau 				lcore_id);
2264a163130bSAnatoly Burakov 			return ret;
2265f88e7c17SRadu Nicolau 		}
22669b133b42SAnatoly Burakov 		/* we're not supporting the VM channel mode */
22679b133b42SAnatoly Burakov 		env = rte_power_get_env();
22689b133b42SAnatoly Burakov 		if (env != PM_ENV_ACPI_CPUFREQ &&
2269bc6fe484SJie Hai 				env != PM_ENV_PSTATE_CPUFREQ &&
22701ed04d33SSivaprasad Tummala 				env != PM_ENV_AMD_PSTATE_CPUFREQ &&
2271bc6fe484SJie Hai 				env != PM_ENV_CPPC_CPUFREQ) {
22728bae59edSStephen Hemminger 			RTE_LOG(ERR, L3FWD_POWER,
22738bae59edSStephen Hemminger 				"Only ACPI and PSTATE mode are supported\n");
22749b133b42SAnatoly Burakov 			return -1;
22759b133b42SAnatoly Burakov 		}
2276f88e7c17SRadu Nicolau 	}
22774d23d39fSHuisong Li 
22784d23d39fSHuisong Li 	if (cpu_resume_latency != -1) {
22794d23d39fSHuisong Li 		RTE_LCORE_FOREACH(lcore_id) {
22804d23d39fSHuisong Li 			/* Back old CPU resume latency. */
22814d23d39fSHuisong Li 			ret = rte_power_qos_get_cpu_resume_latency(lcore_id);
22824d23d39fSHuisong Li 			if (ret < 0) {
22834d23d39fSHuisong Li 				RTE_LOG(ERR, L3FWD_POWER,
22844d23d39fSHuisong Li 					"Failed to get cpu resume latency on lcore-%u, ret=%d.\n",
22854d23d39fSHuisong Li 					lcore_id, ret);
22864d23d39fSHuisong Li 			}
22874d23d39fSHuisong Li 			resume_latency_bk[lcore_id] = ret;
22884d23d39fSHuisong Li 
22894d23d39fSHuisong Li 			/*
22904d23d39fSHuisong Li 			 * Set the cpu resume latency of the worker lcore based
22914d23d39fSHuisong Li 			 * on user's request. If set strict latency (0), just
22924d23d39fSHuisong Li 			 * allow the CPU to enter the shallowest idle state to
22934d23d39fSHuisong Li 			 * improve performance.
22944d23d39fSHuisong Li 			 */
22954d23d39fSHuisong Li 			ret = rte_power_qos_set_cpu_resume_latency(lcore_id,
22964d23d39fSHuisong Li 							cpu_resume_latency);
22974d23d39fSHuisong Li 			if (ret != 0) {
22984d23d39fSHuisong Li 				RTE_LOG(ERR, L3FWD_POWER,
22994d23d39fSHuisong Li 					"Failed to set cpu resume latency on lcore-%u, ret=%d.\n",
23004d23d39fSHuisong Li 					lcore_id, ret);
23014d23d39fSHuisong Li 				return ret;
23024d23d39fSHuisong Li 			}
23034d23d39fSHuisong Li 		}
23044d23d39fSHuisong Li 	}
23054d23d39fSHuisong Li 
2306f88e7c17SRadu Nicolau 	return ret;
2307f88e7c17SRadu Nicolau }
2308613ce669SAnatoly Burakov 
2309613ce669SAnatoly Burakov static int
2310613ce669SAnatoly Burakov deinit_power_library(void)
2311613ce669SAnatoly Burakov {
231210db2a5bSTadhg Kearney 	unsigned int lcore_id, max_pkg, max_die, die, pkg;
2313613ce669SAnatoly Burakov 	int ret = 0;
2314613ce669SAnatoly Burakov 
2315613ce669SAnatoly Burakov 	RTE_LCORE_FOREACH(lcore_id) {
2316613ce669SAnatoly Burakov 		/* deinit power management library */
2317613ce669SAnatoly Burakov 		ret = rte_power_exit(lcore_id);
2318613ce669SAnatoly Burakov 		if (ret) {
23198bae59edSStephen Hemminger 			RTE_LOG(ERR, L3FWD_POWER,
2320613ce669SAnatoly Burakov 				"Library deinitialization failed on core %u\n",
2321613ce669SAnatoly Burakov 				lcore_id);
2322613ce669SAnatoly Burakov 			return ret;
2323613ce669SAnatoly Burakov 		}
2324613ce669SAnatoly Burakov 	}
232510db2a5bSTadhg Kearney 
232610db2a5bSTadhg Kearney 	/* if uncore option was set */
232710db2a5bSTadhg Kearney 	if (enabled_uncore == 0) {
232810db2a5bSTadhg Kearney 		max_pkg = rte_power_uncore_get_num_pkgs();
232910db2a5bSTadhg Kearney 		if (max_pkg == 0)
233010db2a5bSTadhg Kearney 			return -1;
233110db2a5bSTadhg Kearney 		for (pkg = 0; pkg < max_pkg; pkg++) {
233210db2a5bSTadhg Kearney 			max_die = rte_power_uncore_get_num_dies(pkg);
233310db2a5bSTadhg Kearney 			if (max_die == 0)
233410db2a5bSTadhg Kearney 				return -1;
233510db2a5bSTadhg Kearney 			for (die = 0; die < max_die; die++) {
233610db2a5bSTadhg Kearney 				ret = rte_power_uncore_exit(pkg, die);
233710db2a5bSTadhg Kearney 				if (ret < 0) {
233810db2a5bSTadhg Kearney 					RTE_LOG(ERR, L3FWD_POWER, "Failed to exit uncore deinit successfully for pkg %02u die %02u\n"
233910db2a5bSTadhg Kearney 						, pkg, die);
234010db2a5bSTadhg Kearney 					return -1;
234110db2a5bSTadhg Kearney 				}
234210db2a5bSTadhg Kearney 			}
234310db2a5bSTadhg Kearney 		}
234410db2a5bSTadhg Kearney 	}
23454d23d39fSHuisong Li 
23464d23d39fSHuisong Li 	if (cpu_resume_latency != -1) {
23474d23d39fSHuisong Li 		RTE_LCORE_FOREACH(lcore_id) {
23484d23d39fSHuisong Li 			/* Restore the original value. */
23494d23d39fSHuisong Li 			rte_power_qos_set_cpu_resume_latency(lcore_id,
23504d23d39fSHuisong Li 						resume_latency_bk[lcore_id]);
23514d23d39fSHuisong Li 		}
23524d23d39fSHuisong Li 	}
23534d23d39fSHuisong Li 
2354613ce669SAnatoly Burakov 	return ret;
2355613ce669SAnatoly Burakov }
2356613ce669SAnatoly Burakov 
2357a137d012SLiang Ma static void
2358a35919a1SCiara Power get_current_stat_values(uint64_t *values)
2359609e7984SReshma Pattan {
2360609e7984SReshma Pattan 	unsigned int lcore_id = rte_lcore_id();
2361609e7984SReshma Pattan 	struct lcore_conf *qconf;
2362609e7984SReshma Pattan 	uint64_t app_eps = 0, app_fps = 0, app_br = 0;
2363609e7984SReshma Pattan 	uint64_t count = 0;
2364609e7984SReshma Pattan 
2365cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
2366609e7984SReshma Pattan 		qconf = &lcore_conf[lcore_id];
2367609e7984SReshma Pattan 		if (qconf->n_rx_queue == 0)
2368609e7984SReshma Pattan 			continue;
2369609e7984SReshma Pattan 		count++;
2370609e7984SReshma Pattan 		rte_spinlock_lock(&stats[lcore_id].telemetry_lock);
2371609e7984SReshma Pattan 		app_eps += stats[lcore_id].ep_nep[1];
2372609e7984SReshma Pattan 		app_fps += stats[lcore_id].fp_nfp[1];
2373609e7984SReshma Pattan 		app_br += stats[lcore_id].br;
2374609e7984SReshma Pattan 		rte_spinlock_unlock(&stats[lcore_id].telemetry_lock);
2375609e7984SReshma Pattan 	}
2376609e7984SReshma Pattan 
2377018faf21SDavid Hunt 	if (count > 0) {
2378018faf21SDavid Hunt 		values[0] = app_eps/count;
2379018faf21SDavid Hunt 		values[1] = app_fps/count;
2380018faf21SDavid Hunt 		values[2] = app_br/count;
2381a35919a1SCiara Power 	} else
2382a35919a1SCiara Power 		memset(values, 0, sizeof(uint64_t) * NUM_TELSTATS);
2383a35919a1SCiara Power 
2384018faf21SDavid Hunt }
2385018faf21SDavid Hunt 
2386a35919a1SCiara Power static void
2387a35919a1SCiara Power update_telemetry(__rte_unused struct rte_timer *tim,
2388a35919a1SCiara Power 		__rte_unused void *arg)
2389a35919a1SCiara Power {
2390a35919a1SCiara Power 	int ret;
2391a35919a1SCiara Power 	uint64_t values[NUM_TELSTATS] = {0};
2392a35919a1SCiara Power 
2393a35919a1SCiara Power 	get_current_stat_values(values);
2394609e7984SReshma Pattan 	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, telstats_index,
2395609e7984SReshma Pattan 					values, RTE_DIM(values));
2396609e7984SReshma Pattan 	if (ret < 0)
23978bae59edSStephen Hemminger 		RTE_LOG(WARNING, L3FWD_POWER, "failed to update metrics\n");
2398609e7984SReshma Pattan }
2399eeb486f3SCiara Power 
2400a35919a1SCiara Power static int
2401a35919a1SCiara Power handle_app_stats(const char *cmd __rte_unused,
2402a35919a1SCiara Power 		const char *params __rte_unused,
2403a35919a1SCiara Power 		struct rte_tel_data *d)
2404a35919a1SCiara Power {
2405a35919a1SCiara Power 	uint64_t values[NUM_TELSTATS] = {0};
2406a35919a1SCiara Power 	uint32_t i;
2407a35919a1SCiara Power 
2408a35919a1SCiara Power 	rte_tel_data_start_dict(d);
2409a35919a1SCiara Power 	get_current_stat_values(values);
2410a35919a1SCiara Power 	for (i = 0; i < NUM_TELSTATS; i++)
2411af0785a2SBruce Richardson 		rte_tel_data_add_dict_uint(d, telstats_strings[i].name,
2412a35919a1SCiara Power 					   values[i]);
2413a35919a1SCiara Power 	return 0;
2414a35919a1SCiara Power }
2415eeb486f3SCiara Power 
2416609e7984SReshma Pattan static void
2417609e7984SReshma Pattan telemetry_setup_timer(void)
2418609e7984SReshma Pattan {
2419609e7984SReshma Pattan 	int lcore_id = rte_lcore_id();
2420609e7984SReshma Pattan 	uint64_t hz = rte_get_timer_hz();
2421609e7984SReshma Pattan 	uint64_t ticks;
2422609e7984SReshma Pattan 
2423609e7984SReshma Pattan 	ticks = hz / TELEMETRY_INTERVALS_PER_SEC;
2424609e7984SReshma Pattan 	rte_timer_reset_sync(&telemetry_timer,
2425609e7984SReshma Pattan 			ticks,
2426609e7984SReshma Pattan 			PERIODICAL,
2427609e7984SReshma Pattan 			lcore_id,
2428609e7984SReshma Pattan 			update_telemetry,
2429609e7984SReshma Pattan 			NULL);
2430609e7984SReshma Pattan }
2431a137d012SLiang Ma 
2432a137d012SLiang Ma static int
2433a137d012SLiang Ma launch_timer(unsigned int lcore_id)
2434a137d012SLiang Ma {
2435a137d012SLiang Ma 	int64_t prev_tsc = 0, cur_tsc, diff_tsc, cycles_10ms;
2436a137d012SLiang Ma 
2437a137d012SLiang Ma 	RTE_SET_USED(lcore_id);
2438a137d012SLiang Ma 
2439a137d012SLiang Ma 
2440cb056611SStephen Hemminger 	if (rte_get_main_lcore() != lcore_id) {
2441cb056611SStephen Hemminger 		rte_panic("timer on lcore:%d which is not main core:%d\n",
2442a137d012SLiang Ma 				lcore_id,
2443cb056611SStephen Hemminger 				rte_get_main_lcore());
2444a137d012SLiang Ma 	}
2445a137d012SLiang Ma 
24468bae59edSStephen Hemminger 	RTE_LOG(INFO, L3FWD_POWER, "Bring up the Timer\n");
2447a137d012SLiang Ma 
2448609e7984SReshma Pattan 	telemetry_setup_timer();
2449a137d012SLiang Ma 
2450a137d012SLiang Ma 	cycles_10ms = rte_get_timer_hz() / 100;
2451a137d012SLiang Ma 
2452a137d012SLiang Ma 	while (!is_done()) {
2453a137d012SLiang Ma 		cur_tsc = rte_rdtsc();
2454a137d012SLiang Ma 		diff_tsc = cur_tsc - prev_tsc;
2455a137d012SLiang Ma 		if (diff_tsc > cycles_10ms) {
2456a137d012SLiang Ma 			rte_timer_manage();
2457a137d012SLiang Ma 			prev_tsc = cur_tsc;
2458a137d012SLiang Ma 			cycles_10ms = rte_get_timer_hz() / 100;
2459a137d012SLiang Ma 		}
2460a137d012SLiang Ma 	}
2461a137d012SLiang Ma 
24628bae59edSStephen Hemminger 	RTE_LOG(INFO, L3FWD_POWER, "Timer_subsystem is done\n");
2463a137d012SLiang Ma 
2464a137d012SLiang Ma 	return 0;
2465a137d012SLiang Ma }
2466a137d012SLiang Ma 
246711159dd6SAnatoly Burakov static int
246811159dd6SAnatoly Burakov autodetect_mode(void)
246911159dd6SAnatoly Burakov {
247011159dd6SAnatoly Burakov 	RTE_LOG(NOTICE, L3FWD_POWER, "Operating mode not specified, probing frequency scaling support...\n");
247111159dd6SAnatoly Burakov 
247211159dd6SAnatoly Burakov 	/*
247311159dd6SAnatoly Burakov 	 * Empty poll and telemetry modes have to be specifically requested to
247411159dd6SAnatoly Burakov 	 * be enabled, but we can auto-detect between interrupt mode with or
2475bc6fe484SJie Hai 	 * without frequency scaling. Any of ACPI, pstate and CPPC can be used.
247611159dd6SAnatoly Burakov 	 */
247711159dd6SAnatoly Burakov 	if (rte_power_check_env_supported(PM_ENV_ACPI_CPUFREQ))
247811159dd6SAnatoly Burakov 		return APP_MODE_LEGACY;
247911159dd6SAnatoly Burakov 	if (rte_power_check_env_supported(PM_ENV_PSTATE_CPUFREQ))
248011159dd6SAnatoly Burakov 		return APP_MODE_LEGACY;
24811ed04d33SSivaprasad Tummala 	if (rte_power_check_env_supported(PM_ENV_AMD_PSTATE_CPUFREQ))
24821ed04d33SSivaprasad Tummala 		return APP_MODE_LEGACY;
2483bc6fe484SJie Hai 	if (rte_power_check_env_supported(PM_ENV_CPPC_CPUFREQ))
2484bc6fe484SJie Hai 		return APP_MODE_LEGACY;
248511159dd6SAnatoly Burakov 
248611159dd6SAnatoly Burakov 	RTE_LOG(NOTICE, L3FWD_POWER, "Frequency scaling not supported, selecting interrupt-only mode\n");
248711159dd6SAnatoly Burakov 
248811159dd6SAnatoly Burakov 	return APP_MODE_INTERRUPT;
248911159dd6SAnatoly Burakov }
249011159dd6SAnatoly Burakov 
249111159dd6SAnatoly Burakov static const char *
249211159dd6SAnatoly Burakov mode_to_str(enum appmode mode)
249311159dd6SAnatoly Burakov {
249411159dd6SAnatoly Burakov 	switch (mode) {
249511159dd6SAnatoly Burakov 	case APP_MODE_LEGACY:
249611159dd6SAnatoly Burakov 		return "legacy";
249711159dd6SAnatoly Burakov 	case APP_MODE_TELEMETRY:
249811159dd6SAnatoly Burakov 		return "telemetry";
249911159dd6SAnatoly Burakov 	case APP_MODE_INTERRUPT:
250011159dd6SAnatoly Burakov 		return "interrupt-only";
250126fe454eSLiang Ma 	case APP_MODE_PMD_MGMT:
250226fe454eSLiang Ma 		return "pmd mgmt";
250311159dd6SAnatoly Burakov 	default:
250411159dd6SAnatoly Burakov 		return "invalid";
250511159dd6SAnatoly Burakov 	}
250611159dd6SAnatoly Burakov }
2507f88e7c17SRadu Nicolau 
25081bb4a528SFerruh Yigit static uint32_t
25091bb4a528SFerruh Yigit eth_dev_get_overhead_len(uint32_t max_rx_pktlen, uint16_t max_mtu)
25101bb4a528SFerruh Yigit {
25111bb4a528SFerruh Yigit 	uint32_t overhead_len;
25121bb4a528SFerruh Yigit 
25131bb4a528SFerruh Yigit 	if (max_mtu != UINT16_MAX && max_rx_pktlen > max_mtu)
25141bb4a528SFerruh Yigit 		overhead_len = max_rx_pktlen - max_mtu;
25151bb4a528SFerruh Yigit 	else
25161bb4a528SFerruh Yigit 		overhead_len = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
25171bb4a528SFerruh Yigit 
25181bb4a528SFerruh Yigit 	return overhead_len;
25191bb4a528SFerruh Yigit }
25201bb4a528SFerruh Yigit 
25211bb4a528SFerruh Yigit static int
25221bb4a528SFerruh Yigit config_port_max_pkt_len(struct rte_eth_conf *conf,
25231bb4a528SFerruh Yigit 		struct rte_eth_dev_info *dev_info)
25241bb4a528SFerruh Yigit {
25251bb4a528SFerruh Yigit 	uint32_t overhead_len;
25261bb4a528SFerruh Yigit 
25271bb4a528SFerruh Yigit 	if (max_pkt_len == 0)
25281bb4a528SFerruh Yigit 		return 0;
25291bb4a528SFerruh Yigit 
25301bb4a528SFerruh Yigit 	if (max_pkt_len < RTE_ETHER_MIN_LEN || max_pkt_len > MAX_JUMBO_PKT_LEN)
25311bb4a528SFerruh Yigit 		return -1;
25321bb4a528SFerruh Yigit 
25331bb4a528SFerruh Yigit 	overhead_len = eth_dev_get_overhead_len(dev_info->max_rx_pktlen,
25341bb4a528SFerruh Yigit 			dev_info->max_mtu);
25351bb4a528SFerruh Yigit 	conf->rxmode.mtu = max_pkt_len - overhead_len;
25361bb4a528SFerruh Yigit 
2537b563c142SFerruh Yigit 	if (conf->rxmode.mtu > RTE_ETHER_MTU)
2538295968d1SFerruh Yigit 		conf->txmode.offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
25391bb4a528SFerruh Yigit 
25401bb4a528SFerruh Yigit 	return 0;
25411bb4a528SFerruh Yigit }
25421bb4a528SFerruh Yigit 
25439a212dc0SConor Fogarty /* Power library initialized in the main routine. 8< */
2544d7937e2eSIntel int
254598a16481SDavid Marchand main(int argc, char **argv)
2546d7937e2eSIntel {
2547d7937e2eSIntel 	struct lcore_conf *qconf;
254881f7ecd9SPablo de Lara 	struct rte_eth_dev_info dev_info;
254981f7ecd9SPablo de Lara 	struct rte_eth_txconf *txconf;
2550d7937e2eSIntel 	int ret;
255147523597SZhiyong Yang 	uint16_t nb_ports;
2552d7937e2eSIntel 	uint16_t queueid;
2553d7937e2eSIntel 	unsigned lcore_id;
2554d7937e2eSIntel 	uint64_t hz;
2555d7937e2eSIntel 	uint32_t n_tx_queue, nb_lcores;
2556aee3bc79SCunming Liang 	uint32_t dev_rxq_num, dev_txq_num;
2557b23c5bd7SSivaprasad Tummala 	uint8_t socketid;
2558b23c5bd7SSivaprasad Tummala 	uint16_t portid, nb_rx_queue, queue;
2559a35919a1SCiara Power 	const char *ptr_strings[NUM_TELSTATS];
2560d7937e2eSIntel 
2561d7937e2eSIntel 	/* init EAL */
2562d7937e2eSIntel 	ret = rte_eal_init(argc, argv);
2563d7937e2eSIntel 	if (ret < 0)
2564d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
2565d7937e2eSIntel 	argc -= ret;
2566d7937e2eSIntel 	argv += ret;
2567d7937e2eSIntel 
256819781e7aSHarneet Singh 	/* catch SIGINT and restore cpufreq governor to ondemand */
256919781e7aSHarneet Singh 	signal(SIGINT, signal_exit_now);
257019781e7aSHarneet Singh 
2571d7937e2eSIntel 	/* init RTE timer library to be used late */
2572d7937e2eSIntel 	rte_timer_subsystem_init();
2573d7937e2eSIntel 
2574a9ea6070SDavid Hunt 	/* if we're running pmd-mgmt mode, don't default to baseline mode */
2575a9ea6070SDavid Hunt 	baseline_enabled = false;
2576a9ea6070SDavid Hunt 
2577d7937e2eSIntel 	/* parse application arguments (after the EAL ones) */
2578d7937e2eSIntel 	ret = parse_args(argc, argv);
2579d7937e2eSIntel 	if (ret < 0)
2580d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");
2581d7937e2eSIntel 
25822a0e2e2dSAnatoly Burakov 	if (app_mode == APP_MODE_DEFAULT)
258311159dd6SAnatoly Burakov 		app_mode = autodetect_mode();
258411159dd6SAnatoly Burakov 
258511159dd6SAnatoly Burakov 	RTE_LOG(INFO, L3FWD_POWER, "Selected operation mode: %s\n",
258611159dd6SAnatoly Burakov 			mode_to_str(app_mode));
25872a0e2e2dSAnatoly Burakov 
25889c75ff42SDavid Hunt 	/* only legacy mode relies on power library */
25899c75ff42SDavid Hunt 	if ((app_mode == APP_MODE_LEGACY) && init_power_library())
2590a163130bSAnatoly Burakov 		rte_exit(EXIT_FAILURE, "init_power_library failed\n");
2591f88e7c17SRadu Nicolau 
2592f88e7c17SRadu Nicolau 	if (update_lcore_params() < 0)
2593f88e7c17SRadu Nicolau 		rte_exit(EXIT_FAILURE, "update_lcore_params failed\n");
2594f88e7c17SRadu Nicolau 
2595d7937e2eSIntel 	if (check_lcore_params() < 0)
2596d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "check_lcore_params failed\n");
2597d7937e2eSIntel 
2598d7937e2eSIntel 	ret = init_lcore_rx_queues();
2599d7937e2eSIntel 	if (ret < 0)
2600d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
2601d7937e2eSIntel 
2602d9a42a69SThomas Monjalon 	nb_ports = rte_eth_dev_count_avail();
2603d7937e2eSIntel 
2604a9dbe180SThomas Monjalon 	if (check_port_config() < 0)
2605d7937e2eSIntel 		rte_exit(EXIT_FAILURE, "check_port_config failed\n");
2606d7937e2eSIntel 
2607d7937e2eSIntel 	nb_lcores = rte_lcore_count();
2608d7937e2eSIntel 
2609d7937e2eSIntel 	/* initialize all ports */
26108728ccf3SThomas Monjalon 	RTE_ETH_FOREACH_DEV(portid) {
261140df1d7aSShahaf Shuler 		struct rte_eth_conf local_port_conf = port_conf;
2612f06493adSAnatoly Burakov 		/* not all app modes need interrupts */
2613e0194febSAnatoly Burakov 		bool need_intr = app_mode == APP_MODE_LEGACY ||
2614e0194febSAnatoly Burakov 				app_mode == APP_MODE_INTERRUPT;
261540df1d7aSShahaf Shuler 
2616d7937e2eSIntel 		/* skip ports that are not enabled */
2617d7937e2eSIntel 		if ((enabled_port_mask & (1 << portid)) == 0) {
2618d7937e2eSIntel 			printf("\nSkipping disabled port %d\n", portid);
2619d7937e2eSIntel 			continue;
2620d7937e2eSIntel 		}
2621d7937e2eSIntel 
2622d7937e2eSIntel 		/* init port */
2623d7937e2eSIntel 		printf("Initializing port %d ... ", portid );
2624d7937e2eSIntel 		fflush(stdout);
2625d7937e2eSIntel 
2626089e5ed7SIvan Ilchenko 		ret = rte_eth_dev_info_get(portid, &dev_info);
2627089e5ed7SIvan Ilchenko 		if (ret != 0)
2628089e5ed7SIvan Ilchenko 			rte_exit(EXIT_FAILURE,
2629089e5ed7SIvan Ilchenko 				"Error during getting device (port %u) info: %s\n",
2630089e5ed7SIvan Ilchenko 				portid, strerror(-ret));
2631089e5ed7SIvan Ilchenko 
2632aee3bc79SCunming Liang 		dev_rxq_num = dev_info.max_rx_queues;
2633aee3bc79SCunming Liang 		dev_txq_num = dev_info.max_tx_queues;
2634aee3bc79SCunming Liang 
2635d7937e2eSIntel 		nb_rx_queue = get_port_n_rx_queues(portid);
2636aee3bc79SCunming Liang 		if (nb_rx_queue > dev_rxq_num)
2637aee3bc79SCunming Liang 			rte_exit(EXIT_FAILURE,
2638aee3bc79SCunming Liang 				"Cannot configure not existed rxq: "
2639aee3bc79SCunming Liang 				"port=%d\n", portid);
2640aee3bc79SCunming Liang 
2641d7937e2eSIntel 		n_tx_queue = nb_lcores;
2642aee3bc79SCunming Liang 		if (n_tx_queue > dev_txq_num)
2643aee3bc79SCunming Liang 			n_tx_queue = dev_txq_num;
2644d7937e2eSIntel 		printf("Creating queues: nb_rxq=%d nb_txq=%u... ",
2645d7937e2eSIntel 			nb_rx_queue, (unsigned)n_tx_queue );
2646ddc554adSJingjing Wu 		/* If number of Rx queue is 0, no need to enable Rx interrupt */
2647ddc554adSJingjing Wu 		if (nb_rx_queue == 0)
2648f06493adSAnatoly Burakov 			need_intr = false;
2649f06493adSAnatoly Burakov 
2650f06493adSAnatoly Burakov 		if (need_intr)
2651f06493adSAnatoly Burakov 			local_port_conf.intr_conf.rxq = 1;
2652089e5ed7SIvan Ilchenko 
2653089e5ed7SIvan Ilchenko 		ret = rte_eth_dev_info_get(portid, &dev_info);
2654089e5ed7SIvan Ilchenko 		if (ret != 0)
2655089e5ed7SIvan Ilchenko 			rte_exit(EXIT_FAILURE,
2656089e5ed7SIvan Ilchenko 				"Error during getting device (port %u) info: %s\n",
2657089e5ed7SIvan Ilchenko 				portid, strerror(-ret));
2658089e5ed7SIvan Ilchenko 
26591bb4a528SFerruh Yigit 		ret = config_port_max_pkt_len(&local_port_conf, &dev_info);
26601bb4a528SFerruh Yigit 		if (ret != 0)
26611bb4a528SFerruh Yigit 			rte_exit(EXIT_FAILURE,
26621bb4a528SFerruh Yigit 				"Invalid max packet length: %u (port %u)\n",
26631bb4a528SFerruh Yigit 				max_pkt_len, portid);
26641bb4a528SFerruh Yigit 
2665295968d1SFerruh Yigit 		if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
266640df1d7aSShahaf Shuler 			local_port_conf.txmode.offloads |=
2667295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
26684f5701f2SFerruh Yigit 
26694f5701f2SFerruh Yigit 		local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
26704f5701f2SFerruh Yigit 			dev_info.flow_type_rss_offloads;
26714f5701f2SFerruh Yigit 		if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
26724f5701f2SFerruh Yigit 				port_conf.rx_adv_conf.rss_conf.rss_hf) {
26734f5701f2SFerruh Yigit 			printf("Port %u modified RSS hash function based on hardware support,"
26744f5701f2SFerruh Yigit 				"requested:%#"PRIx64" configured:%#"PRIx64"\n",
26754f5701f2SFerruh Yigit 				portid,
26764f5701f2SFerruh Yigit 				port_conf.rx_adv_conf.rss_conf.rss_hf,
26774f5701f2SFerruh Yigit 				local_port_conf.rx_adv_conf.rss_conf.rss_hf);
26784f5701f2SFerruh Yigit 		}
26794f5701f2SFerruh Yigit 
2680f0b00d98SMiao Li 		if (local_port_conf.rx_adv_conf.rss_conf.rss_hf == 0)
2681f0b00d98SMiao Li 			local_port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE;
2682f0b00d98SMiao Li 		local_port_conf.rxmode.offloads &= dev_info.rx_offload_capa;
2683f0b00d98SMiao Li 		port_conf.rxmode.offloads = local_port_conf.rxmode.offloads;
2684f0b00d98SMiao Li 
2685d7937e2eSIntel 		ret = rte_eth_dev_configure(portid, nb_rx_queue,
268640df1d7aSShahaf Shuler 					(uint16_t)n_tx_queue, &local_port_conf);
2687d7937e2eSIntel 		if (ret < 0)
2688d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "Cannot configure device: "
2689d7937e2eSIntel 					"err=%d, port=%d\n", ret, portid);
2690d7937e2eSIntel 
269160efb44fSRoman Zhukov 		ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
269260efb44fSRoman Zhukov 						       &nb_txd);
269360efb44fSRoman Zhukov 		if (ret < 0)
269460efb44fSRoman Zhukov 			rte_exit(EXIT_FAILURE,
269560efb44fSRoman Zhukov 				 "Cannot adjust number of descriptors: err=%d, port=%d\n",
269660efb44fSRoman Zhukov 				 ret, portid);
269760efb44fSRoman Zhukov 
269870febdcfSIgor Romanov 		ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
269970febdcfSIgor Romanov 		if (ret < 0)
270070febdcfSIgor Romanov 			rte_exit(EXIT_FAILURE,
270170febdcfSIgor Romanov 				 "Cannot get MAC address: err=%d, port=%d\n",
270270febdcfSIgor Romanov 				 ret, portid);
270370febdcfSIgor Romanov 
2704d7937e2eSIntel 		print_ethaddr(" Address:", &ports_eth_addr[portid]);
2705d7937e2eSIntel 		printf(", ");
2706d7937e2eSIntel 
2707d7937e2eSIntel 		/* init memory */
2708d7937e2eSIntel 		ret = init_mem(NB_MBUF);
2709d7937e2eSIntel 		if (ret < 0)
2710d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "init_mem failed\n");
2711d7937e2eSIntel 
2712e2366e74STomasz Kulasek 		for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2713e2366e74STomasz Kulasek 			if (rte_lcore_is_enabled(lcore_id) == 0)
2714e2366e74STomasz Kulasek 				continue;
2715e2366e74STomasz Kulasek 
2716e2366e74STomasz Kulasek 			/* Initialize TX buffers */
2717e2366e74STomasz Kulasek 			qconf = &lcore_conf[lcore_id];
2718e2366e74STomasz Kulasek 			qconf->tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
2719e2366e74STomasz Kulasek 				RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
2720e2366e74STomasz Kulasek 				rte_eth_dev_socket_id(portid));
2721e2366e74STomasz Kulasek 			if (qconf->tx_buffer[portid] == NULL)
2722e2366e74STomasz Kulasek 				rte_exit(EXIT_FAILURE, "Can't allocate tx buffer for port %u\n",
2723f8244c63SZhiyong Yang 						 portid);
2724e2366e74STomasz Kulasek 
2725e2366e74STomasz Kulasek 			rte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST);
2726e2366e74STomasz Kulasek 		}
2727e2366e74STomasz Kulasek 
2728d7937e2eSIntel 		/* init one TX queue per couple (lcore,port) */
2729d7937e2eSIntel 		queueid = 0;
2730d7937e2eSIntel 		for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2731d7937e2eSIntel 			if (rte_lcore_is_enabled(lcore_id) == 0)
2732d7937e2eSIntel 				continue;
2733d7937e2eSIntel 
2734aee3bc79SCunming Liang 			if (queueid >= dev_txq_num)
2735aee3bc79SCunming Liang 				continue;
2736aee3bc79SCunming Liang 
2737d7937e2eSIntel 			if (numa_on)
2738d7937e2eSIntel 				socketid = \
2739d7937e2eSIntel 				(uint8_t)rte_lcore_to_socket_id(lcore_id);
2740d7937e2eSIntel 			else
2741d7937e2eSIntel 				socketid = 0;
2742d7937e2eSIntel 
2743d7937e2eSIntel 			printf("txq=%u,%d,%d ", lcore_id, queueid, socketid);
2744d7937e2eSIntel 			fflush(stdout);
274581f7ecd9SPablo de Lara 
274681f7ecd9SPablo de Lara 			txconf = &dev_info.default_txconf;
274740df1d7aSShahaf Shuler 			txconf->offloads = local_port_conf.txmode.offloads;
2748d7937e2eSIntel 			ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
274981f7ecd9SPablo de Lara 						     socketid, txconf);
2750d7937e2eSIntel 			if (ret < 0)
2751d7937e2eSIntel 				rte_exit(EXIT_FAILURE,
2752d7937e2eSIntel 					"rte_eth_tx_queue_setup: err=%d, "
2753d7937e2eSIntel 						"port=%d\n", ret, portid);
2754d7937e2eSIntel 
2755d7937e2eSIntel 			qconf = &lcore_conf[lcore_id];
2756d7937e2eSIntel 			qconf->tx_queue_id[portid] = queueid;
2757d7937e2eSIntel 			queueid++;
2758e2366e74STomasz Kulasek 
2759e2366e74STomasz Kulasek 			qconf->tx_port_id[qconf->n_tx_port] = portid;
2760dd1c68faSTomasz Kulasek 			qconf->n_tx_port++;
2761d7937e2eSIntel 		}
2762d7937e2eSIntel 		printf("\n");
2763d7937e2eSIntel 	}
2764d7937e2eSIntel 
2765d7937e2eSIntel 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
2766d7937e2eSIntel 		if (rte_lcore_is_enabled(lcore_id) == 0)
2767d7937e2eSIntel 			continue;
2768d7937e2eSIntel 
2769609e7984SReshma Pattan 		if (app_mode == APP_MODE_LEGACY) {
2770d7937e2eSIntel 			/* init timer structures for each enabled lcore */
2771d7937e2eSIntel 			rte_timer_init(&power_timers[lcore_id]);
2772d7937e2eSIntel 			hz = rte_get_timer_hz();
2773d7937e2eSIntel 			rte_timer_reset(&power_timers[lcore_id],
2774a137d012SLiang Ma 					hz/TIMER_NUMBER_PER_SECOND,
2775a137d012SLiang Ma 					SINGLE, lcore_id,
2776d7937e2eSIntel 					power_timer_cb, NULL);
2777a137d012SLiang Ma 		}
2778d7937e2eSIntel 		qconf = &lcore_conf[lcore_id];
2779d7937e2eSIntel 		printf("\nInitializing rx queues on lcore %u ... ", lcore_id );
2780d7937e2eSIntel 		fflush(stdout);
278126fe454eSLiang Ma 
2782d7937e2eSIntel 		/* init RX queues */
2783d7937e2eSIntel 		for(queue = 0; queue < qconf->n_rx_queue; ++queue) {
278440df1d7aSShahaf Shuler 			struct rte_eth_rxconf rxq_conf;
278540df1d7aSShahaf Shuler 
2786d7937e2eSIntel 			portid = qconf->rx_queue_list[queue].port_id;
2787d7937e2eSIntel 			queueid = qconf->rx_queue_list[queue].queue_id;
2788d7937e2eSIntel 
2789d7937e2eSIntel 			if (numa_on)
2790d7937e2eSIntel 				socketid = \
2791d7937e2eSIntel 				(uint8_t)rte_lcore_to_socket_id(lcore_id);
2792d7937e2eSIntel 			else
2793d7937e2eSIntel 				socketid = 0;
2794d7937e2eSIntel 
2795d7937e2eSIntel 			printf("rxq=%d,%d,%d ", portid, queueid, socketid);
2796d7937e2eSIntel 			fflush(stdout);
2797d7937e2eSIntel 
2798089e5ed7SIvan Ilchenko 			ret = rte_eth_dev_info_get(portid, &dev_info);
2799089e5ed7SIvan Ilchenko 			if (ret != 0)
2800089e5ed7SIvan Ilchenko 				rte_exit(EXIT_FAILURE,
2801089e5ed7SIvan Ilchenko 					"Error during getting device (port %u) info: %s\n",
2802089e5ed7SIvan Ilchenko 					portid, strerror(-ret));
2803089e5ed7SIvan Ilchenko 
280440df1d7aSShahaf Shuler 			rxq_conf = dev_info.default_rxconf;
28055c5c1f99SMarcin Zapolski 			rxq_conf.offloads = port_conf.rxmode.offloads;
2806d7937e2eSIntel 			ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
280740df1d7aSShahaf Shuler 				socketid, &rxq_conf,
280881f7ecd9SPablo de Lara 				pktmbuf_pool[socketid]);
2809d7937e2eSIntel 			if (ret < 0)
2810d7937e2eSIntel 				rte_exit(EXIT_FAILURE,
2811d7937e2eSIntel 					"rte_eth_rx_queue_setup: err=%d, "
2812d7937e2eSIntel 						"port=%d\n", ret, portid);
281382bea466SJianfeng Tan 
281482bea466SJianfeng Tan 			if (parse_ptype) {
281582bea466SJianfeng Tan 				if (add_cb_parse_ptype(portid, queueid) < 0)
281682bea466SJianfeng Tan 					rte_exit(EXIT_FAILURE,
281782bea466SJianfeng Tan 						 "Fail to add ptype cb\n");
28186184a022SGregory Etelson 			}
281926fe454eSLiang Ma 
2820a9ea6070SDavid Hunt 			if (app_mode == APP_MODE_PMD_MGMT && !baseline_enabled) {
282159f2853cSKevin Laatz 				/* Set power_pmd_mgmt configs passed by user */
282259f2853cSKevin Laatz 				rte_power_pmd_mgmt_set_emptypoll_max(max_empty_polls);
282359f2853cSKevin Laatz 				ret = rte_power_pmd_mgmt_set_pause_duration(pause_duration);
282459f2853cSKevin Laatz 				if (ret < 0)
282559f2853cSKevin Laatz 					rte_exit(EXIT_FAILURE,
282659f2853cSKevin Laatz 						"Error setting pause_duration: err=%d, lcore=%d\n",
282759f2853cSKevin Laatz 							ret, lcore_id);
282859f2853cSKevin Laatz 
282959f2853cSKevin Laatz 				ret = rte_power_pmd_mgmt_set_scaling_freq_min(lcore_id,
283059f2853cSKevin Laatz 						scale_freq_min);
283159f2853cSKevin Laatz 				if (ret < 0)
283259f2853cSKevin Laatz 					rte_exit(EXIT_FAILURE,
283359f2853cSKevin Laatz 						"Error setting scaling freq min: err=%d, lcore=%d\n",
283459f2853cSKevin Laatz 							ret, lcore_id);
283559f2853cSKevin Laatz 
283659f2853cSKevin Laatz 				ret = rte_power_pmd_mgmt_set_scaling_freq_max(lcore_id,
283759f2853cSKevin Laatz 						scale_freq_max);
283859f2853cSKevin Laatz 				if (ret < 0)
283959f2853cSKevin Laatz 					rte_exit(EXIT_FAILURE,
284059f2853cSKevin Laatz 						"Error setting scaling freq max: err=%d, lcore %d\n",
284159f2853cSKevin Laatz 							ret, lcore_id);
284259f2853cSKevin Laatz 
284326fe454eSLiang Ma 				ret = rte_power_ethdev_pmgmt_queue_enable(
284426fe454eSLiang Ma 						lcore_id, portid, queueid,
284526fe454eSLiang Ma 						pmgmt_type);
284626fe454eSLiang Ma 				if (ret < 0)
284726fe454eSLiang Ma 					rte_exit(EXIT_FAILURE,
284826fe454eSLiang Ma 						"rte_power_ethdev_pmgmt_queue_enable: err=%d, port=%d\n",
284926fe454eSLiang Ma 							ret, portid);
285026fe454eSLiang Ma 			}
2851d7937e2eSIntel 		}
2852d7937e2eSIntel 	}
28539a212dc0SConor Fogarty 	/* >8 End of power library initialization. */
2854d7937e2eSIntel 
2855d7937e2eSIntel 	printf("\n");
2856d7937e2eSIntel 
2857d7937e2eSIntel 	/* start ports */
28588728ccf3SThomas Monjalon 	RTE_ETH_FOREACH_DEV(portid) {
2859d7937e2eSIntel 		if ((enabled_port_mask & (1 << portid)) == 0) {
2860d7937e2eSIntel 			continue;
2861d7937e2eSIntel 		}
2862d7937e2eSIntel 		/* Start device */
2863d7937e2eSIntel 		ret = rte_eth_dev_start(portid);
2864d7937e2eSIntel 		if (ret < 0)
2865d7937e2eSIntel 			rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, "
2866d7937e2eSIntel 						"port=%d\n", ret, portid);
2867d7937e2eSIntel 		/*
2868d7937e2eSIntel 		 * If enabled, put device in promiscuous mode.
2869d7937e2eSIntel 		 * This allows IO forwarding mode to forward packets
2870d7937e2eSIntel 		 * to itself through 2 cross-connected  ports of the
2871d7937e2eSIntel 		 * target machine.
2872d7937e2eSIntel 		 */
2873f430bbceSIvan Ilchenko 		if (promiscuous_on) {
2874f430bbceSIvan Ilchenko 			ret = rte_eth_promiscuous_enable(portid);
2875f430bbceSIvan Ilchenko 			if (ret != 0)
2876f430bbceSIvan Ilchenko 				rte_exit(EXIT_FAILURE,
2877f430bbceSIvan Ilchenko 					"rte_eth_promiscuous_enable: err=%s, port=%u\n",
2878f430bbceSIvan Ilchenko 					rte_strerror(-ret), portid);
2879f430bbceSIvan Ilchenko 		}
2880aee3bc79SCunming Liang 		/* initialize spinlock for each port */
2881aee3bc79SCunming Liang 		rte_spinlock_init(&(locks[portid]));
28826184a022SGregory Etelson 
28836184a022SGregory Etelson 		if (!parse_ptype)
28846184a022SGregory Etelson 			if (!check_ptype(portid))
28856184a022SGregory Etelson 				rte_exit(EXIT_FAILURE,
28866184a022SGregory Etelson 					"PMD can not provide needed ptypes\n");
2887d7937e2eSIntel 	}
2888d7937e2eSIntel 
28898728ccf3SThomas Monjalon 	check_all_ports_link_status(enabled_port_mask);
2890d7937e2eSIntel 
2891d7937e2eSIntel 	/* launch per-lcore init on every lcore */
2892609e7984SReshma Pattan 	if (app_mode == APP_MODE_LEGACY) {
2893cb056611SStephen Hemminger 		rte_eal_mp_remote_launch(main_legacy_loop, NULL, CALL_MAIN);
28945b41ab35SAnatoly Burakov 	} else if (app_mode == APP_MODE_TELEMETRY) {
2895292472baSThomas Monjalon 		unsigned int i;
2896292472baSThomas Monjalon 
2897609e7984SReshma Pattan 		/* Init metrics library */
2898609e7984SReshma Pattan 		rte_metrics_init(rte_socket_id());
2899609e7984SReshma Pattan 		/** Register stats with metrics library */
2900a35919a1SCiara Power 		for (i = 0; i < NUM_TELSTATS; i++)
2901609e7984SReshma Pattan 			ptr_strings[i] = telstats_strings[i].name;
2902609e7984SReshma Pattan 
2903a35919a1SCiara Power 		ret = rte_metrics_reg_names(ptr_strings, NUM_TELSTATS);
2904609e7984SReshma Pattan 		if (ret >= 0)
2905609e7984SReshma Pattan 			telstats_index = ret;
2906609e7984SReshma Pattan 		else
2907609e7984SReshma Pattan 			rte_exit(EXIT_FAILURE, "failed to register metrics names");
2908609e7984SReshma Pattan 
2909cb056611SStephen Hemminger 		RTE_LCORE_FOREACH_WORKER(lcore_id) {
2910609e7984SReshma Pattan 			rte_spinlock_init(&stats[lcore_id].telemetry_lock);
2911609e7984SReshma Pattan 		}
2912609e7984SReshma Pattan 		rte_timer_init(&telemetry_timer);
2913a35919a1SCiara Power 		rte_telemetry_register_cmd("/l3fwd-power/stats",
2914a35919a1SCiara Power 				handle_app_stats,
2915a35919a1SCiara Power 				"Returns global power stats. Parameters: None");
2916609e7984SReshma Pattan 		rte_eal_mp_remote_launch(main_telemetry_loop, NULL,
2917cb056611SStephen Hemminger 						SKIP_MAIN);
2918e0194febSAnatoly Burakov 	} else if (app_mode == APP_MODE_INTERRUPT) {
2919cb056611SStephen Hemminger 		rte_eal_mp_remote_launch(main_intr_loop, NULL, CALL_MAIN);
292026fe454eSLiang Ma 	} else if (app_mode == APP_MODE_PMD_MGMT) {
292126fe454eSLiang Ma 		/* reuse telemetry loop for PMD power management mode */
292226fe454eSLiang Ma 		rte_eal_mp_remote_launch(main_telemetry_loop, NULL, CALL_MAIN);
2923a137d012SLiang Ma 	}
2924a137d012SLiang Ma 
29259c75ff42SDavid Hunt 	if (app_mode == APP_MODE_TELEMETRY)
2926a137d012SLiang Ma 		launch_timer(rte_lcore_id());
2927a137d012SLiang Ma 
2928cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
2929d7937e2eSIntel 		if (rte_eal_wait_lcore(lcore_id) < 0)
2930d7937e2eSIntel 			return -1;
2931d7937e2eSIntel 	}
2932d7937e2eSIntel 
293326fe454eSLiang Ma 	if (app_mode == APP_MODE_PMD_MGMT) {
293426fe454eSLiang Ma 		for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
293526fe454eSLiang Ma 			if (rte_lcore_is_enabled(lcore_id) == 0)
293626fe454eSLiang Ma 				continue;
293726fe454eSLiang Ma 			qconf = &lcore_conf[lcore_id];
293826fe454eSLiang Ma 			for (queue = 0; queue < qconf->n_rx_queue; ++queue) {
293926fe454eSLiang Ma 				portid = qconf->rx_queue_list[queue].port_id;
294026fe454eSLiang Ma 				queueid = qconf->rx_queue_list[queue].queue_id;
294126fe454eSLiang Ma 
294226fe454eSLiang Ma 				rte_power_ethdev_pmgmt_queue_disable(lcore_id,
294326fe454eSLiang Ma 						portid, queueid);
294426fe454eSLiang Ma 			}
294526fe454eSLiang Ma 		}
294626fe454eSLiang Ma 	}
294726fe454eSLiang Ma 
2948613ce669SAnatoly Burakov 	RTE_ETH_FOREACH_DEV(portid)
2949613ce669SAnatoly Burakov 	{
2950613ce669SAnatoly Burakov 		if ((enabled_port_mask & (1 << portid)) == 0)
2951613ce669SAnatoly Burakov 			continue;
2952613ce669SAnatoly Burakov 
2953b55efbabSIvan Ilchenko 		ret = rte_eth_dev_stop(portid);
2954b55efbabSIvan Ilchenko 		if (ret != 0)
2955b55efbabSIvan Ilchenko 			RTE_LOG(ERR, L3FWD_POWER, "rte_eth_dev_stop: err=%d, port=%u\n",
2956b55efbabSIvan Ilchenko 				ret, portid);
2957b55efbabSIvan Ilchenko 
2958613ce669SAnatoly Burakov 		rte_eth_dev_close(portid);
2959613ce669SAnatoly Burakov 	}
2960613ce669SAnatoly Burakov 
29619c75ff42SDavid Hunt 	if ((app_mode == APP_MODE_LEGACY) && deinit_power_library())
2962613ce669SAnatoly Burakov 		rte_exit(EXIT_FAILURE, "deinit_power_library failed\n");
2963613ce669SAnatoly Burakov 
2964613ce669SAnatoly Burakov 	if (rte_eal_cleanup() < 0)
2965613ce669SAnatoly Burakov 		RTE_LOG(ERR, L3FWD_POWER, "EAL cleanup failed\n");
2966613ce669SAnatoly Burakov 
2967d7937e2eSIntel 	return 0;
2968d7937e2eSIntel }
2969