xref: /dpdk/examples/qos_sched/args.c (revision 4b978938168b219346775ff877ac31649a36cba7)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3de3cfa2cSIntel  */
4de3cfa2cSIntel 
5de3cfa2cSIntel #include <stdio.h>
6de3cfa2cSIntel #include <string.h>
7de3cfa2cSIntel #include <stdlib.h>
8de3cfa2cSIntel #include <stdint.h>
9de3cfa2cSIntel #include <locale.h>
10de3cfa2cSIntel #include <unistd.h>
11de3cfa2cSIntel #include <limits.h>
12de3cfa2cSIntel #include <getopt.h>
13de3cfa2cSIntel 
14de3cfa2cSIntel #include <rte_log.h>
15de3cfa2cSIntel #include <rte_eal.h>
16de3cfa2cSIntel #include <rte_lcore.h>
17de3cfa2cSIntel #include <rte_string_fns.h>
18de3cfa2cSIntel 
19de3cfa2cSIntel #include "main.h"
20de3cfa2cSIntel 
21de3cfa2cSIntel #define APP_NAME "qos_sched"
22de3cfa2cSIntel #define MAX_OPT_VALUES 8
23de3cfa2cSIntel #define SYS_CPU_DIR "/sys/devices/system/cpu/cpu%u/topology/"
24de3cfa2cSIntel 
25cb056611SStephen Hemminger static uint32_t app_main_core = 1;
26de3cfa2cSIntel static uint32_t app_numa_mask;
27de3cfa2cSIntel static uint64_t app_used_port_mask = 0;
28de3cfa2cSIntel static uint64_t app_used_rx_port_mask = 0;
29de3cfa2cSIntel static uint64_t app_used_tx_port_mask = 0;
30de3cfa2cSIntel 
31de3cfa2cSIntel 
32de3cfa2cSIntel static const char usage[] =
33de3cfa2cSIntel 	"                                                                               \n"
34de3cfa2cSIntel 	"    %s <APP PARAMS>                                                            \n"
35de3cfa2cSIntel 	"                                                                               \n"
36de3cfa2cSIntel 	"Application mandatory parameters:                                              \n"
37de3cfa2cSIntel 	"    --pfc \"RX PORT, TX PORT, RX LCORE, WT LCORE\" : Packet flow configuration \n"
38de3cfa2cSIntel 	"           multiple pfc can be configured in command line                      \n"
39de3cfa2cSIntel 	"                                                                               \n"
40de3cfa2cSIntel 	"Application optional parameters:                                               \n"
41fc48d8a5SIbtisam Tariq 	"    -i      : run in interactive mode (default value is %u)                    \n"
42cb056611SStephen Hemminger 	"    --mnc I : main core index (default value is %u)                            \n"
43de3cfa2cSIntel 	"    --rsz \"A, B, C\" :   Ring sizes                                           \n"
44de3cfa2cSIntel 	"           A = Size (in number of buffer descriptors) of each of the NIC RX    \n"
45de3cfa2cSIntel 	"               rings read by the I/O RX lcores (default value is %u)           \n"
46de3cfa2cSIntel 	"           B = Size (in number of elements) of each of the SW rings used by the\n"
47de3cfa2cSIntel 	"               I/O RX lcores to send packets to worker lcores (default value is\n"
48de3cfa2cSIntel 	"               %u)                                                             \n"
49de3cfa2cSIntel 	"           C = Size (in number of buffer descriptors) of each of the NIC TX    \n"
50de3cfa2cSIntel 	"               rings written by worker lcores (default value is %u)            \n"
51de3cfa2cSIntel 	"    --bsz \"A, B, C, D\": Burst sizes                                          \n"
52de3cfa2cSIntel 	"           A = I/O RX lcore read burst size from NIC RX (default value is %u)  \n"
53de3cfa2cSIntel 	"           B = I/O RX lcore write burst size to output SW rings,               \n"
54de3cfa2cSIntel 	"               Worker lcore read burst size from input SW rings,               \n"
55de3cfa2cSIntel 	"               QoS enqueue size (default value is %u)                          \n"
56de3cfa2cSIntel 	"           C = QoS dequeue size (default value is %u)                          \n"
57de3cfa2cSIntel 	"           D = Worker lcore write burst size to NIC TX (default value is %u)   \n"
58e93b24a3SIntel 	"    --msz M : Mempool size (in number of mbufs) for each pfc (default %u)      \n"
59de3cfa2cSIntel 	"    --rth \"A, B, C\" :   RX queue threshold parameters                        \n"
60de3cfa2cSIntel 	"           A = RX prefetch threshold (default value is %u)                     \n"
61de3cfa2cSIntel 	"           B = RX host threshold (default value is %u)                         \n"
62de3cfa2cSIntel 	"           C = RX write-back threshold (default value is %u)                   \n"
63de3cfa2cSIntel 	"    --tth \"A, B, C\" :   TX queue threshold parameters                        \n"
64de3cfa2cSIntel 	"           A = TX prefetch threshold (default value is %u)                     \n"
65de3cfa2cSIntel 	"           B = TX host threshold (default value is %u)                         \n"
66de3cfa2cSIntel 	"           C = TX write-back threshold (default value is %u)                   \n"
67de3cfa2cSIntel 	"    --cfg FILE : profile configuration to load                                 \n"
68de3cfa2cSIntel ;
69de3cfa2cSIntel 
70de3cfa2cSIntel /* display usage */
71de3cfa2cSIntel static void
72de3cfa2cSIntel app_usage(const char *prgname)
73de3cfa2cSIntel {
74cb056611SStephen Hemminger 	printf(usage, prgname, APP_INTERACTIVE_DEFAULT, app_main_core,
75de3cfa2cSIntel 		APP_RX_DESC_DEFAULT, APP_RING_SIZE, APP_TX_DESC_DEFAULT,
76e93b24a3SIntel 		MAX_PKT_RX_BURST, PKT_ENQUEUE, PKT_DEQUEUE,
77e93b24a3SIntel 		MAX_PKT_TX_BURST, NB_MBUF,
78de3cfa2cSIntel 		RX_PTHRESH, RX_HTHRESH, RX_WTHRESH,
79de3cfa2cSIntel 		TX_PTHRESH, TX_HTHRESH, TX_WTHRESH
80de3cfa2cSIntel 		);
81de3cfa2cSIntel }
82de3cfa2cSIntel 
83de3cfa2cSIntel 
84de3cfa2cSIntel 
85de3cfa2cSIntel /* returns:
86de3cfa2cSIntel 	 number of values parsed
87de3cfa2cSIntel 	-1 in case of error
88de3cfa2cSIntel */
89de3cfa2cSIntel static int
90de3cfa2cSIntel app_parse_opt_vals(const char *conf_str, char separator, uint32_t n_vals, uint32_t *opt_vals)
91de3cfa2cSIntel {
92de3cfa2cSIntel 	char *string;
93cb923408SSlawomir Mrozowicz 	int i, n_tokens;
94de3cfa2cSIntel 	char *tokens[MAX_OPT_VALUES];
95de3cfa2cSIntel 
96de3cfa2cSIntel 	if (conf_str == NULL || opt_vals == NULL || n_vals == 0 || n_vals > MAX_OPT_VALUES)
97de3cfa2cSIntel 		return -1;
98de3cfa2cSIntel 
99de3cfa2cSIntel 	/* duplicate configuration string before splitting it to tokens */
100de3cfa2cSIntel 	string = strdup(conf_str);
101de3cfa2cSIntel 	if (string == NULL)
102de3cfa2cSIntel 		return -1;
103de3cfa2cSIntel 
104de3cfa2cSIntel 	n_tokens = rte_strsplit(string, strnlen(string, 32), tokens, n_vals, separator);
105de3cfa2cSIntel 
106db8aee15SChengwen Feng 	if (n_tokens > MAX_OPT_VALUES) {
107db8aee15SChengwen Feng 		free(string);
108035b6a4fSSlawomir Mrozowicz 		return -1;
109db8aee15SChengwen Feng 	}
110035b6a4fSSlawomir Mrozowicz 
111035b6a4fSSlawomir Mrozowicz 	for (i = 0; i < n_tokens; i++)
112de3cfa2cSIntel 		opt_vals[i] = (uint32_t)atol(tokens[i]);
113de3cfa2cSIntel 
114de3cfa2cSIntel 	free(string);
115de3cfa2cSIntel 
116de3cfa2cSIntel 	return n_tokens;
117de3cfa2cSIntel }
118de3cfa2cSIntel 
119de3cfa2cSIntel static int
120de3cfa2cSIntel app_parse_ring_conf(const char *conf_str)
121de3cfa2cSIntel {
122de3cfa2cSIntel 	int ret;
123de3cfa2cSIntel 	uint32_t vals[3];
124de3cfa2cSIntel 
125de3cfa2cSIntel 	ret = app_parse_opt_vals(conf_str, ',', 3, vals);
126de3cfa2cSIntel 	if (ret != 3)
127de3cfa2cSIntel 		return ret;
128de3cfa2cSIntel 
129de3cfa2cSIntel 	ring_conf.rx_size = vals[0];
130de3cfa2cSIntel 	ring_conf.ring_size = vals[1];
131de3cfa2cSIntel 	ring_conf.tx_size = vals[2];
132de3cfa2cSIntel 
133de3cfa2cSIntel 	return 0;
134de3cfa2cSIntel }
135de3cfa2cSIntel 
136de3cfa2cSIntel static int
137de3cfa2cSIntel app_parse_rth_conf(const char *conf_str)
138de3cfa2cSIntel {
139de3cfa2cSIntel 	int ret;
140de3cfa2cSIntel 	uint32_t vals[3];
141de3cfa2cSIntel 
142de3cfa2cSIntel 	ret = app_parse_opt_vals(conf_str, ',', 3, vals);
143de3cfa2cSIntel 	if (ret != 3)
144de3cfa2cSIntel 		return ret;
145de3cfa2cSIntel 
146de3cfa2cSIntel 	rx_thresh.pthresh = (uint8_t)vals[0];
147de3cfa2cSIntel 	rx_thresh.hthresh = (uint8_t)vals[1];
148de3cfa2cSIntel 	rx_thresh.wthresh = (uint8_t)vals[2];
149de3cfa2cSIntel 
150de3cfa2cSIntel 	return 0;
151de3cfa2cSIntel }
152de3cfa2cSIntel 
153de3cfa2cSIntel static int
154de3cfa2cSIntel app_parse_tth_conf(const char *conf_str)
155de3cfa2cSIntel {
156de3cfa2cSIntel 	int ret;
157de3cfa2cSIntel 	uint32_t vals[3];
158de3cfa2cSIntel 
159de3cfa2cSIntel 	ret = app_parse_opt_vals(conf_str, ',', 3, vals);
160de3cfa2cSIntel 	if (ret != 3)
161de3cfa2cSIntel 		return ret;
162de3cfa2cSIntel 
163de3cfa2cSIntel 	tx_thresh.pthresh = (uint8_t)vals[0];
164de3cfa2cSIntel 	tx_thresh.hthresh = (uint8_t)vals[1];
165de3cfa2cSIntel 	tx_thresh.wthresh = (uint8_t)vals[2];
166de3cfa2cSIntel 
167de3cfa2cSIntel 	return 0;
168de3cfa2cSIntel }
169de3cfa2cSIntel 
170de3cfa2cSIntel static int
171de3cfa2cSIntel app_parse_flow_conf(const char *conf_str)
172de3cfa2cSIntel {
173de3cfa2cSIntel 	int ret;
174de3cfa2cSIntel 	uint32_t vals[5];
175de3cfa2cSIntel 	struct flow_conf *pconf;
176de3cfa2cSIntel 	uint64_t mask;
177de3cfa2cSIntel 
17835f30466SJerin Jacob 	memset(vals, 0, sizeof(vals));
179de3cfa2cSIntel 	ret = app_parse_opt_vals(conf_str, ',', 6, vals);
180de3cfa2cSIntel 	if (ret < 4 || ret > 5)
181de3cfa2cSIntel 		return ret;
182de3cfa2cSIntel 
183de3cfa2cSIntel 	pconf = &qos_conf[nb_pfc];
184de3cfa2cSIntel 
185f8244c63SZhiyong Yang 	pconf->rx_port = vals[0];
186f8244c63SZhiyong Yang 	pconf->tx_port = vals[1];
187*4b978938SSivaprasad Tummala 	pconf->rx_core = vals[2];
188*4b978938SSivaprasad Tummala 	pconf->wt_core = vals[3];
189de3cfa2cSIntel 	if (ret == 5)
190*4b978938SSivaprasad Tummala 		pconf->tx_core = vals[4];
191de3cfa2cSIntel 	else
192de3cfa2cSIntel 		pconf->tx_core = pconf->wt_core;
193de3cfa2cSIntel 
194de3cfa2cSIntel 	if (pconf->rx_core == pconf->wt_core) {
195de3cfa2cSIntel 		RTE_LOG(ERR, APP, "pfc %u: rx thread and worker thread cannot share same core\n", nb_pfc);
196de3cfa2cSIntel 		return -1;
197de3cfa2cSIntel 	}
198de3cfa2cSIntel 
199de3cfa2cSIntel 	if (pconf->rx_port >= RTE_MAX_ETHPORTS) {
200f8244c63SZhiyong Yang 		RTE_LOG(ERR, APP, "pfc %u: invalid rx port %"PRIu16" index\n",
201e8ed6c78SBruce Richardson 				nb_pfc, pconf->rx_port);
202de3cfa2cSIntel 		return -1;
203de3cfa2cSIntel 	}
204de3cfa2cSIntel 	if (pconf->tx_port >= RTE_MAX_ETHPORTS) {
205f8244c63SZhiyong Yang 		RTE_LOG(ERR, APP, "pfc %u: invalid tx port %"PRIu16" index\n",
206f2c41f26SSlawomir Mrozowicz 				nb_pfc, pconf->tx_port);
207de3cfa2cSIntel 		return -1;
208de3cfa2cSIntel 	}
209de3cfa2cSIntel 
210de3cfa2cSIntel 	mask = 1lu << pconf->rx_port;
211de3cfa2cSIntel 	if (app_used_rx_port_mask & mask) {
212f8244c63SZhiyong Yang 		RTE_LOG(ERR, APP, "pfc %u: rx port %"PRIu16" is used already\n",
213e8ed6c78SBruce Richardson 				nb_pfc, pconf->rx_port);
214de3cfa2cSIntel 		return -1;
215de3cfa2cSIntel 	}
216de3cfa2cSIntel 	app_used_rx_port_mask |= mask;
217de3cfa2cSIntel 	app_used_port_mask |= mask;
218de3cfa2cSIntel 
219de3cfa2cSIntel 	mask = 1lu << pconf->tx_port;
220de3cfa2cSIntel 	if (app_used_tx_port_mask & mask) {
221f8244c63SZhiyong Yang 		RTE_LOG(ERR, APP, "pfc %u: port %"PRIu16" is used already\n",
222e8ed6c78SBruce Richardson 				nb_pfc, pconf->tx_port);
223de3cfa2cSIntel 		return -1;
224de3cfa2cSIntel 	}
225de3cfa2cSIntel 	app_used_tx_port_mask |= mask;
226de3cfa2cSIntel 	app_used_port_mask |= mask;
227de3cfa2cSIntel 
228de3cfa2cSIntel 	nb_pfc++;
229de3cfa2cSIntel 
230de3cfa2cSIntel 	return 0;
231de3cfa2cSIntel }
232de3cfa2cSIntel 
233de3cfa2cSIntel static int
234de3cfa2cSIntel app_parse_burst_conf(const char *conf_str)
235de3cfa2cSIntel {
236de3cfa2cSIntel 	int ret;
237de3cfa2cSIntel 	uint32_t vals[4];
238de3cfa2cSIntel 
239de3cfa2cSIntel 	ret = app_parse_opt_vals(conf_str, ',', 4, vals);
240de3cfa2cSIntel 	if (ret != 4)
241de3cfa2cSIntel 		return ret;
242de3cfa2cSIntel 
243de3cfa2cSIntel 	burst_conf.rx_burst    = (uint16_t)vals[0];
244de3cfa2cSIntel 	burst_conf.ring_burst  = (uint16_t)vals[1];
245de3cfa2cSIntel 	burst_conf.qos_dequeue = (uint16_t)vals[2];
246de3cfa2cSIntel 	burst_conf.tx_burst    = (uint16_t)vals[3];
247de3cfa2cSIntel 
248de3cfa2cSIntel 	return 0;
249de3cfa2cSIntel }
250de3cfa2cSIntel 
251a12daff4SIbtisam Tariq enum {
252a12daff4SIbtisam Tariq #define OPT_PFC "pfc"
253a12daff4SIbtisam Tariq 	OPT_PFC_NUM = 256,
254a12daff4SIbtisam Tariq #define OPT_MNC "mnc"
255a12daff4SIbtisam Tariq 	OPT_MNC_NUM,
256a12daff4SIbtisam Tariq #define OPT_RSZ "rsz"
257a12daff4SIbtisam Tariq 	OPT_RSZ_NUM,
258a12daff4SIbtisam Tariq #define OPT_BSZ "bsz"
259a12daff4SIbtisam Tariq 	OPT_BSZ_NUM,
260a12daff4SIbtisam Tariq #define OPT_MSZ "msz"
261a12daff4SIbtisam Tariq 	OPT_MSZ_NUM,
262a12daff4SIbtisam Tariq #define OPT_RTH "rth"
263a12daff4SIbtisam Tariq 	OPT_RTH_NUM,
264a12daff4SIbtisam Tariq #define OPT_TTH "tth"
265a12daff4SIbtisam Tariq 	OPT_TTH_NUM,
266a12daff4SIbtisam Tariq #define OPT_CFG "cfg"
267a12daff4SIbtisam Tariq 	OPT_CFG_NUM,
268a12daff4SIbtisam Tariq };
269a12daff4SIbtisam Tariq 
270de3cfa2cSIntel /*
271de3cfa2cSIntel  * Parses the argument given in the command line of the application,
272de3cfa2cSIntel  * calculates mask for used cores and initializes EAL with calculated core mask
273de3cfa2cSIntel  */
274de3cfa2cSIntel int
275de3cfa2cSIntel app_parse_args(int argc, char **argv)
276de3cfa2cSIntel {
277de3cfa2cSIntel 	int opt, ret;
278de3cfa2cSIntel 	int option_index;
279de3cfa2cSIntel 	char *prgname = argv[0];
2804e43299dSBruce Richardson 	uint32_t i;
281de3cfa2cSIntel 
282de3cfa2cSIntel 	static struct option lgopts[] = {
283a12daff4SIbtisam Tariq 		{OPT_PFC, 1, NULL, OPT_PFC_NUM},
284a12daff4SIbtisam Tariq 		{OPT_MNC, 1, NULL, OPT_MNC_NUM},
285a12daff4SIbtisam Tariq 		{OPT_RSZ, 1, NULL, OPT_RSZ_NUM},
286a12daff4SIbtisam Tariq 		{OPT_BSZ, 1, NULL, OPT_BSZ_NUM},
287a12daff4SIbtisam Tariq 		{OPT_MSZ, 1, NULL, OPT_MSZ_NUM},
288a12daff4SIbtisam Tariq 		{OPT_RTH, 1, NULL, OPT_RTH_NUM},
289a12daff4SIbtisam Tariq 		{OPT_TTH, 1, NULL, OPT_TTH_NUM},
290a12daff4SIbtisam Tariq 		{OPT_CFG, 1, NULL, OPT_CFG_NUM},
291de3cfa2cSIntel 		{NULL,    0, 0,    0          }
292de3cfa2cSIntel 	};
293de3cfa2cSIntel 
294de3cfa2cSIntel 	/* initialize EAL first */
295de3cfa2cSIntel 	ret = rte_eal_init(argc, argv);
296de3cfa2cSIntel 	if (ret < 0)
297de3cfa2cSIntel 		return -1;
298de3cfa2cSIntel 
299de3cfa2cSIntel 	argc -= ret;
300de3cfa2cSIntel 	argv += ret;
301de3cfa2cSIntel 
302de3cfa2cSIntel 	/* set en_US locale to print big numbers with ',' */
303de3cfa2cSIntel 	setlocale(LC_NUMERIC, "en_US.utf-8");
304de3cfa2cSIntel 
305cfd5c971SIntel 	while ((opt = getopt_long(argc, argv, "i",
306de3cfa2cSIntel 		lgopts, &option_index)) != EOF) {
307de3cfa2cSIntel 
308de3cfa2cSIntel 			switch (opt) {
309cfd5c971SIntel 			case 'i':
310cfd5c971SIntel 				printf("Interactive-mode selected\n");
311cfd5c971SIntel 				interactive = 1;
312cfd5c971SIntel 				break;
313de3cfa2cSIntel 			/* long options */
314a12daff4SIbtisam Tariq 
315a12daff4SIbtisam Tariq 			case OPT_PFC_NUM:
316de3cfa2cSIntel 				ret = app_parse_flow_conf(optarg);
317de3cfa2cSIntel 				if (ret) {
318a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid pipe configuration %s\n",
319a12daff4SIbtisam Tariq 							optarg);
320de3cfa2cSIntel 					return -1;
321de3cfa2cSIntel 				}
322de3cfa2cSIntel 				break;
323a12daff4SIbtisam Tariq 
324a12daff4SIbtisam Tariq 			case OPT_MNC_NUM:
325cb056611SStephen Hemminger 				app_main_core = (uint32_t)atoi(optarg);
326de3cfa2cSIntel 				break;
327a12daff4SIbtisam Tariq 
328a12daff4SIbtisam Tariq 			case OPT_RSZ_NUM:
329de3cfa2cSIntel 				ret = app_parse_ring_conf(optarg);
330de3cfa2cSIntel 				if (ret) {
331a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid ring configuration %s\n",
332a12daff4SIbtisam Tariq 							optarg);
333de3cfa2cSIntel 					return -1;
334de3cfa2cSIntel 				}
335de3cfa2cSIntel 				break;
336a12daff4SIbtisam Tariq 
337a12daff4SIbtisam Tariq 			case OPT_BSZ_NUM:
338de3cfa2cSIntel 				ret = app_parse_burst_conf(optarg);
339de3cfa2cSIntel 				if (ret) {
340a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid burst configuration %s\n",
341a12daff4SIbtisam Tariq 							optarg);
342de3cfa2cSIntel 					return -1;
343de3cfa2cSIntel 				}
344de3cfa2cSIntel 				break;
345a12daff4SIbtisam Tariq 
346a12daff4SIbtisam Tariq 			case OPT_MSZ_NUM:
347e93b24a3SIntel 				mp_size = atoi(optarg);
348e93b24a3SIntel 				if (mp_size <= 0) {
349a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid mempool size %s\n",
350a12daff4SIbtisam Tariq 							optarg);
351e93b24a3SIntel 					return -1;
352e93b24a3SIntel 				}
353e93b24a3SIntel 				break;
354a12daff4SIbtisam Tariq 
355a12daff4SIbtisam Tariq 			case OPT_RTH_NUM:
356de3cfa2cSIntel 				ret = app_parse_rth_conf(optarg);
357de3cfa2cSIntel 				if (ret) {
358a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid RX threshold configuration %s\n",
359a12daff4SIbtisam Tariq 							optarg);
360de3cfa2cSIntel 					return -1;
361de3cfa2cSIntel 				}
362de3cfa2cSIntel 				break;
363a12daff4SIbtisam Tariq 
364a12daff4SIbtisam Tariq 			case OPT_TTH_NUM:
365de3cfa2cSIntel 				ret = app_parse_tth_conf(optarg);
366de3cfa2cSIntel 				if (ret) {
367a12daff4SIbtisam Tariq 					RTE_LOG(ERR, APP, "Invalid TX threshold configuration %s\n",
368a12daff4SIbtisam Tariq 							optarg);
369de3cfa2cSIntel 					return -1;
370de3cfa2cSIntel 				}
371de3cfa2cSIntel 				break;
372a12daff4SIbtisam Tariq 
373a12daff4SIbtisam Tariq 			case OPT_CFG_NUM:
374de3cfa2cSIntel 				cfg_profile = optarg;
375de3cfa2cSIntel 				break;
376de3cfa2cSIntel 
377de3cfa2cSIntel 			default:
378de3cfa2cSIntel 				app_usage(prgname);
379de3cfa2cSIntel 				return -1;
380de3cfa2cSIntel 			}
381de3cfa2cSIntel 	}
382de3cfa2cSIntel 
383de3cfa2cSIntel 	if (nb_pfc == 0) {
384de3cfa2cSIntel 		RTE_LOG(ERR, APP, "Packet flow not configured!\n");
385de3cfa2cSIntel 		app_usage(prgname);
386de3cfa2cSIntel 		return -1;
387de3cfa2cSIntel 	}
388de3cfa2cSIntel 
389de3cfa2cSIntel 	/* sanity check for cores assignment */
390de3cfa2cSIntel 	for(i = 0; i < nb_pfc; i++) {
3914e43299dSBruce Richardson 		if (qos_conf[i].rx_core >= RTE_MAX_LCORE) {
392de3cfa2cSIntel 			RTE_LOG(ERR, APP, "pfc %u: invalid RX lcore index %u\n", i + 1,
393de3cfa2cSIntel 					qos_conf[i].rx_core);
394de3cfa2cSIntel 			return -1;
395de3cfa2cSIntel 		}
3964e43299dSBruce Richardson 		if (qos_conf[i].wt_core >= RTE_MAX_LCORE) {
397de3cfa2cSIntel 			RTE_LOG(ERR, APP, "pfc %u: invalid WT lcore index %u\n", i + 1,
398de3cfa2cSIntel 					qos_conf[i].wt_core);
399de3cfa2cSIntel 			return -1;
400de3cfa2cSIntel 		}
401de3cfa2cSIntel 		uint32_t rx_sock = rte_lcore_to_socket_id(qos_conf[i].rx_core);
402de3cfa2cSIntel 		uint32_t wt_sock = rte_lcore_to_socket_id(qos_conf[i].wt_core);
403de3cfa2cSIntel 		if (rx_sock != wt_sock) {
404de3cfa2cSIntel 			RTE_LOG(ERR, APP, "pfc %u: RX and WT must be on the same socket\n", i + 1);
405de3cfa2cSIntel 			return -1;
406de3cfa2cSIntel 		}
407de3cfa2cSIntel 		app_numa_mask |= 1 << rte_lcore_to_socket_id(qos_conf[i].rx_core);
408de3cfa2cSIntel 	}
409de3cfa2cSIntel 
410de3cfa2cSIntel 	return 0;
411de3cfa2cSIntel }
412