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