xref: /dpdk/examples/pipeline/cli.c (revision 5074e1d551072105ff725d1d1add943d9ef276a9)
1*5074e1d5SCristian Dumitrescu /* SPDX-License-Identifier: BSD-3-Clause
2*5074e1d5SCristian Dumitrescu  * Copyright(c) 2020 Intel Corporation
3*5074e1d5SCristian Dumitrescu  */
4*5074e1d5SCristian Dumitrescu 
5*5074e1d5SCristian Dumitrescu #include <stdio.h>
6*5074e1d5SCristian Dumitrescu #include <stdint.h>
7*5074e1d5SCristian Dumitrescu #include <stdlib.h>
8*5074e1d5SCristian Dumitrescu #include <string.h>
9*5074e1d5SCristian Dumitrescu 
10*5074e1d5SCristian Dumitrescu #include <rte_common.h>
11*5074e1d5SCristian Dumitrescu #include <rte_ethdev.h>
12*5074e1d5SCristian Dumitrescu #include <rte_swx_port_ethdev.h>
13*5074e1d5SCristian Dumitrescu #include <rte_swx_port_source_sink.h>
14*5074e1d5SCristian Dumitrescu #include <rte_swx_pipeline.h>
15*5074e1d5SCristian Dumitrescu #include <rte_swx_ctl.h>
16*5074e1d5SCristian Dumitrescu 
17*5074e1d5SCristian Dumitrescu #include "cli.h"
18*5074e1d5SCristian Dumitrescu 
19*5074e1d5SCristian Dumitrescu #include "obj.h"
20*5074e1d5SCristian Dumitrescu #include "thread.h"
21*5074e1d5SCristian Dumitrescu 
22*5074e1d5SCristian Dumitrescu #ifndef CMD_MAX_TOKENS
23*5074e1d5SCristian Dumitrescu #define CMD_MAX_TOKENS     256
24*5074e1d5SCristian Dumitrescu #endif
25*5074e1d5SCristian Dumitrescu 
26*5074e1d5SCristian Dumitrescu #define MSG_OUT_OF_MEMORY   "Not enough memory.\n"
27*5074e1d5SCristian Dumitrescu #define MSG_CMD_UNKNOWN     "Unknown command \"%s\".\n"
28*5074e1d5SCristian Dumitrescu #define MSG_CMD_UNIMPLEM    "Command \"%s\" not implemented.\n"
29*5074e1d5SCristian Dumitrescu #define MSG_ARG_NOT_ENOUGH  "Not enough arguments for command \"%s\".\n"
30*5074e1d5SCristian Dumitrescu #define MSG_ARG_TOO_MANY    "Too many arguments for command \"%s\".\n"
31*5074e1d5SCristian Dumitrescu #define MSG_ARG_MISMATCH    "Wrong number of arguments for command \"%s\".\n"
32*5074e1d5SCristian Dumitrescu #define MSG_ARG_NOT_FOUND   "Argument \"%s\" not found.\n"
33*5074e1d5SCristian Dumitrescu #define MSG_ARG_INVALID     "Invalid value for argument \"%s\".\n"
34*5074e1d5SCristian Dumitrescu #define MSG_FILE_ERR        "Error in file \"%s\" at line %u.\n"
35*5074e1d5SCristian Dumitrescu #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
36*5074e1d5SCristian Dumitrescu #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
37*5074e1d5SCristian Dumitrescu 
38*5074e1d5SCristian Dumitrescu #define skip_white_spaces(pos)			\
39*5074e1d5SCristian Dumitrescu ({						\
40*5074e1d5SCristian Dumitrescu 	__typeof__(pos) _p = (pos);		\
41*5074e1d5SCristian Dumitrescu 	for ( ; isspace(*_p); _p++)		\
42*5074e1d5SCristian Dumitrescu 		;				\
43*5074e1d5SCristian Dumitrescu 	_p;					\
44*5074e1d5SCristian Dumitrescu })
45*5074e1d5SCristian Dumitrescu 
46*5074e1d5SCristian Dumitrescu static int
47*5074e1d5SCristian Dumitrescu parser_read_uint64(uint64_t *value, const char *p)
48*5074e1d5SCristian Dumitrescu {
49*5074e1d5SCristian Dumitrescu 	char *next;
50*5074e1d5SCristian Dumitrescu 	uint64_t val;
51*5074e1d5SCristian Dumitrescu 
52*5074e1d5SCristian Dumitrescu 	p = skip_white_spaces(p);
53*5074e1d5SCristian Dumitrescu 	if (!isdigit(*p))
54*5074e1d5SCristian Dumitrescu 		return -EINVAL;
55*5074e1d5SCristian Dumitrescu 
56*5074e1d5SCristian Dumitrescu 	val = strtoul(p, &next, 10);
57*5074e1d5SCristian Dumitrescu 	if (p == next)
58*5074e1d5SCristian Dumitrescu 		return -EINVAL;
59*5074e1d5SCristian Dumitrescu 
60*5074e1d5SCristian Dumitrescu 	p = next;
61*5074e1d5SCristian Dumitrescu 	switch (*p) {
62*5074e1d5SCristian Dumitrescu 	case 'T':
63*5074e1d5SCristian Dumitrescu 		val *= 1024ULL;
64*5074e1d5SCristian Dumitrescu 		/* fall through */
65*5074e1d5SCristian Dumitrescu 	case 'G':
66*5074e1d5SCristian Dumitrescu 		val *= 1024ULL;
67*5074e1d5SCristian Dumitrescu 		/* fall through */
68*5074e1d5SCristian Dumitrescu 	case 'M':
69*5074e1d5SCristian Dumitrescu 		val *= 1024ULL;
70*5074e1d5SCristian Dumitrescu 		/* fall through */
71*5074e1d5SCristian Dumitrescu 	case 'k':
72*5074e1d5SCristian Dumitrescu 	case 'K':
73*5074e1d5SCristian Dumitrescu 		val *= 1024ULL;
74*5074e1d5SCristian Dumitrescu 		p++;
75*5074e1d5SCristian Dumitrescu 		break;
76*5074e1d5SCristian Dumitrescu 	}
77*5074e1d5SCristian Dumitrescu 
78*5074e1d5SCristian Dumitrescu 	p = skip_white_spaces(p);
79*5074e1d5SCristian Dumitrescu 	if (*p != '\0')
80*5074e1d5SCristian Dumitrescu 		return -EINVAL;
81*5074e1d5SCristian Dumitrescu 
82*5074e1d5SCristian Dumitrescu 	*value = val;
83*5074e1d5SCristian Dumitrescu 	return 0;
84*5074e1d5SCristian Dumitrescu }
85*5074e1d5SCristian Dumitrescu 
86*5074e1d5SCristian Dumitrescu static int
87*5074e1d5SCristian Dumitrescu parser_read_uint32(uint32_t *value, const char *p)
88*5074e1d5SCristian Dumitrescu {
89*5074e1d5SCristian Dumitrescu 	uint64_t val = 0;
90*5074e1d5SCristian Dumitrescu 	int ret = parser_read_uint64(&val, p);
91*5074e1d5SCristian Dumitrescu 
92*5074e1d5SCristian Dumitrescu 	if (ret < 0)
93*5074e1d5SCristian Dumitrescu 		return ret;
94*5074e1d5SCristian Dumitrescu 
95*5074e1d5SCristian Dumitrescu 	if (val > UINT32_MAX)
96*5074e1d5SCristian Dumitrescu 		return -ERANGE;
97*5074e1d5SCristian Dumitrescu 
98*5074e1d5SCristian Dumitrescu 	*value = val;
99*5074e1d5SCristian Dumitrescu 	return 0;
100*5074e1d5SCristian Dumitrescu }
101*5074e1d5SCristian Dumitrescu 
102*5074e1d5SCristian Dumitrescu static int
103*5074e1d5SCristian Dumitrescu parser_read_uint16(uint16_t *value, const char *p)
104*5074e1d5SCristian Dumitrescu {
105*5074e1d5SCristian Dumitrescu 	uint64_t val = 0;
106*5074e1d5SCristian Dumitrescu 	int ret = parser_read_uint64(&val, p);
107*5074e1d5SCristian Dumitrescu 
108*5074e1d5SCristian Dumitrescu 	if (ret < 0)
109*5074e1d5SCristian Dumitrescu 		return ret;
110*5074e1d5SCristian Dumitrescu 
111*5074e1d5SCristian Dumitrescu 	if (val > UINT16_MAX)
112*5074e1d5SCristian Dumitrescu 		return -ERANGE;
113*5074e1d5SCristian Dumitrescu 
114*5074e1d5SCristian Dumitrescu 	*value = val;
115*5074e1d5SCristian Dumitrescu 	return 0;
116*5074e1d5SCristian Dumitrescu }
117*5074e1d5SCristian Dumitrescu 
118*5074e1d5SCristian Dumitrescu #define PARSE_DELIMITER " \f\n\r\t\v"
119*5074e1d5SCristian Dumitrescu 
120*5074e1d5SCristian Dumitrescu static int
121*5074e1d5SCristian Dumitrescu parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
122*5074e1d5SCristian Dumitrescu {
123*5074e1d5SCristian Dumitrescu 	uint32_t i;
124*5074e1d5SCristian Dumitrescu 
125*5074e1d5SCristian Dumitrescu 	if ((string == NULL) ||
126*5074e1d5SCristian Dumitrescu 		(tokens == NULL) ||
127*5074e1d5SCristian Dumitrescu 		(*n_tokens < 1))
128*5074e1d5SCristian Dumitrescu 		return -EINVAL;
129*5074e1d5SCristian Dumitrescu 
130*5074e1d5SCristian Dumitrescu 	for (i = 0; i < *n_tokens; i++) {
131*5074e1d5SCristian Dumitrescu 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
132*5074e1d5SCristian Dumitrescu 		if (tokens[i] == NULL)
133*5074e1d5SCristian Dumitrescu 			break;
134*5074e1d5SCristian Dumitrescu 	}
135*5074e1d5SCristian Dumitrescu 
136*5074e1d5SCristian Dumitrescu 	if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string))
137*5074e1d5SCristian Dumitrescu 		return -E2BIG;
138*5074e1d5SCristian Dumitrescu 
139*5074e1d5SCristian Dumitrescu 	*n_tokens = i;
140*5074e1d5SCristian Dumitrescu 	return 0;
141*5074e1d5SCristian Dumitrescu }
142*5074e1d5SCristian Dumitrescu 
143*5074e1d5SCristian Dumitrescu static int
144*5074e1d5SCristian Dumitrescu is_comment(char *in)
145*5074e1d5SCristian Dumitrescu {
146*5074e1d5SCristian Dumitrescu 	if ((strlen(in) && index("!#%;", in[0])) ||
147*5074e1d5SCristian Dumitrescu 		(strncmp(in, "//", 2) == 0) ||
148*5074e1d5SCristian Dumitrescu 		(strncmp(in, "--", 2) == 0))
149*5074e1d5SCristian Dumitrescu 		return 1;
150*5074e1d5SCristian Dumitrescu 
151*5074e1d5SCristian Dumitrescu 	return 0;
152*5074e1d5SCristian Dumitrescu }
153*5074e1d5SCristian Dumitrescu 
154*5074e1d5SCristian Dumitrescu static const char cmd_mempool_help[] =
155*5074e1d5SCristian Dumitrescu "mempool <mempool_name>\n"
156*5074e1d5SCristian Dumitrescu "   buffer <buffer_size>\n"
157*5074e1d5SCristian Dumitrescu "   pool <pool_size>\n"
158*5074e1d5SCristian Dumitrescu "   cache <cache_size>\n"
159*5074e1d5SCristian Dumitrescu "   cpu <cpu_id>\n";
160*5074e1d5SCristian Dumitrescu 
161*5074e1d5SCristian Dumitrescu static void
162*5074e1d5SCristian Dumitrescu cmd_mempool(char **tokens,
163*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
164*5074e1d5SCristian Dumitrescu 	char *out,
165*5074e1d5SCristian Dumitrescu 	size_t out_size,
166*5074e1d5SCristian Dumitrescu 	void *obj)
167*5074e1d5SCristian Dumitrescu {
168*5074e1d5SCristian Dumitrescu 	struct mempool_params p;
169*5074e1d5SCristian Dumitrescu 	char *name;
170*5074e1d5SCristian Dumitrescu 	struct mempool *mempool;
171*5074e1d5SCristian Dumitrescu 
172*5074e1d5SCristian Dumitrescu 	if (n_tokens != 10) {
173*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
174*5074e1d5SCristian Dumitrescu 		return;
175*5074e1d5SCristian Dumitrescu 	}
176*5074e1d5SCristian Dumitrescu 
177*5074e1d5SCristian Dumitrescu 	name = tokens[1];
178*5074e1d5SCristian Dumitrescu 
179*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "buffer") != 0) {
180*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
181*5074e1d5SCristian Dumitrescu 		return;
182*5074e1d5SCristian Dumitrescu 	}
183*5074e1d5SCristian Dumitrescu 
184*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
185*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
186*5074e1d5SCristian Dumitrescu 		return;
187*5074e1d5SCristian Dumitrescu 	}
188*5074e1d5SCristian Dumitrescu 
189*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[4], "pool") != 0) {
190*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
191*5074e1d5SCristian Dumitrescu 		return;
192*5074e1d5SCristian Dumitrescu 	}
193*5074e1d5SCristian Dumitrescu 
194*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
195*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
196*5074e1d5SCristian Dumitrescu 		return;
197*5074e1d5SCristian Dumitrescu 	}
198*5074e1d5SCristian Dumitrescu 
199*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[6], "cache") != 0) {
200*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
201*5074e1d5SCristian Dumitrescu 		return;
202*5074e1d5SCristian Dumitrescu 	}
203*5074e1d5SCristian Dumitrescu 
204*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
205*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
206*5074e1d5SCristian Dumitrescu 		return;
207*5074e1d5SCristian Dumitrescu 	}
208*5074e1d5SCristian Dumitrescu 
209*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[8], "cpu") != 0) {
210*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
211*5074e1d5SCristian Dumitrescu 		return;
212*5074e1d5SCristian Dumitrescu 	}
213*5074e1d5SCristian Dumitrescu 
214*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
215*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
216*5074e1d5SCristian Dumitrescu 		return;
217*5074e1d5SCristian Dumitrescu 	}
218*5074e1d5SCristian Dumitrescu 
219*5074e1d5SCristian Dumitrescu 	mempool = mempool_create(obj, name, &p);
220*5074e1d5SCristian Dumitrescu 	if (mempool == NULL) {
221*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
222*5074e1d5SCristian Dumitrescu 		return;
223*5074e1d5SCristian Dumitrescu 	}
224*5074e1d5SCristian Dumitrescu }
225*5074e1d5SCristian Dumitrescu 
226*5074e1d5SCristian Dumitrescu static const char cmd_link_help[] =
227*5074e1d5SCristian Dumitrescu "link <link_name>\n"
228*5074e1d5SCristian Dumitrescu "   dev <device_name> | port <port_id>\n"
229*5074e1d5SCristian Dumitrescu "   rxq <n_queues> <queue_size> <mempool_name>\n"
230*5074e1d5SCristian Dumitrescu "   txq <n_queues> <queue_size>\n"
231*5074e1d5SCristian Dumitrescu "   promiscuous on | off\n"
232*5074e1d5SCristian Dumitrescu "   [rss <qid_0> ... <qid_n>]\n";
233*5074e1d5SCristian Dumitrescu 
234*5074e1d5SCristian Dumitrescu static void
235*5074e1d5SCristian Dumitrescu cmd_link(char **tokens,
236*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
237*5074e1d5SCristian Dumitrescu 	char *out,
238*5074e1d5SCristian Dumitrescu 	size_t out_size,
239*5074e1d5SCristian Dumitrescu 	void *obj)
240*5074e1d5SCristian Dumitrescu {
241*5074e1d5SCristian Dumitrescu 	struct link_params p;
242*5074e1d5SCristian Dumitrescu 	struct link_params_rss rss;
243*5074e1d5SCristian Dumitrescu 	struct link *link;
244*5074e1d5SCristian Dumitrescu 	char *name;
245*5074e1d5SCristian Dumitrescu 
246*5074e1d5SCristian Dumitrescu 	memset(&p, 0, sizeof(p));
247*5074e1d5SCristian Dumitrescu 
248*5074e1d5SCristian Dumitrescu 	if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
249*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
250*5074e1d5SCristian Dumitrescu 		return;
251*5074e1d5SCristian Dumitrescu 	}
252*5074e1d5SCristian Dumitrescu 	name = tokens[1];
253*5074e1d5SCristian Dumitrescu 
254*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "dev") == 0)
255*5074e1d5SCristian Dumitrescu 		p.dev_name = tokens[3];
256*5074e1d5SCristian Dumitrescu 	else if (strcmp(tokens[2], "port") == 0) {
257*5074e1d5SCristian Dumitrescu 		p.dev_name = NULL;
258*5074e1d5SCristian Dumitrescu 
259*5074e1d5SCristian Dumitrescu 		if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
260*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
261*5074e1d5SCristian Dumitrescu 			return;
262*5074e1d5SCristian Dumitrescu 		}
263*5074e1d5SCristian Dumitrescu 	} else {
264*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
265*5074e1d5SCristian Dumitrescu 		return;
266*5074e1d5SCristian Dumitrescu 	}
267*5074e1d5SCristian Dumitrescu 
268*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[4], "rxq") != 0) {
269*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
270*5074e1d5SCristian Dumitrescu 		return;
271*5074e1d5SCristian Dumitrescu 	}
272*5074e1d5SCristian Dumitrescu 
273*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
274*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
275*5074e1d5SCristian Dumitrescu 		return;
276*5074e1d5SCristian Dumitrescu 	}
277*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
278*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
279*5074e1d5SCristian Dumitrescu 		return;
280*5074e1d5SCristian Dumitrescu 	}
281*5074e1d5SCristian Dumitrescu 
282*5074e1d5SCristian Dumitrescu 	p.rx.mempool_name = tokens[7];
283*5074e1d5SCristian Dumitrescu 
284*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[8], "txq") != 0) {
285*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
286*5074e1d5SCristian Dumitrescu 		return;
287*5074e1d5SCristian Dumitrescu 	}
288*5074e1d5SCristian Dumitrescu 
289*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
290*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
291*5074e1d5SCristian Dumitrescu 		return;
292*5074e1d5SCristian Dumitrescu 	}
293*5074e1d5SCristian Dumitrescu 
294*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
295*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
296*5074e1d5SCristian Dumitrescu 		return;
297*5074e1d5SCristian Dumitrescu 	}
298*5074e1d5SCristian Dumitrescu 
299*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[11], "promiscuous") != 0) {
300*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
301*5074e1d5SCristian Dumitrescu 		return;
302*5074e1d5SCristian Dumitrescu 	}
303*5074e1d5SCristian Dumitrescu 
304*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[12], "on") == 0)
305*5074e1d5SCristian Dumitrescu 		p.promiscuous = 1;
306*5074e1d5SCristian Dumitrescu 	else if (strcmp(tokens[12], "off") == 0)
307*5074e1d5SCristian Dumitrescu 		p.promiscuous = 0;
308*5074e1d5SCristian Dumitrescu 	else {
309*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
310*5074e1d5SCristian Dumitrescu 		return;
311*5074e1d5SCristian Dumitrescu 	}
312*5074e1d5SCristian Dumitrescu 
313*5074e1d5SCristian Dumitrescu 	/* RSS */
314*5074e1d5SCristian Dumitrescu 	p.rx.rss = NULL;
315*5074e1d5SCristian Dumitrescu 	if (n_tokens > 13) {
316*5074e1d5SCristian Dumitrescu 		uint32_t queue_id, i;
317*5074e1d5SCristian Dumitrescu 
318*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[13], "rss") != 0) {
319*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
320*5074e1d5SCristian Dumitrescu 			return;
321*5074e1d5SCristian Dumitrescu 		}
322*5074e1d5SCristian Dumitrescu 
323*5074e1d5SCristian Dumitrescu 		p.rx.rss = &rss;
324*5074e1d5SCristian Dumitrescu 
325*5074e1d5SCristian Dumitrescu 		rss.n_queues = 0;
326*5074e1d5SCristian Dumitrescu 		for (i = 14; i < n_tokens; i++) {
327*5074e1d5SCristian Dumitrescu 			if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
328*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size, MSG_ARG_INVALID,
329*5074e1d5SCristian Dumitrescu 					"queue_id");
330*5074e1d5SCristian Dumitrescu 				return;
331*5074e1d5SCristian Dumitrescu 			}
332*5074e1d5SCristian Dumitrescu 
333*5074e1d5SCristian Dumitrescu 			rss.queue_id[rss.n_queues] = queue_id;
334*5074e1d5SCristian Dumitrescu 			rss.n_queues++;
335*5074e1d5SCristian Dumitrescu 		}
336*5074e1d5SCristian Dumitrescu 	}
337*5074e1d5SCristian Dumitrescu 
338*5074e1d5SCristian Dumitrescu 	link = link_create(obj, name, &p);
339*5074e1d5SCristian Dumitrescu 	if (link == NULL) {
340*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
341*5074e1d5SCristian Dumitrescu 		return;
342*5074e1d5SCristian Dumitrescu 	}
343*5074e1d5SCristian Dumitrescu }
344*5074e1d5SCristian Dumitrescu 
345*5074e1d5SCristian Dumitrescu /* Print the link stats and info */
346*5074e1d5SCristian Dumitrescu static void
347*5074e1d5SCristian Dumitrescu print_link_info(struct link *link, char *out, size_t out_size)
348*5074e1d5SCristian Dumitrescu {
349*5074e1d5SCristian Dumitrescu 	struct rte_eth_stats stats;
350*5074e1d5SCristian Dumitrescu 	struct rte_ether_addr mac_addr;
351*5074e1d5SCristian Dumitrescu 	struct rte_eth_link eth_link;
352*5074e1d5SCristian Dumitrescu 	uint16_t mtu;
353*5074e1d5SCristian Dumitrescu 	int ret;
354*5074e1d5SCristian Dumitrescu 
355*5074e1d5SCristian Dumitrescu 	memset(&stats, 0, sizeof(stats));
356*5074e1d5SCristian Dumitrescu 	rte_eth_stats_get(link->port_id, &stats);
357*5074e1d5SCristian Dumitrescu 
358*5074e1d5SCristian Dumitrescu 	ret = rte_eth_macaddr_get(link->port_id, &mac_addr);
359*5074e1d5SCristian Dumitrescu 	if (ret != 0) {
360*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s: MAC address get failed: %s",
361*5074e1d5SCristian Dumitrescu 			 link->name, rte_strerror(-ret));
362*5074e1d5SCristian Dumitrescu 		return;
363*5074e1d5SCristian Dumitrescu 	}
364*5074e1d5SCristian Dumitrescu 
365*5074e1d5SCristian Dumitrescu 	ret = rte_eth_link_get(link->port_id, &eth_link);
366*5074e1d5SCristian Dumitrescu 	if (ret < 0) {
367*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s: link get failed: %s",
368*5074e1d5SCristian Dumitrescu 			 link->name, rte_strerror(-ret));
369*5074e1d5SCristian Dumitrescu 		return;
370*5074e1d5SCristian Dumitrescu 	}
371*5074e1d5SCristian Dumitrescu 
372*5074e1d5SCristian Dumitrescu 	rte_eth_dev_get_mtu(link->port_id, &mtu);
373*5074e1d5SCristian Dumitrescu 
374*5074e1d5SCristian Dumitrescu 	snprintf(out, out_size,
375*5074e1d5SCristian Dumitrescu 		"\n"
376*5074e1d5SCristian Dumitrescu 		"%s: flags=<%s> mtu %u\n"
377*5074e1d5SCristian Dumitrescu 		"\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n"
378*5074e1d5SCristian Dumitrescu 		"\tport# %u  speed %s\n"
379*5074e1d5SCristian Dumitrescu 		"\tRX packets %" PRIu64"  bytes %" PRIu64"\n"
380*5074e1d5SCristian Dumitrescu 		"\tRX errors %" PRIu64"  missed %" PRIu64"  no-mbuf %" PRIu64"\n"
381*5074e1d5SCristian Dumitrescu 		"\tTX packets %" PRIu64"  bytes %" PRIu64"\n"
382*5074e1d5SCristian Dumitrescu 		"\tTX errors %" PRIu64"\n",
383*5074e1d5SCristian Dumitrescu 		link->name,
384*5074e1d5SCristian Dumitrescu 		eth_link.link_status == 0 ? "DOWN" : "UP",
385*5074e1d5SCristian Dumitrescu 		mtu,
386*5074e1d5SCristian Dumitrescu 		mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
387*5074e1d5SCristian Dumitrescu 		mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
388*5074e1d5SCristian Dumitrescu 		mac_addr.addr_bytes[4], mac_addr.addr_bytes[5],
389*5074e1d5SCristian Dumitrescu 		link->n_rxq,
390*5074e1d5SCristian Dumitrescu 		link->n_txq,
391*5074e1d5SCristian Dumitrescu 		link->port_id,
392*5074e1d5SCristian Dumitrescu 		rte_eth_link_speed_to_str(eth_link.link_speed),
393*5074e1d5SCristian Dumitrescu 		stats.ipackets,
394*5074e1d5SCristian Dumitrescu 		stats.ibytes,
395*5074e1d5SCristian Dumitrescu 		stats.ierrors,
396*5074e1d5SCristian Dumitrescu 		stats.imissed,
397*5074e1d5SCristian Dumitrescu 		stats.rx_nombuf,
398*5074e1d5SCristian Dumitrescu 		stats.opackets,
399*5074e1d5SCristian Dumitrescu 		stats.obytes,
400*5074e1d5SCristian Dumitrescu 		stats.oerrors);
401*5074e1d5SCristian Dumitrescu }
402*5074e1d5SCristian Dumitrescu 
403*5074e1d5SCristian Dumitrescu /*
404*5074e1d5SCristian Dumitrescu  * link show [<link_name>]
405*5074e1d5SCristian Dumitrescu  */
406*5074e1d5SCristian Dumitrescu static void
407*5074e1d5SCristian Dumitrescu cmd_link_show(char **tokens,
408*5074e1d5SCristian Dumitrescu 	      uint32_t n_tokens,
409*5074e1d5SCristian Dumitrescu 	      char *out,
410*5074e1d5SCristian Dumitrescu 	      size_t out_size,
411*5074e1d5SCristian Dumitrescu 	      void *obj)
412*5074e1d5SCristian Dumitrescu {
413*5074e1d5SCristian Dumitrescu 	struct link *link;
414*5074e1d5SCristian Dumitrescu 	char *link_name;
415*5074e1d5SCristian Dumitrescu 
416*5074e1d5SCristian Dumitrescu 	if (n_tokens != 2 && n_tokens != 3) {
417*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
418*5074e1d5SCristian Dumitrescu 		return;
419*5074e1d5SCristian Dumitrescu 	}
420*5074e1d5SCristian Dumitrescu 
421*5074e1d5SCristian Dumitrescu 	if (n_tokens == 2) {
422*5074e1d5SCristian Dumitrescu 		link = link_next(obj, NULL);
423*5074e1d5SCristian Dumitrescu 
424*5074e1d5SCristian Dumitrescu 		while (link != NULL) {
425*5074e1d5SCristian Dumitrescu 			out_size = out_size - strlen(out);
426*5074e1d5SCristian Dumitrescu 			out = &out[strlen(out)];
427*5074e1d5SCristian Dumitrescu 
428*5074e1d5SCristian Dumitrescu 			print_link_info(link, out, out_size);
429*5074e1d5SCristian Dumitrescu 			link = link_next(obj, link);
430*5074e1d5SCristian Dumitrescu 		}
431*5074e1d5SCristian Dumitrescu 	} else {
432*5074e1d5SCristian Dumitrescu 		out_size = out_size - strlen(out);
433*5074e1d5SCristian Dumitrescu 		out = &out[strlen(out)];
434*5074e1d5SCristian Dumitrescu 
435*5074e1d5SCristian Dumitrescu 		link_name = tokens[2];
436*5074e1d5SCristian Dumitrescu 		link = link_find(obj, link_name);
437*5074e1d5SCristian Dumitrescu 
438*5074e1d5SCristian Dumitrescu 		if (link == NULL) {
439*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
440*5074e1d5SCristian Dumitrescu 					"Link does not exist");
441*5074e1d5SCristian Dumitrescu 			return;
442*5074e1d5SCristian Dumitrescu 		}
443*5074e1d5SCristian Dumitrescu 		print_link_info(link, out, out_size);
444*5074e1d5SCristian Dumitrescu 	}
445*5074e1d5SCristian Dumitrescu }
446*5074e1d5SCristian Dumitrescu 
447*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_create_help[] =
448*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> create <numa_node>\n";
449*5074e1d5SCristian Dumitrescu 
450*5074e1d5SCristian Dumitrescu static void
451*5074e1d5SCristian Dumitrescu cmd_pipeline_create(char **tokens,
452*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
453*5074e1d5SCristian Dumitrescu 	char *out,
454*5074e1d5SCristian Dumitrescu 	size_t out_size,
455*5074e1d5SCristian Dumitrescu 	void *obj)
456*5074e1d5SCristian Dumitrescu {
457*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
458*5074e1d5SCristian Dumitrescu 	char *name;
459*5074e1d5SCristian Dumitrescu 	uint32_t numa_node;
460*5074e1d5SCristian Dumitrescu 
461*5074e1d5SCristian Dumitrescu 	if (n_tokens != 4) {
462*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
463*5074e1d5SCristian Dumitrescu 		return;
464*5074e1d5SCristian Dumitrescu 	}
465*5074e1d5SCristian Dumitrescu 
466*5074e1d5SCristian Dumitrescu 	name = tokens[1];
467*5074e1d5SCristian Dumitrescu 
468*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&numa_node, tokens[3]) != 0) {
469*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
470*5074e1d5SCristian Dumitrescu 		return;
471*5074e1d5SCristian Dumitrescu 	}
472*5074e1d5SCristian Dumitrescu 
473*5074e1d5SCristian Dumitrescu 	p = pipeline_create(obj, name, (int)numa_node);
474*5074e1d5SCristian Dumitrescu 	if (!p) {
475*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "pipeline create error.");
476*5074e1d5SCristian Dumitrescu 		return;
477*5074e1d5SCristian Dumitrescu 	}
478*5074e1d5SCristian Dumitrescu }
479*5074e1d5SCristian Dumitrescu 
480*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_port_in_help[] =
481*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> port in <port_id>\n"
482*5074e1d5SCristian Dumitrescu "   link <link_name> rxq <queue_id> bsz <burst_size>\n"
483*5074e1d5SCristian Dumitrescu "   source <mempool_name> <fie_name>\n";
484*5074e1d5SCristian Dumitrescu 
485*5074e1d5SCristian Dumitrescu static void
486*5074e1d5SCristian Dumitrescu cmd_pipeline_port_in(char **tokens,
487*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
488*5074e1d5SCristian Dumitrescu 	char *out,
489*5074e1d5SCristian Dumitrescu 	size_t out_size,
490*5074e1d5SCristian Dumitrescu 	void *obj)
491*5074e1d5SCristian Dumitrescu {
492*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
493*5074e1d5SCristian Dumitrescu 	int status;
494*5074e1d5SCristian Dumitrescu 	uint32_t port_id = 0, t0;
495*5074e1d5SCristian Dumitrescu 
496*5074e1d5SCristian Dumitrescu 	if (n_tokens < 6) {
497*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
498*5074e1d5SCristian Dumitrescu 		return;
499*5074e1d5SCristian Dumitrescu 	}
500*5074e1d5SCristian Dumitrescu 
501*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, tokens[1]);
502*5074e1d5SCristian Dumitrescu 	if (!p || p->ctl) {
503*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
504*5074e1d5SCristian Dumitrescu 		return;
505*5074e1d5SCristian Dumitrescu 	}
506*5074e1d5SCristian Dumitrescu 
507*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "port") != 0) {
508*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
509*5074e1d5SCristian Dumitrescu 		return;
510*5074e1d5SCristian Dumitrescu 	}
511*5074e1d5SCristian Dumitrescu 
512*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[3], "in") != 0) {
513*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
514*5074e1d5SCristian Dumitrescu 		return;
515*5074e1d5SCristian Dumitrescu 	}
516*5074e1d5SCristian Dumitrescu 
517*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&port_id, tokens[4]) != 0) {
518*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
519*5074e1d5SCristian Dumitrescu 		return;
520*5074e1d5SCristian Dumitrescu 	}
521*5074e1d5SCristian Dumitrescu 
522*5074e1d5SCristian Dumitrescu 	t0 = 5;
523*5074e1d5SCristian Dumitrescu 
524*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[t0], "link") == 0) {
525*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_ethdev_reader_params params;
526*5074e1d5SCristian Dumitrescu 		struct link *link;
527*5074e1d5SCristian Dumitrescu 
528*5074e1d5SCristian Dumitrescu 		if (n_tokens < t0 + 6) {
529*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_MISMATCH,
530*5074e1d5SCristian Dumitrescu 				"pipeline port in link");
531*5074e1d5SCristian Dumitrescu 			return;
532*5074e1d5SCristian Dumitrescu 		}
533*5074e1d5SCristian Dumitrescu 
534*5074e1d5SCristian Dumitrescu 		link = link_find(obj, tokens[t0 + 1]);
535*5074e1d5SCristian Dumitrescu 		if (!link) {
536*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
537*5074e1d5SCristian Dumitrescu 				"link_name");
538*5074e1d5SCristian Dumitrescu 			return;
539*5074e1d5SCristian Dumitrescu 		}
540*5074e1d5SCristian Dumitrescu 		params.dev_name = link->dev_name;
541*5074e1d5SCristian Dumitrescu 
542*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
543*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
544*5074e1d5SCristian Dumitrescu 			return;
545*5074e1d5SCristian Dumitrescu 		}
546*5074e1d5SCristian Dumitrescu 
547*5074e1d5SCristian Dumitrescu 		if (parser_read_uint16(&params.queue_id, tokens[t0 + 3]) != 0) {
548*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
549*5074e1d5SCristian Dumitrescu 				"queue_id");
550*5074e1d5SCristian Dumitrescu 			return;
551*5074e1d5SCristian Dumitrescu 		}
552*5074e1d5SCristian Dumitrescu 
553*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[t0 + 4], "bsz") != 0) {
554*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
555*5074e1d5SCristian Dumitrescu 			return;
556*5074e1d5SCristian Dumitrescu 		}
557*5074e1d5SCristian Dumitrescu 
558*5074e1d5SCristian Dumitrescu 		if (parser_read_uint32(&params.burst_size, tokens[t0 + 5])) {
559*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
560*5074e1d5SCristian Dumitrescu 				"burst_size");
561*5074e1d5SCristian Dumitrescu 			return;
562*5074e1d5SCristian Dumitrescu 		}
563*5074e1d5SCristian Dumitrescu 
564*5074e1d5SCristian Dumitrescu 		t0 += 6;
565*5074e1d5SCristian Dumitrescu 
566*5074e1d5SCristian Dumitrescu 		status = rte_swx_pipeline_port_in_config(p->p,
567*5074e1d5SCristian Dumitrescu 			port_id,
568*5074e1d5SCristian Dumitrescu 			"ethdev",
569*5074e1d5SCristian Dumitrescu 			&params);
570*5074e1d5SCristian Dumitrescu 	} else if (strcmp(tokens[t0], "source") == 0) {
571*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_source_params params;
572*5074e1d5SCristian Dumitrescu 		struct mempool *mp;
573*5074e1d5SCristian Dumitrescu 
574*5074e1d5SCristian Dumitrescu 		if (n_tokens < t0 + 3) {
575*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_MISMATCH,
576*5074e1d5SCristian Dumitrescu 				"pipeline port in source");
577*5074e1d5SCristian Dumitrescu 			return;
578*5074e1d5SCristian Dumitrescu 		}
579*5074e1d5SCristian Dumitrescu 
580*5074e1d5SCristian Dumitrescu 		mp = mempool_find(obj, tokens[t0 + 1]);
581*5074e1d5SCristian Dumitrescu 		if (!mp) {
582*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
583*5074e1d5SCristian Dumitrescu 				"mempool_name");
584*5074e1d5SCristian Dumitrescu 			return;
585*5074e1d5SCristian Dumitrescu 		}
586*5074e1d5SCristian Dumitrescu 		params.pool = mp->m;
587*5074e1d5SCristian Dumitrescu 
588*5074e1d5SCristian Dumitrescu 		params.file_name = tokens[t0 + 2];
589*5074e1d5SCristian Dumitrescu 
590*5074e1d5SCristian Dumitrescu 		t0 += 3;
591*5074e1d5SCristian Dumitrescu 
592*5074e1d5SCristian Dumitrescu 		status = rte_swx_pipeline_port_in_config(p->p,
593*5074e1d5SCristian Dumitrescu 			port_id,
594*5074e1d5SCristian Dumitrescu 			"source",
595*5074e1d5SCristian Dumitrescu 			&params);
596*5074e1d5SCristian Dumitrescu 	} else {
597*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
598*5074e1d5SCristian Dumitrescu 		return;
599*5074e1d5SCristian Dumitrescu 	}
600*5074e1d5SCristian Dumitrescu 
601*5074e1d5SCristian Dumitrescu 	if (status) {
602*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "port in error.");
603*5074e1d5SCristian Dumitrescu 		return;
604*5074e1d5SCristian Dumitrescu 	}
605*5074e1d5SCristian Dumitrescu 
606*5074e1d5SCristian Dumitrescu 	if (n_tokens != t0) {
607*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
608*5074e1d5SCristian Dumitrescu 		return;
609*5074e1d5SCristian Dumitrescu 	}
610*5074e1d5SCristian Dumitrescu }
611*5074e1d5SCristian Dumitrescu 
612*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_port_out_help[] =
613*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> port out <port_id>\n"
614*5074e1d5SCristian Dumitrescu "   link <link_name> txq <txq_id> bsz <burst_size>\n"
615*5074e1d5SCristian Dumitrescu "   | sink <file_name> | none\n";
616*5074e1d5SCristian Dumitrescu 
617*5074e1d5SCristian Dumitrescu static void
618*5074e1d5SCristian Dumitrescu cmd_pipeline_port_out(char **tokens,
619*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
620*5074e1d5SCristian Dumitrescu 	char *out,
621*5074e1d5SCristian Dumitrescu 	size_t out_size,
622*5074e1d5SCristian Dumitrescu 	void *obj)
623*5074e1d5SCristian Dumitrescu {
624*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
625*5074e1d5SCristian Dumitrescu 	int status;
626*5074e1d5SCristian Dumitrescu 	uint32_t port_id = 0, t0;
627*5074e1d5SCristian Dumitrescu 
628*5074e1d5SCristian Dumitrescu 	if (n_tokens < 6) {
629*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
630*5074e1d5SCristian Dumitrescu 		return;
631*5074e1d5SCristian Dumitrescu 	}
632*5074e1d5SCristian Dumitrescu 
633*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, tokens[1]);
634*5074e1d5SCristian Dumitrescu 	if (!p || p->ctl) {
635*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
636*5074e1d5SCristian Dumitrescu 		return;
637*5074e1d5SCristian Dumitrescu 	}
638*5074e1d5SCristian Dumitrescu 
639*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "port") != 0) {
640*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
641*5074e1d5SCristian Dumitrescu 		return;
642*5074e1d5SCristian Dumitrescu 	}
643*5074e1d5SCristian Dumitrescu 
644*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[3], "out") != 0) {
645*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
646*5074e1d5SCristian Dumitrescu 		return;
647*5074e1d5SCristian Dumitrescu 	}
648*5074e1d5SCristian Dumitrescu 
649*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&port_id, tokens[4]) != 0) {
650*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
651*5074e1d5SCristian Dumitrescu 		return;
652*5074e1d5SCristian Dumitrescu 	}
653*5074e1d5SCristian Dumitrescu 
654*5074e1d5SCristian Dumitrescu 	t0 = 5;
655*5074e1d5SCristian Dumitrescu 
656*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[t0], "link") == 0) {
657*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_ethdev_writer_params params;
658*5074e1d5SCristian Dumitrescu 		struct link *link;
659*5074e1d5SCristian Dumitrescu 
660*5074e1d5SCristian Dumitrescu 		if (n_tokens < t0 + 6) {
661*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_MISMATCH,
662*5074e1d5SCristian Dumitrescu 				"pipeline port out link");
663*5074e1d5SCristian Dumitrescu 			return;
664*5074e1d5SCristian Dumitrescu 		}
665*5074e1d5SCristian Dumitrescu 
666*5074e1d5SCristian Dumitrescu 		link = link_find(obj, tokens[t0 + 1]);
667*5074e1d5SCristian Dumitrescu 		if (!link) {
668*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
669*5074e1d5SCristian Dumitrescu 				"link_name");
670*5074e1d5SCristian Dumitrescu 			return;
671*5074e1d5SCristian Dumitrescu 		}
672*5074e1d5SCristian Dumitrescu 		params.dev_name = link->dev_name;
673*5074e1d5SCristian Dumitrescu 
674*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[t0 + 2], "txq") != 0) {
675*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
676*5074e1d5SCristian Dumitrescu 			return;
677*5074e1d5SCristian Dumitrescu 		}
678*5074e1d5SCristian Dumitrescu 
679*5074e1d5SCristian Dumitrescu 		if (parser_read_uint16(&params.queue_id, tokens[t0 + 3]) != 0) {
680*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
681*5074e1d5SCristian Dumitrescu 				"queue_id");
682*5074e1d5SCristian Dumitrescu 			return;
683*5074e1d5SCristian Dumitrescu 		}
684*5074e1d5SCristian Dumitrescu 
685*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[t0 + 4], "bsz") != 0) {
686*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
687*5074e1d5SCristian Dumitrescu 			return;
688*5074e1d5SCristian Dumitrescu 		}
689*5074e1d5SCristian Dumitrescu 
690*5074e1d5SCristian Dumitrescu 		if (parser_read_uint32(&params.burst_size, tokens[t0 + 5])) {
691*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, MSG_ARG_INVALID,
692*5074e1d5SCristian Dumitrescu 				"burst_size");
693*5074e1d5SCristian Dumitrescu 			return;
694*5074e1d5SCristian Dumitrescu 		}
695*5074e1d5SCristian Dumitrescu 
696*5074e1d5SCristian Dumitrescu 		t0 += 6;
697*5074e1d5SCristian Dumitrescu 
698*5074e1d5SCristian Dumitrescu 		status = rte_swx_pipeline_port_out_config(p->p,
699*5074e1d5SCristian Dumitrescu 			port_id,
700*5074e1d5SCristian Dumitrescu 			"ethdev",
701*5074e1d5SCristian Dumitrescu 			&params);
702*5074e1d5SCristian Dumitrescu 	} else if (strcmp(tokens[t0], "sink") == 0) {
703*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_sink_params params;
704*5074e1d5SCristian Dumitrescu 
705*5074e1d5SCristian Dumitrescu 		params.file_name = strcmp(tokens[t0 + 1], "none") ?
706*5074e1d5SCristian Dumitrescu 			tokens[t0 + 1] : NULL;
707*5074e1d5SCristian Dumitrescu 
708*5074e1d5SCristian Dumitrescu 		t0 += 2;
709*5074e1d5SCristian Dumitrescu 
710*5074e1d5SCristian Dumitrescu 		status = rte_swx_pipeline_port_out_config(p->p,
711*5074e1d5SCristian Dumitrescu 			port_id,
712*5074e1d5SCristian Dumitrescu 			"sink",
713*5074e1d5SCristian Dumitrescu 			&params);
714*5074e1d5SCristian Dumitrescu 	} else {
715*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
716*5074e1d5SCristian Dumitrescu 		return;
717*5074e1d5SCristian Dumitrescu 	}
718*5074e1d5SCristian Dumitrescu 
719*5074e1d5SCristian Dumitrescu 	if (status) {
720*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "port out error.");
721*5074e1d5SCristian Dumitrescu 		return;
722*5074e1d5SCristian Dumitrescu 	}
723*5074e1d5SCristian Dumitrescu 
724*5074e1d5SCristian Dumitrescu 	if (n_tokens != t0) {
725*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
726*5074e1d5SCristian Dumitrescu 		return;
727*5074e1d5SCristian Dumitrescu 	}
728*5074e1d5SCristian Dumitrescu }
729*5074e1d5SCristian Dumitrescu 
730*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_build_help[] =
731*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> build <spec_file>\n";
732*5074e1d5SCristian Dumitrescu 
733*5074e1d5SCristian Dumitrescu static void
734*5074e1d5SCristian Dumitrescu cmd_pipeline_build(char **tokens,
735*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
736*5074e1d5SCristian Dumitrescu 	char *out,
737*5074e1d5SCristian Dumitrescu 	size_t out_size,
738*5074e1d5SCristian Dumitrescu 	void *obj)
739*5074e1d5SCristian Dumitrescu {
740*5074e1d5SCristian Dumitrescu 	struct pipeline *p = NULL;
741*5074e1d5SCristian Dumitrescu 	FILE *spec = NULL;
742*5074e1d5SCristian Dumitrescu 	uint32_t err_line;
743*5074e1d5SCristian Dumitrescu 	const char *err_msg;
744*5074e1d5SCristian Dumitrescu 	int status;
745*5074e1d5SCristian Dumitrescu 
746*5074e1d5SCristian Dumitrescu 	if (n_tokens != 4) {
747*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
748*5074e1d5SCristian Dumitrescu 		return;
749*5074e1d5SCristian Dumitrescu 	}
750*5074e1d5SCristian Dumitrescu 
751*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, tokens[1]);
752*5074e1d5SCristian Dumitrescu 	if (!p || p->ctl) {
753*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
754*5074e1d5SCristian Dumitrescu 		return;
755*5074e1d5SCristian Dumitrescu 	}
756*5074e1d5SCristian Dumitrescu 
757*5074e1d5SCristian Dumitrescu 	spec = fopen(tokens[3], "r");
758*5074e1d5SCristian Dumitrescu 	if (!spec) {
759*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
760*5074e1d5SCristian Dumitrescu 		return;
761*5074e1d5SCristian Dumitrescu 	}
762*5074e1d5SCristian Dumitrescu 
763*5074e1d5SCristian Dumitrescu 	status = rte_swx_pipeline_build_from_spec(p->p,
764*5074e1d5SCristian Dumitrescu 		spec,
765*5074e1d5SCristian Dumitrescu 		&err_line,
766*5074e1d5SCristian Dumitrescu 		&err_msg);
767*5074e1d5SCristian Dumitrescu 	fclose(spec);
768*5074e1d5SCristian Dumitrescu 	if (status) {
769*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Error %d at line %u: %s\n.",
770*5074e1d5SCristian Dumitrescu 			status, err_line, err_msg);
771*5074e1d5SCristian Dumitrescu 		return;
772*5074e1d5SCristian Dumitrescu 	}
773*5074e1d5SCristian Dumitrescu 
774*5074e1d5SCristian Dumitrescu 	p->ctl = rte_swx_ctl_pipeline_create(p->p);
775*5074e1d5SCristian Dumitrescu 	if (!p->ctl) {
776*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Pipeline control create failed.");
777*5074e1d5SCristian Dumitrescu 		rte_swx_pipeline_free(p->p);
778*5074e1d5SCristian Dumitrescu 		return;
779*5074e1d5SCristian Dumitrescu 	}
780*5074e1d5SCristian Dumitrescu }
781*5074e1d5SCristian Dumitrescu 
782*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_table_update_help[] =
783*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> table <table_name> update <file_name_add> "
784*5074e1d5SCristian Dumitrescu "<file_name_delete> <file_name_default>";
785*5074e1d5SCristian Dumitrescu 
786*5074e1d5SCristian Dumitrescu static void
787*5074e1d5SCristian Dumitrescu cmd_pipeline_table_update(char **tokens,
788*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
789*5074e1d5SCristian Dumitrescu 	char *out,
790*5074e1d5SCristian Dumitrescu 	size_t out_size,
791*5074e1d5SCristian Dumitrescu 	void *obj)
792*5074e1d5SCristian Dumitrescu {
793*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
794*5074e1d5SCristian Dumitrescu 	char *pipeline_name, *table_name, *line = NULL;
795*5074e1d5SCristian Dumitrescu 	char *file_name_add, *file_name_delete, *file_name_default;
796*5074e1d5SCristian Dumitrescu 	FILE *file_add = NULL, *file_delete = NULL, *file_default = NULL;
797*5074e1d5SCristian Dumitrescu 	uint32_t line_id;
798*5074e1d5SCristian Dumitrescu 	int status;
799*5074e1d5SCristian Dumitrescu 
800*5074e1d5SCristian Dumitrescu 	if (n_tokens != 8) {
801*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
802*5074e1d5SCristian Dumitrescu 		return;
803*5074e1d5SCristian Dumitrescu 	}
804*5074e1d5SCristian Dumitrescu 
805*5074e1d5SCristian Dumitrescu 	pipeline_name = tokens[1];
806*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, pipeline_name);
807*5074e1d5SCristian Dumitrescu 	if (!p || !p->ctl) {
808*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
809*5074e1d5SCristian Dumitrescu 		return;
810*5074e1d5SCristian Dumitrescu 	}
811*5074e1d5SCristian Dumitrescu 
812*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "table") != 0) {
813*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
814*5074e1d5SCristian Dumitrescu 		return;
815*5074e1d5SCristian Dumitrescu 	}
816*5074e1d5SCristian Dumitrescu 
817*5074e1d5SCristian Dumitrescu 	table_name = tokens[3];
818*5074e1d5SCristian Dumitrescu 
819*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[4], "update") != 0) {
820*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "update");
821*5074e1d5SCristian Dumitrescu 		return;
822*5074e1d5SCristian Dumitrescu 	}
823*5074e1d5SCristian Dumitrescu 
824*5074e1d5SCristian Dumitrescu 	file_name_add = tokens[5];
825*5074e1d5SCristian Dumitrescu 	file_name_delete = tokens[6];
826*5074e1d5SCristian Dumitrescu 	file_name_default = tokens[7];
827*5074e1d5SCristian Dumitrescu 
828*5074e1d5SCristian Dumitrescu 	/* File open. */
829*5074e1d5SCristian Dumitrescu 	if (strcmp(file_name_add, "none")) {
830*5074e1d5SCristian Dumitrescu 		file_add = fopen(file_name_add, "r");
831*5074e1d5SCristian Dumitrescu 		if (!file_add) {
832*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "Cannot open file %s",
833*5074e1d5SCristian Dumitrescu 				file_name_add);
834*5074e1d5SCristian Dumitrescu 			goto error;
835*5074e1d5SCristian Dumitrescu 		}
836*5074e1d5SCristian Dumitrescu 	}
837*5074e1d5SCristian Dumitrescu 
838*5074e1d5SCristian Dumitrescu 	if (strcmp(file_name_delete, "none")) {
839*5074e1d5SCristian Dumitrescu 		file_add = fopen(file_name_delete, "r");
840*5074e1d5SCristian Dumitrescu 		if (!file_add) {
841*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "Cannot open file %s",
842*5074e1d5SCristian Dumitrescu 				file_name_delete);
843*5074e1d5SCristian Dumitrescu 			goto error;
844*5074e1d5SCristian Dumitrescu 		}
845*5074e1d5SCristian Dumitrescu 	}
846*5074e1d5SCristian Dumitrescu 
847*5074e1d5SCristian Dumitrescu 	if (strcmp(file_name_default, "none")) {
848*5074e1d5SCristian Dumitrescu 		file_add = fopen(file_name_default, "r");
849*5074e1d5SCristian Dumitrescu 		if (!file_add) {
850*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "Cannot open file %s",
851*5074e1d5SCristian Dumitrescu 				file_name_default);
852*5074e1d5SCristian Dumitrescu 			goto error;
853*5074e1d5SCristian Dumitrescu 		}
854*5074e1d5SCristian Dumitrescu 	}
855*5074e1d5SCristian Dumitrescu 
856*5074e1d5SCristian Dumitrescu 	if (!file_add && !file_delete && !file_default) {
857*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Nothing to be done.");
858*5074e1d5SCristian Dumitrescu 		return;
859*5074e1d5SCristian Dumitrescu 	}
860*5074e1d5SCristian Dumitrescu 
861*5074e1d5SCristian Dumitrescu 	/* Buffer allocation. */
862*5074e1d5SCristian Dumitrescu 	line = malloc(2048);
863*5074e1d5SCristian Dumitrescu 	if (!line) {
864*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
865*5074e1d5SCristian Dumitrescu 		goto error;
866*5074e1d5SCristian Dumitrescu 	}
867*5074e1d5SCristian Dumitrescu 
868*5074e1d5SCristian Dumitrescu 	/* Add. */
869*5074e1d5SCristian Dumitrescu 	if (file_add) {
870*5074e1d5SCristian Dumitrescu 		for (line_id = 1; ; line_id++) {
871*5074e1d5SCristian Dumitrescu 			struct rte_swx_table_entry *entry;
872*5074e1d5SCristian Dumitrescu 
873*5074e1d5SCristian Dumitrescu 			if (fgets(line, 2048, file_add) == NULL)
874*5074e1d5SCristian Dumitrescu 				break;
875*5074e1d5SCristian Dumitrescu 
876*5074e1d5SCristian Dumitrescu 			entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
877*5074e1d5SCristian Dumitrescu 				table_name,
878*5074e1d5SCristian Dumitrescu 				line);
879*5074e1d5SCristian Dumitrescu 			if (!entry) {
880*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size, MSG_FILE_ERR,
881*5074e1d5SCristian Dumitrescu 					file_name_add, line_id);
882*5074e1d5SCristian Dumitrescu 				goto error;
883*5074e1d5SCristian Dumitrescu 			}
884*5074e1d5SCristian Dumitrescu 
885*5074e1d5SCristian Dumitrescu 			status = rte_swx_ctl_pipeline_table_entry_add(p->ctl,
886*5074e1d5SCristian Dumitrescu 				table_name,
887*5074e1d5SCristian Dumitrescu 				entry);
888*5074e1d5SCristian Dumitrescu 			if (status) {
889*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size,
890*5074e1d5SCristian Dumitrescu 					"Invalid entry in file %s at line %u",
891*5074e1d5SCristian Dumitrescu 					file_name_add, line_id);
892*5074e1d5SCristian Dumitrescu 				goto error;
893*5074e1d5SCristian Dumitrescu 			}
894*5074e1d5SCristian Dumitrescu 		}
895*5074e1d5SCristian Dumitrescu 
896*5074e1d5SCristian Dumitrescu 		fclose(file_add);
897*5074e1d5SCristian Dumitrescu 	}
898*5074e1d5SCristian Dumitrescu 
899*5074e1d5SCristian Dumitrescu 	/* Delete. */
900*5074e1d5SCristian Dumitrescu 	if (file_delete) {
901*5074e1d5SCristian Dumitrescu 		for (line_id = 1; ; line_id++) {
902*5074e1d5SCristian Dumitrescu 			struct rte_swx_table_entry *entry;
903*5074e1d5SCristian Dumitrescu 
904*5074e1d5SCristian Dumitrescu 			if (fgets(line, 2048, file_delete) == NULL)
905*5074e1d5SCristian Dumitrescu 				break;
906*5074e1d5SCristian Dumitrescu 
907*5074e1d5SCristian Dumitrescu 			entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
908*5074e1d5SCristian Dumitrescu 				table_name,
909*5074e1d5SCristian Dumitrescu 				line);
910*5074e1d5SCristian Dumitrescu 			if (!entry) {
911*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size, MSG_FILE_ERR,
912*5074e1d5SCristian Dumitrescu 					file_name_delete, line_id);
913*5074e1d5SCristian Dumitrescu 				goto error;
914*5074e1d5SCristian Dumitrescu 			}
915*5074e1d5SCristian Dumitrescu 
916*5074e1d5SCristian Dumitrescu 			status = rte_swx_ctl_pipeline_table_entry_delete(p->ctl,
917*5074e1d5SCristian Dumitrescu 				table_name,
918*5074e1d5SCristian Dumitrescu 				entry);
919*5074e1d5SCristian Dumitrescu 			if (status)  {
920*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size,
921*5074e1d5SCristian Dumitrescu 					"Invalid entry in file %s at line %u",
922*5074e1d5SCristian Dumitrescu 					file_name_delete, line_id);
923*5074e1d5SCristian Dumitrescu 				goto error;
924*5074e1d5SCristian Dumitrescu 			}
925*5074e1d5SCristian Dumitrescu 		}
926*5074e1d5SCristian Dumitrescu 
927*5074e1d5SCristian Dumitrescu 		fclose(file_delete);
928*5074e1d5SCristian Dumitrescu 	}
929*5074e1d5SCristian Dumitrescu 
930*5074e1d5SCristian Dumitrescu 	/* Default. */
931*5074e1d5SCristian Dumitrescu 	if (file_default) {
932*5074e1d5SCristian Dumitrescu 		for (line_id = 1; ; line_id++) {
933*5074e1d5SCristian Dumitrescu 			struct rte_swx_table_entry *entry;
934*5074e1d5SCristian Dumitrescu 
935*5074e1d5SCristian Dumitrescu 			if (fgets(line, 2048, file_default) == NULL)
936*5074e1d5SCristian Dumitrescu 				break;
937*5074e1d5SCristian Dumitrescu 
938*5074e1d5SCristian Dumitrescu 			entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
939*5074e1d5SCristian Dumitrescu 				table_name,
940*5074e1d5SCristian Dumitrescu 				line);
941*5074e1d5SCristian Dumitrescu 			if (!entry) {
942*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size, MSG_FILE_ERR,
943*5074e1d5SCristian Dumitrescu 					file_name_default, line_id);
944*5074e1d5SCristian Dumitrescu 				goto error;
945*5074e1d5SCristian Dumitrescu 			}
946*5074e1d5SCristian Dumitrescu 
947*5074e1d5SCristian Dumitrescu 			status = rte_swx_ctl_pipeline_table_default_entry_add(p->ctl,
948*5074e1d5SCristian Dumitrescu 				table_name,
949*5074e1d5SCristian Dumitrescu 				entry);
950*5074e1d5SCristian Dumitrescu 			if (status) {
951*5074e1d5SCristian Dumitrescu 				snprintf(out, out_size,
952*5074e1d5SCristian Dumitrescu 					"Invalid entry in file %s at line %u",
953*5074e1d5SCristian Dumitrescu 					file_name_default, line_id);
954*5074e1d5SCristian Dumitrescu 				goto error;
955*5074e1d5SCristian Dumitrescu 			}
956*5074e1d5SCristian Dumitrescu 		}
957*5074e1d5SCristian Dumitrescu 
958*5074e1d5SCristian Dumitrescu 		fclose(file_default);
959*5074e1d5SCristian Dumitrescu 	}
960*5074e1d5SCristian Dumitrescu 
961*5074e1d5SCristian Dumitrescu 	status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
962*5074e1d5SCristian Dumitrescu 	if (status) {
963*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Commit failed.");
964*5074e1d5SCristian Dumitrescu 		goto error;
965*5074e1d5SCristian Dumitrescu 	}
966*5074e1d5SCristian Dumitrescu 
967*5074e1d5SCristian Dumitrescu 	free(line);
968*5074e1d5SCristian Dumitrescu 
969*5074e1d5SCristian Dumitrescu 	rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name);
970*5074e1d5SCristian Dumitrescu 
971*5074e1d5SCristian Dumitrescu 	return;
972*5074e1d5SCristian Dumitrescu 
973*5074e1d5SCristian Dumitrescu error:
974*5074e1d5SCristian Dumitrescu 	rte_swx_ctl_pipeline_abort(p->ctl);
975*5074e1d5SCristian Dumitrescu 	free(line);
976*5074e1d5SCristian Dumitrescu 	if (file_add)
977*5074e1d5SCristian Dumitrescu 		fclose(file_add);
978*5074e1d5SCristian Dumitrescu 	if (file_delete)
979*5074e1d5SCristian Dumitrescu 		fclose(file_delete);
980*5074e1d5SCristian Dumitrescu 	if (file_default)
981*5074e1d5SCristian Dumitrescu 		fclose(file_default);
982*5074e1d5SCristian Dumitrescu }
983*5074e1d5SCristian Dumitrescu 
984*5074e1d5SCristian Dumitrescu static const char cmd_pipeline_stats_help[] =
985*5074e1d5SCristian Dumitrescu "pipeline <pipeline_name> stats\n";
986*5074e1d5SCristian Dumitrescu 
987*5074e1d5SCristian Dumitrescu static void
988*5074e1d5SCristian Dumitrescu cmd_pipeline_stats(char **tokens,
989*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
990*5074e1d5SCristian Dumitrescu 	char *out,
991*5074e1d5SCristian Dumitrescu 	size_t out_size,
992*5074e1d5SCristian Dumitrescu 	void *obj)
993*5074e1d5SCristian Dumitrescu {
994*5074e1d5SCristian Dumitrescu 	struct rte_swx_ctl_pipeline_info info;
995*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
996*5074e1d5SCristian Dumitrescu 	uint32_t i;
997*5074e1d5SCristian Dumitrescu 	int status;
998*5074e1d5SCristian Dumitrescu 
999*5074e1d5SCristian Dumitrescu 	if (n_tokens != 3) {
1000*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1001*5074e1d5SCristian Dumitrescu 		return;
1002*5074e1d5SCristian Dumitrescu 	}
1003*5074e1d5SCristian Dumitrescu 
1004*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, tokens[1]);
1005*5074e1d5SCristian Dumitrescu 	if (!p || !p->ctl) {
1006*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1007*5074e1d5SCristian Dumitrescu 		return;
1008*5074e1d5SCristian Dumitrescu 	}
1009*5074e1d5SCristian Dumitrescu 
1010*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "stats")) {
1011*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1012*5074e1d5SCristian Dumitrescu 		return;
1013*5074e1d5SCristian Dumitrescu 	}
1014*5074e1d5SCristian Dumitrescu 
1015*5074e1d5SCristian Dumitrescu 	status = rte_swx_ctl_pipeline_info_get(p->p, &info);
1016*5074e1d5SCristian Dumitrescu 	if (status) {
1017*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "Pipeline info get error.");
1018*5074e1d5SCristian Dumitrescu 		return;
1019*5074e1d5SCristian Dumitrescu 	}
1020*5074e1d5SCristian Dumitrescu 
1021*5074e1d5SCristian Dumitrescu 	snprintf(out, out_size, "Input ports:\n");
1022*5074e1d5SCristian Dumitrescu 	out_size -= strlen(out);
1023*5074e1d5SCristian Dumitrescu 	out += strlen(out);
1024*5074e1d5SCristian Dumitrescu 
1025*5074e1d5SCristian Dumitrescu 	for (i = 0; i < info.n_ports_in; i++) {
1026*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_in_stats stats;
1027*5074e1d5SCristian Dumitrescu 
1028*5074e1d5SCristian Dumitrescu 		rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
1029*5074e1d5SCristian Dumitrescu 
1030*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\tPort %u:"
1031*5074e1d5SCristian Dumitrescu 			" packets %" PRIu64
1032*5074e1d5SCristian Dumitrescu 			" bytes %" PRIu64
1033*5074e1d5SCristian Dumitrescu 			" empty %" PRIu64 "\n",
1034*5074e1d5SCristian Dumitrescu 			i, stats.n_pkts, stats.n_bytes, stats.n_empty);
1035*5074e1d5SCristian Dumitrescu 		out_size -= strlen(out);
1036*5074e1d5SCristian Dumitrescu 		out += strlen(out);
1037*5074e1d5SCristian Dumitrescu 	}
1038*5074e1d5SCristian Dumitrescu 
1039*5074e1d5SCristian Dumitrescu 	snprintf(out, out_size, "Output ports:\n");
1040*5074e1d5SCristian Dumitrescu 	out_size -= strlen(out);
1041*5074e1d5SCristian Dumitrescu 	out += strlen(out);
1042*5074e1d5SCristian Dumitrescu 
1043*5074e1d5SCristian Dumitrescu 	for (i = 0; i < info.n_ports_out; i++) {
1044*5074e1d5SCristian Dumitrescu 		struct rte_swx_port_out_stats stats;
1045*5074e1d5SCristian Dumitrescu 
1046*5074e1d5SCristian Dumitrescu 		rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
1047*5074e1d5SCristian Dumitrescu 
1048*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\tPort %u:"
1049*5074e1d5SCristian Dumitrescu 			" packets %" PRIu64
1050*5074e1d5SCristian Dumitrescu 			" bytes %" PRIu64 "\n",
1051*5074e1d5SCristian Dumitrescu 			i, stats.n_pkts, stats.n_bytes);
1052*5074e1d5SCristian Dumitrescu 		out_size -= strlen(out);
1053*5074e1d5SCristian Dumitrescu 		out += strlen(out);
1054*5074e1d5SCristian Dumitrescu 	}
1055*5074e1d5SCristian Dumitrescu }
1056*5074e1d5SCristian Dumitrescu 
1057*5074e1d5SCristian Dumitrescu static const char cmd_thread_pipeline_enable_help[] =
1058*5074e1d5SCristian Dumitrescu "thread <thread_id> pipeline <pipeline_name> enable\n";
1059*5074e1d5SCristian Dumitrescu 
1060*5074e1d5SCristian Dumitrescu static void
1061*5074e1d5SCristian Dumitrescu cmd_thread_pipeline_enable(char **tokens,
1062*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
1063*5074e1d5SCristian Dumitrescu 	char *out,
1064*5074e1d5SCristian Dumitrescu 	size_t out_size,
1065*5074e1d5SCristian Dumitrescu 	void *obj)
1066*5074e1d5SCristian Dumitrescu {
1067*5074e1d5SCristian Dumitrescu 	char *pipeline_name;
1068*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
1069*5074e1d5SCristian Dumitrescu 	uint32_t thread_id;
1070*5074e1d5SCristian Dumitrescu 	int status;
1071*5074e1d5SCristian Dumitrescu 
1072*5074e1d5SCristian Dumitrescu 	if (n_tokens != 5) {
1073*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1074*5074e1d5SCristian Dumitrescu 		return;
1075*5074e1d5SCristian Dumitrescu 	}
1076*5074e1d5SCristian Dumitrescu 
1077*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1078*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1079*5074e1d5SCristian Dumitrescu 		return;
1080*5074e1d5SCristian Dumitrescu 	}
1081*5074e1d5SCristian Dumitrescu 
1082*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "pipeline") != 0) {
1083*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1084*5074e1d5SCristian Dumitrescu 		return;
1085*5074e1d5SCristian Dumitrescu 	}
1086*5074e1d5SCristian Dumitrescu 
1087*5074e1d5SCristian Dumitrescu 	pipeline_name = tokens[3];
1088*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, pipeline_name);
1089*5074e1d5SCristian Dumitrescu 	if (!p || !p->ctl) {
1090*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1091*5074e1d5SCristian Dumitrescu 		return;
1092*5074e1d5SCristian Dumitrescu 	}
1093*5074e1d5SCristian Dumitrescu 
1094*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[4], "enable") != 0) {
1095*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1096*5074e1d5SCristian Dumitrescu 		return;
1097*5074e1d5SCristian Dumitrescu 	}
1098*5074e1d5SCristian Dumitrescu 
1099*5074e1d5SCristian Dumitrescu 	status = thread_pipeline_enable(thread_id, obj, pipeline_name);
1100*5074e1d5SCristian Dumitrescu 	if (status) {
1101*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
1102*5074e1d5SCristian Dumitrescu 		return;
1103*5074e1d5SCristian Dumitrescu 	}
1104*5074e1d5SCristian Dumitrescu }
1105*5074e1d5SCristian Dumitrescu 
1106*5074e1d5SCristian Dumitrescu static const char cmd_thread_pipeline_disable_help[] =
1107*5074e1d5SCristian Dumitrescu "thread <thread_id> pipeline <pipeline_name> disable\n";
1108*5074e1d5SCristian Dumitrescu 
1109*5074e1d5SCristian Dumitrescu static void
1110*5074e1d5SCristian Dumitrescu cmd_thread_pipeline_disable(char **tokens,
1111*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens,
1112*5074e1d5SCristian Dumitrescu 	char *out,
1113*5074e1d5SCristian Dumitrescu 	size_t out_size,
1114*5074e1d5SCristian Dumitrescu 	void *obj)
1115*5074e1d5SCristian Dumitrescu {
1116*5074e1d5SCristian Dumitrescu 	struct pipeline *p;
1117*5074e1d5SCristian Dumitrescu 	char *pipeline_name;
1118*5074e1d5SCristian Dumitrescu 	uint32_t thread_id;
1119*5074e1d5SCristian Dumitrescu 	int status;
1120*5074e1d5SCristian Dumitrescu 
1121*5074e1d5SCristian Dumitrescu 	if (n_tokens != 5) {
1122*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1123*5074e1d5SCristian Dumitrescu 		return;
1124*5074e1d5SCristian Dumitrescu 	}
1125*5074e1d5SCristian Dumitrescu 
1126*5074e1d5SCristian Dumitrescu 	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1127*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1128*5074e1d5SCristian Dumitrescu 		return;
1129*5074e1d5SCristian Dumitrescu 	}
1130*5074e1d5SCristian Dumitrescu 
1131*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[2], "pipeline") != 0) {
1132*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1133*5074e1d5SCristian Dumitrescu 		return;
1134*5074e1d5SCristian Dumitrescu 	}
1135*5074e1d5SCristian Dumitrescu 
1136*5074e1d5SCristian Dumitrescu 	pipeline_name = tokens[3];
1137*5074e1d5SCristian Dumitrescu 	p = pipeline_find(obj, pipeline_name);
1138*5074e1d5SCristian Dumitrescu 	if (!p || !p->ctl) {
1139*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1140*5074e1d5SCristian Dumitrescu 		return;
1141*5074e1d5SCristian Dumitrescu 	}
1142*5074e1d5SCristian Dumitrescu 
1143*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[4], "disable") != 0) {
1144*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
1145*5074e1d5SCristian Dumitrescu 		return;
1146*5074e1d5SCristian Dumitrescu 	}
1147*5074e1d5SCristian Dumitrescu 
1148*5074e1d5SCristian Dumitrescu 	status = thread_pipeline_disable(thread_id, obj, pipeline_name);
1149*5074e1d5SCristian Dumitrescu 	if (status) {
1150*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_CMD_FAIL,
1151*5074e1d5SCristian Dumitrescu 			"thread pipeline disable");
1152*5074e1d5SCristian Dumitrescu 		return;
1153*5074e1d5SCristian Dumitrescu 	}
1154*5074e1d5SCristian Dumitrescu }
1155*5074e1d5SCristian Dumitrescu 
1156*5074e1d5SCristian Dumitrescu static void
1157*5074e1d5SCristian Dumitrescu cmd_help(char **tokens,
1158*5074e1d5SCristian Dumitrescu 	 uint32_t n_tokens,
1159*5074e1d5SCristian Dumitrescu 	 char *out,
1160*5074e1d5SCristian Dumitrescu 	 size_t out_size,
1161*5074e1d5SCristian Dumitrescu 	 void *arg __rte_unused)
1162*5074e1d5SCristian Dumitrescu {
1163*5074e1d5SCristian Dumitrescu 	tokens++;
1164*5074e1d5SCristian Dumitrescu 	n_tokens--;
1165*5074e1d5SCristian Dumitrescu 
1166*5074e1d5SCristian Dumitrescu 	if (n_tokens == 0) {
1167*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size,
1168*5074e1d5SCristian Dumitrescu 			"Type 'help <command>' for command details.\n\n");
1169*5074e1d5SCristian Dumitrescu 		return;
1170*5074e1d5SCristian Dumitrescu 	}
1171*5074e1d5SCristian Dumitrescu 
1172*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "mempool") == 0) {
1173*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
1174*5074e1d5SCristian Dumitrescu 		return;
1175*5074e1d5SCristian Dumitrescu 	}
1176*5074e1d5SCristian Dumitrescu 
1177*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "link") == 0) {
1178*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n", cmd_link_help);
1179*5074e1d5SCristian Dumitrescu 		return;
1180*5074e1d5SCristian Dumitrescu 	}
1181*5074e1d5SCristian Dumitrescu 
1182*5074e1d5SCristian Dumitrescu 	if ((strcmp(tokens[0], "pipeline") == 0) &&
1183*5074e1d5SCristian Dumitrescu 		((n_tokens == 1) && (strcmp(tokens[2], "create")) == 0)) {
1184*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
1185*5074e1d5SCristian Dumitrescu 		return;
1186*5074e1d5SCristian Dumitrescu 	}
1187*5074e1d5SCristian Dumitrescu 
1188*5074e1d5SCristian Dumitrescu 	if ((strcmp(tokens[0], "pipeline") == 0) &&
1189*5074e1d5SCristian Dumitrescu 		(strcmp(tokens[1], "port") == 0)) {
1190*5074e1d5SCristian Dumitrescu 		if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) {
1191*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "\n%s\n",
1192*5074e1d5SCristian Dumitrescu 				cmd_pipeline_port_in_help);
1193*5074e1d5SCristian Dumitrescu 			return;
1194*5074e1d5SCristian Dumitrescu 		}
1195*5074e1d5SCristian Dumitrescu 
1196*5074e1d5SCristian Dumitrescu 		if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) {
1197*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "\n%s\n",
1198*5074e1d5SCristian Dumitrescu 				cmd_pipeline_port_out_help);
1199*5074e1d5SCristian Dumitrescu 			return;
1200*5074e1d5SCristian Dumitrescu 		}
1201*5074e1d5SCristian Dumitrescu 	}
1202*5074e1d5SCristian Dumitrescu 
1203*5074e1d5SCristian Dumitrescu 	if ((strcmp(tokens[0], "pipeline") == 0) &&
1204*5074e1d5SCristian Dumitrescu 		((n_tokens >= 2) && (strcmp(tokens[2], "build")) == 0)) {
1205*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
1206*5074e1d5SCristian Dumitrescu 		return;
1207*5074e1d5SCristian Dumitrescu 	}
1208*5074e1d5SCristian Dumitrescu 
1209*5074e1d5SCristian Dumitrescu 	if ((strcmp(tokens[0], "pipeline") == 0) &&
1210*5074e1d5SCristian Dumitrescu 		((n_tokens >= 2) && (strcmp(tokens[2], "table")) == 0)) {
1211*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n",
1212*5074e1d5SCristian Dumitrescu 			cmd_pipeline_table_update_help);
1213*5074e1d5SCristian Dumitrescu 		return;
1214*5074e1d5SCristian Dumitrescu 	}
1215*5074e1d5SCristian Dumitrescu 
1216*5074e1d5SCristian Dumitrescu 	if ((strcmp(tokens[0], "pipeline") == 0) &&
1217*5074e1d5SCristian Dumitrescu 		((n_tokens >= 2) && (strcmp(tokens[2], "stats")) == 0)) {
1218*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
1219*5074e1d5SCristian Dumitrescu 		return;
1220*5074e1d5SCristian Dumitrescu 	}
1221*5074e1d5SCristian Dumitrescu 
1222*5074e1d5SCristian Dumitrescu 	if ((n_tokens == 3) &&
1223*5074e1d5SCristian Dumitrescu 		(strcmp(tokens[0], "thread") == 0) &&
1224*5074e1d5SCristian Dumitrescu 		(strcmp(tokens[1], "pipeline") == 0)) {
1225*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[2], "enable") == 0) {
1226*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "\n%s\n",
1227*5074e1d5SCristian Dumitrescu 				cmd_thread_pipeline_enable_help);
1228*5074e1d5SCristian Dumitrescu 			return;
1229*5074e1d5SCristian Dumitrescu 		}
1230*5074e1d5SCristian Dumitrescu 
1231*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[2], "disable") == 0) {
1232*5074e1d5SCristian Dumitrescu 			snprintf(out, out_size, "\n%s\n",
1233*5074e1d5SCristian Dumitrescu 				cmd_thread_pipeline_disable_help);
1234*5074e1d5SCristian Dumitrescu 			return;
1235*5074e1d5SCristian Dumitrescu 		}
1236*5074e1d5SCristian Dumitrescu 	}
1237*5074e1d5SCristian Dumitrescu 
1238*5074e1d5SCristian Dumitrescu 	snprintf(out, out_size, "Invalid command\n");
1239*5074e1d5SCristian Dumitrescu }
1240*5074e1d5SCristian Dumitrescu 
1241*5074e1d5SCristian Dumitrescu void
1242*5074e1d5SCristian Dumitrescu cli_process(char *in, char *out, size_t out_size, void *obj)
1243*5074e1d5SCristian Dumitrescu {
1244*5074e1d5SCristian Dumitrescu 	char *tokens[CMD_MAX_TOKENS];
1245*5074e1d5SCristian Dumitrescu 	uint32_t n_tokens = RTE_DIM(tokens);
1246*5074e1d5SCristian Dumitrescu 	int status;
1247*5074e1d5SCristian Dumitrescu 
1248*5074e1d5SCristian Dumitrescu 	if (is_comment(in))
1249*5074e1d5SCristian Dumitrescu 		return;
1250*5074e1d5SCristian Dumitrescu 
1251*5074e1d5SCristian Dumitrescu 	status = parse_tokenize_string(in, tokens, &n_tokens);
1252*5074e1d5SCristian Dumitrescu 	if (status) {
1253*5074e1d5SCristian Dumitrescu 		snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
1254*5074e1d5SCristian Dumitrescu 		return;
1255*5074e1d5SCristian Dumitrescu 	}
1256*5074e1d5SCristian Dumitrescu 
1257*5074e1d5SCristian Dumitrescu 	if (n_tokens == 0)
1258*5074e1d5SCristian Dumitrescu 		return;
1259*5074e1d5SCristian Dumitrescu 
1260*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "help") == 0) {
1261*5074e1d5SCristian Dumitrescu 		cmd_help(tokens, n_tokens, out, out_size, obj);
1262*5074e1d5SCristian Dumitrescu 		return;
1263*5074e1d5SCristian Dumitrescu 	}
1264*5074e1d5SCristian Dumitrescu 
1265*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "mempool") == 0) {
1266*5074e1d5SCristian Dumitrescu 		cmd_mempool(tokens, n_tokens, out, out_size, obj);
1267*5074e1d5SCristian Dumitrescu 		return;
1268*5074e1d5SCristian Dumitrescu 	}
1269*5074e1d5SCristian Dumitrescu 
1270*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "link") == 0) {
1271*5074e1d5SCristian Dumitrescu 		if (strcmp(tokens[1], "show") == 0) {
1272*5074e1d5SCristian Dumitrescu 			cmd_link_show(tokens, n_tokens, out, out_size, obj);
1273*5074e1d5SCristian Dumitrescu 			return;
1274*5074e1d5SCristian Dumitrescu 		}
1275*5074e1d5SCristian Dumitrescu 
1276*5074e1d5SCristian Dumitrescu 		cmd_link(tokens, n_tokens, out, out_size, obj);
1277*5074e1d5SCristian Dumitrescu 		return;
1278*5074e1d5SCristian Dumitrescu 	}
1279*5074e1d5SCristian Dumitrescu 
1280*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "pipeline") == 0) {
1281*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 3) &&
1282*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "create") == 0)) {
1283*5074e1d5SCristian Dumitrescu 			cmd_pipeline_create(tokens, n_tokens, out, out_size,
1284*5074e1d5SCristian Dumitrescu 				obj);
1285*5074e1d5SCristian Dumitrescu 			return;
1286*5074e1d5SCristian Dumitrescu 		}
1287*5074e1d5SCristian Dumitrescu 
1288*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 4) &&
1289*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "port") == 0) &&
1290*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[3], "in") == 0)) {
1291*5074e1d5SCristian Dumitrescu 			cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
1292*5074e1d5SCristian Dumitrescu 				obj);
1293*5074e1d5SCristian Dumitrescu 			return;
1294*5074e1d5SCristian Dumitrescu 		}
1295*5074e1d5SCristian Dumitrescu 
1296*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 4) &&
1297*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "port") == 0) &&
1298*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[3], "out") == 0)) {
1299*5074e1d5SCristian Dumitrescu 			cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
1300*5074e1d5SCristian Dumitrescu 				obj);
1301*5074e1d5SCristian Dumitrescu 			return;
1302*5074e1d5SCristian Dumitrescu 		}
1303*5074e1d5SCristian Dumitrescu 
1304*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 3) &&
1305*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "build") == 0)) {
1306*5074e1d5SCristian Dumitrescu 			cmd_pipeline_build(tokens, n_tokens, out, out_size,
1307*5074e1d5SCristian Dumitrescu 				obj);
1308*5074e1d5SCristian Dumitrescu 			return;
1309*5074e1d5SCristian Dumitrescu 		}
1310*5074e1d5SCristian Dumitrescu 
1311*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 3) &&
1312*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "table") == 0)) {
1313*5074e1d5SCristian Dumitrescu 			cmd_pipeline_table_update(tokens, n_tokens, out,
1314*5074e1d5SCristian Dumitrescu 				out_size, obj);
1315*5074e1d5SCristian Dumitrescu 			return;
1316*5074e1d5SCristian Dumitrescu 		}
1317*5074e1d5SCristian Dumitrescu 
1318*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 3) &&
1319*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[2], "stats") == 0)) {
1320*5074e1d5SCristian Dumitrescu 			cmd_pipeline_stats(tokens, n_tokens, out, out_size,
1321*5074e1d5SCristian Dumitrescu 				obj);
1322*5074e1d5SCristian Dumitrescu 			return;
1323*5074e1d5SCristian Dumitrescu 		}
1324*5074e1d5SCristian Dumitrescu 	}
1325*5074e1d5SCristian Dumitrescu 
1326*5074e1d5SCristian Dumitrescu 	if (strcmp(tokens[0], "thread") == 0) {
1327*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 5) &&
1328*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[4], "enable") == 0)) {
1329*5074e1d5SCristian Dumitrescu 			cmd_thread_pipeline_enable(tokens, n_tokens,
1330*5074e1d5SCristian Dumitrescu 				out, out_size, obj);
1331*5074e1d5SCristian Dumitrescu 			return;
1332*5074e1d5SCristian Dumitrescu 		}
1333*5074e1d5SCristian Dumitrescu 
1334*5074e1d5SCristian Dumitrescu 		if ((n_tokens >= 5) &&
1335*5074e1d5SCristian Dumitrescu 			(strcmp(tokens[4], "disable") == 0)) {
1336*5074e1d5SCristian Dumitrescu 			cmd_thread_pipeline_disable(tokens, n_tokens,
1337*5074e1d5SCristian Dumitrescu 				out, out_size, obj);
1338*5074e1d5SCristian Dumitrescu 			return;
1339*5074e1d5SCristian Dumitrescu 		}
1340*5074e1d5SCristian Dumitrescu 	}
1341*5074e1d5SCristian Dumitrescu 
1342*5074e1d5SCristian Dumitrescu 	snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
1343*5074e1d5SCristian Dumitrescu }
1344*5074e1d5SCristian Dumitrescu 
1345*5074e1d5SCristian Dumitrescu int
1346*5074e1d5SCristian Dumitrescu cli_script_process(const char *file_name,
1347*5074e1d5SCristian Dumitrescu 	size_t msg_in_len_max,
1348*5074e1d5SCristian Dumitrescu 	size_t msg_out_len_max,
1349*5074e1d5SCristian Dumitrescu 	void *obj)
1350*5074e1d5SCristian Dumitrescu {
1351*5074e1d5SCristian Dumitrescu 	char *msg_in = NULL, *msg_out = NULL;
1352*5074e1d5SCristian Dumitrescu 	FILE *f = NULL;
1353*5074e1d5SCristian Dumitrescu 
1354*5074e1d5SCristian Dumitrescu 	/* Check input arguments */
1355*5074e1d5SCristian Dumitrescu 	if ((file_name == NULL) ||
1356*5074e1d5SCristian Dumitrescu 		(strlen(file_name) == 0) ||
1357*5074e1d5SCristian Dumitrescu 		(msg_in_len_max == 0) ||
1358*5074e1d5SCristian Dumitrescu 		(msg_out_len_max == 0))
1359*5074e1d5SCristian Dumitrescu 		return -EINVAL;
1360*5074e1d5SCristian Dumitrescu 
1361*5074e1d5SCristian Dumitrescu 	msg_in = malloc(msg_in_len_max + 1);
1362*5074e1d5SCristian Dumitrescu 	msg_out = malloc(msg_out_len_max + 1);
1363*5074e1d5SCristian Dumitrescu 	if ((msg_in == NULL) ||
1364*5074e1d5SCristian Dumitrescu 		(msg_out == NULL)) {
1365*5074e1d5SCristian Dumitrescu 		free(msg_out);
1366*5074e1d5SCristian Dumitrescu 		free(msg_in);
1367*5074e1d5SCristian Dumitrescu 		return -ENOMEM;
1368*5074e1d5SCristian Dumitrescu 	}
1369*5074e1d5SCristian Dumitrescu 
1370*5074e1d5SCristian Dumitrescu 	/* Open input file */
1371*5074e1d5SCristian Dumitrescu 	f = fopen(file_name, "r");
1372*5074e1d5SCristian Dumitrescu 	if (f == NULL) {
1373*5074e1d5SCristian Dumitrescu 		free(msg_out);
1374*5074e1d5SCristian Dumitrescu 		free(msg_in);
1375*5074e1d5SCristian Dumitrescu 		return -EIO;
1376*5074e1d5SCristian Dumitrescu 	}
1377*5074e1d5SCristian Dumitrescu 
1378*5074e1d5SCristian Dumitrescu 	/* Read file */
1379*5074e1d5SCristian Dumitrescu 	for ( ; ; ) {
1380*5074e1d5SCristian Dumitrescu 		if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
1381*5074e1d5SCristian Dumitrescu 			break;
1382*5074e1d5SCristian Dumitrescu 
1383*5074e1d5SCristian Dumitrescu 		printf("%s", msg_in);
1384*5074e1d5SCristian Dumitrescu 		msg_out[0] = 0;
1385*5074e1d5SCristian Dumitrescu 
1386*5074e1d5SCristian Dumitrescu 		cli_process(msg_in,
1387*5074e1d5SCristian Dumitrescu 			msg_out,
1388*5074e1d5SCristian Dumitrescu 			msg_out_len_max,
1389*5074e1d5SCristian Dumitrescu 			obj);
1390*5074e1d5SCristian Dumitrescu 
1391*5074e1d5SCristian Dumitrescu 		if (strlen(msg_out))
1392*5074e1d5SCristian Dumitrescu 			printf("%s", msg_out);
1393*5074e1d5SCristian Dumitrescu 	}
1394*5074e1d5SCristian Dumitrescu 
1395*5074e1d5SCristian Dumitrescu 	/* Close file */
1396*5074e1d5SCristian Dumitrescu 	fclose(f);
1397*5074e1d5SCristian Dumitrescu 	free(msg_out);
1398*5074e1d5SCristian Dumitrescu 	free(msg_in);
1399*5074e1d5SCristian Dumitrescu 	return 0;
1400*5074e1d5SCristian Dumitrescu }
1401