examples/ip_pipeline: add enable and disable commands
[dpdk.git] / examples / ip_pipeline / cli.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <rte_common.h>
11
12 #include "cli.h"
13 #include "kni.h"
14 #include "link.h"
15 #include "mempool.h"
16 #include "parser.h"
17 #include "pipeline.h"
18 #include "swq.h"
19 #include "tap.h"
20 #include "thread.h"
21 #include "tmgr.h"
22
23 #ifndef CMD_MAX_TOKENS
24 #define CMD_MAX_TOKENS     256
25 #endif
26
27 #define MSG_OUT_OF_MEMORY  "Not enough memory.\n"
28 #define MSG_CMD_UNKNOWN    "Unknown command \"%s\".\n"
29 #define MSG_CMD_UNIMPLEM   "Command \"%s\" not implemented.\n"
30 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
31 #define MSG_ARG_TOO_MANY   "Too many arguments for command \"%s\".\n"
32 #define MSG_ARG_MISMATCH   "Wrong number of arguments for command \"%s\".\n"
33 #define MSG_ARG_NOT_FOUND  "Argument \"%s\" not found.\n"
34 #define MSG_ARG_INVALID    "Invalid value for argument \"%s\".\n"
35 #define MSG_FILE_ERR       "Error in file \"%s\" at line %u.\n"
36 #define MSG_CMD_FAIL       "Command \"%s\" failed.\n"
37
38 static int
39 is_comment(char *in)
40 {
41         if ((strlen(in) && index("!#%;", in[0])) ||
42                 (strncmp(in, "//", 2) == 0) ||
43                 (strncmp(in, "--", 2) == 0))
44                 return 1;
45
46         return 0;
47 }
48
49 /**
50  * mempool <mempool_name>
51  *  buffer <buffer_size>
52  *  pool <pool_size>
53  *  cache <cache_size>
54  *  cpu <cpu_id>
55  */
56 static void
57 cmd_mempool(char **tokens,
58         uint32_t n_tokens,
59         char *out,
60         size_t out_size)
61 {
62         struct mempool_params p;
63         char *name;
64         struct mempool *mempool;
65
66         if (n_tokens != 10) {
67                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
68                 return;
69         }
70
71         name = tokens[1];
72
73         if (strcmp(tokens[2], "buffer") != 0) {
74                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
75                 return;
76         }
77
78         if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
79                 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
80                 return;
81         }
82
83         if (strcmp(tokens[4], "pool") != 0) {
84                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
85                 return;
86         }
87
88         if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
89                 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
90                 return;
91         }
92
93         if (strcmp(tokens[6], "cache") != 0) {
94                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
95                 return;
96         }
97
98         if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
99                 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
100                 return;
101         }
102
103         if (strcmp(tokens[8], "cpu") != 0) {
104                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
105                 return;
106         }
107
108         if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
109                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
110                 return;
111         }
112
113         mempool = mempool_create(name, &p);
114         if (mempool == NULL) {
115                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
116                 return;
117         }
118 }
119
120 /**
121  * link <link_name>
122  *  dev <device_name> | port <port_id>
123  *  rxq <n_queues> <queue_size> <mempool_name>
124  *  txq <n_queues> <queue_size>
125  *  promiscuous on | off
126  *  [rss <qid_0> ... <qid_n>]
127  */
128 static void
129 cmd_link(char **tokens,
130         uint32_t n_tokens,
131         char *out,
132         size_t out_size)
133 {
134         struct link_params p;
135         struct link_params_rss rss;
136         struct link *link;
137         char *name;
138
139         if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
140                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
141                 return;
142         }
143         name = tokens[1];
144
145         if (strcmp(tokens[2], "dev") == 0)
146                 p.dev_name = tokens[3];
147         else if (strcmp(tokens[2], "port") == 0) {
148                 p.dev_name = NULL;
149
150                 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
151                         snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
152                         return;
153                 }
154         } else {
155                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
156                 return;
157         }
158
159         if (strcmp(tokens[4], "rxq") != 0) {
160                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
161                 return;
162         }
163
164         if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
165                 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
166                 return;
167         }
168         if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
169                 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
170                 return;
171         }
172
173         p.rx.mempool_name = tokens[7];
174
175         if (strcmp(tokens[8], "txq") != 0) {
176                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
177                 return;
178         }
179
180         if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
181                 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
182                 return;
183         }
184
185         if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
186                 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
187                 return;
188         }
189
190         if (strcmp(tokens[11], "promiscuous") != 0) {
191                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
192                 return;
193         }
194
195         if (strcmp(tokens[12], "on") == 0)
196                 p.promiscuous = 1;
197         else if (strcmp(tokens[12], "off") == 0)
198                 p.promiscuous = 0;
199         else {
200                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
201                 return;
202         }
203
204         /* RSS */
205         p.rx.rss = NULL;
206         if (n_tokens > 13) {
207                 uint32_t queue_id, i;
208
209                 if (strcmp(tokens[13], "rss") != 0) {
210                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
211                         return;
212                 }
213
214                 p.rx.rss = &rss;
215
216                 rss.n_queues = 0;
217                 for (i = 14; i < n_tokens; i++) {
218                         if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
219                                 snprintf(out, out_size, MSG_ARG_INVALID,
220                                         "queue_id");
221                                 return;
222                         }
223
224                         rss.queue_id[rss.n_queues] = queue_id;
225                         rss.n_queues++;
226                 }
227         }
228
229         link = link_create(name, &p);
230         if (link == NULL) {
231                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
232                 return;
233         }
234 }
235
236 /**
237  * swq <swq_name>
238  *  size <size>
239  *  cpu <cpu_id>
240  */
241 static void
242 cmd_swq(char **tokens,
243         uint32_t n_tokens,
244         char *out,
245         size_t out_size)
246 {
247         struct swq_params p;
248         char *name;
249         struct swq *swq;
250
251         if (n_tokens != 6) {
252                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
253                 return;
254         }
255
256         name = tokens[1];
257
258         if (strcmp(tokens[2], "size") != 0) {
259                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
260                 return;
261         }
262
263         if (parser_read_uint32(&p.size, tokens[3]) != 0) {
264                 snprintf(out, out_size, MSG_ARG_INVALID, "size");
265                 return;
266         }
267
268         if (strcmp(tokens[4], "cpu") != 0) {
269                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
270                 return;
271         }
272
273         if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) {
274                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
275                 return;
276         }
277
278         swq = swq_create(name, &p);
279         if (swq == NULL) {
280                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
281                 return;
282         }
283 }
284
285 /**
286  * tmgr subport profile
287  *  <tb_rate> <tb_size>
288  *  <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>
289  *  <tc_period>
290  */
291 static void
292 cmd_tmgr_subport_profile(char **tokens,
293         uint32_t n_tokens,
294         char *out,
295         size_t out_size)
296 {
297         struct rte_sched_subport_params p;
298         int status, i;
299
300         if (n_tokens != 10) {
301                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
302                 return;
303         }
304
305         if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) {
306                 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
307                 return;
308         }
309
310         if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) {
311                 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
312                 return;
313         }
314
315         for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
316                 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) {
317                         snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
318                         return;
319                 }
320
321         if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) {
322                 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
323                 return;
324         }
325
326         status = tmgr_subport_profile_add(&p);
327         if (status != 0) {
328                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
329                 return;
330         }
331 }
332
333 /**
334  * tmgr pipe profile
335  *  <tb_rate> <tb_size>
336  *  <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>
337  *  <tc_period>
338  *  <tc_ov_weight>
339  *  <wrr_weight0..15>
340  */
341 static void
342 cmd_tmgr_pipe_profile(char **tokens,
343         uint32_t n_tokens,
344         char *out,
345         size_t out_size)
346 {
347         struct rte_sched_pipe_params p;
348         int status, i;
349
350         if (n_tokens != 27) {
351                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
352                 return;
353         }
354
355         if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) {
356                 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
357                 return;
358         }
359
360         if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) {
361                 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
362                 return;
363         }
364
365         for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
366                 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) {
367                         snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
368                         return;
369                 }
370
371         if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) {
372                 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
373                 return;
374         }
375
376 #ifdef RTE_SCHED_SUBPORT_TC_OV
377         if (parser_read_uint8(&p.tc_ov_weight, tokens[10]) != 0) {
378                 snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight");
379                 return;
380         }
381 #endif
382
383         for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++)
384                 if (parser_read_uint8(&p.wrr_weights[i], tokens[11 + i]) != 0) {
385                         snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights");
386                         return;
387                 }
388
389         status = tmgr_pipe_profile_add(&p);
390         if (status != 0) {
391                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
392                 return;
393         }
394 }
395
396 /**
397  * tmgr <tmgr_name>
398  *  rate <rate>
399  *  spp <n_subports_per_port>
400  *  pps <n_pipes_per_subport>
401  *  qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3>
402  *  fo <frame_overhead>
403  *  mtu <mtu>
404  *  cpu <cpu_id>
405  */
406 static void
407 cmd_tmgr(char **tokens,
408         uint32_t n_tokens,
409         char *out,
410         size_t out_size)
411 {
412         struct tmgr_port_params p;
413         char *name;
414         struct tmgr_port *tmgr_port;
415         int i;
416
417         if (n_tokens != 19) {
418                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
419                 return;
420         }
421
422         name = tokens[1];
423
424         if (strcmp(tokens[2], "rate") != 0) {
425                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
426                 return;
427         }
428
429         if (parser_read_uint32(&p.rate, tokens[3]) != 0) {
430                 snprintf(out, out_size, MSG_ARG_INVALID, "rate");
431                 return;
432         }
433
434         if (strcmp(tokens[4], "spp") != 0) {
435                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
436                 return;
437         }
438
439         if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) {
440                 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
441                 return;
442         }
443
444         if (strcmp(tokens[6], "pps") != 0) {
445                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
446                 return;
447         }
448
449         if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) {
450                 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
451                 return;
452         }
453
454         if (strcmp(tokens[8], "qsize") != 0) {
455                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize");
456                 return;
457         }
458
459         for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
460                 if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) {
461                         snprintf(out, out_size, MSG_ARG_INVALID, "qsize");
462                         return;
463                 }
464
465         if (strcmp(tokens[13], "fo") != 0) {
466                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo");
467                 return;
468         }
469
470         if (parser_read_uint32(&p.frame_overhead, tokens[14]) != 0) {
471                 snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead");
472                 return;
473         }
474
475         if (strcmp(tokens[15], "mtu") != 0) {
476                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu");
477                 return;
478         }
479
480         if (parser_read_uint32(&p.mtu, tokens[16]) != 0) {
481                 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
482                 return;
483         }
484
485         if (strcmp(tokens[17], "cpu") != 0) {
486                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
487                 return;
488         }
489
490         if (parser_read_uint32(&p.cpu_id, tokens[18]) != 0) {
491                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
492                 return;
493         }
494
495         tmgr_port = tmgr_port_create(name, &p);
496         if (tmgr_port == NULL) {
497                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
498                 return;
499         }
500 }
501
502 /**
503  * tmgr <tmgr_name> subport <subport_id>
504  *  profile <subport_profile_id>
505  */
506 static void
507 cmd_tmgr_subport(char **tokens,
508         uint32_t n_tokens,
509         char *out,
510         size_t out_size)
511 {
512         uint32_t subport_id, subport_profile_id;
513         int status;
514         char *name;
515
516         if (n_tokens != 6) {
517                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
518                 return;
519         }
520
521         name = tokens[1];
522
523         if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
524                 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
525                 return;
526         }
527
528         if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) {
529                 snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id");
530                 return;
531         }
532
533         status = tmgr_subport_config(name, subport_id, subport_profile_id);
534         if (status) {
535                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
536                 return;
537         }
538 }
539
540 /**
541  * tmgr <tmgr_name> subport <subport_id> pipe
542  *  from <pipe_id_first> to <pipe_id_last>
543  *  profile <pipe_profile_id>
544  */
545 static void
546 cmd_tmgr_subport_pipe(char **tokens,
547         uint32_t n_tokens,
548         char *out,
549         size_t out_size)
550 {
551         uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id;
552         int status;
553         char *name;
554
555         if (n_tokens != 11) {
556                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
557                 return;
558         }
559
560         name = tokens[1];
561
562         if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
563                 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
564                 return;
565         }
566
567         if (strcmp(tokens[4], "pipe") != 0) {
568                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
569                 return;
570         }
571
572         if (strcmp(tokens[5], "from") != 0) {
573                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
574                 return;
575         }
576
577         if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) {
578                 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first");
579                 return;
580         }
581
582         if (strcmp(tokens[7], "to") != 0) {
583                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
584                 return;
585         }
586
587         if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) {
588                 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last");
589                 return;
590         }
591
592         if (strcmp(tokens[9], "profile") != 0) {
593                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
594                 return;
595         }
596
597         if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) {
598                 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
599                 return;
600         }
601
602         status = tmgr_pipe_config(name, subport_id, pipe_id_first,
603                         pipe_id_last, pipe_profile_id);
604         if (status) {
605                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
606                 return;
607         }
608 }
609
610 /**
611  * tap <tap_name>
612  */
613 static void
614 cmd_tap(char **tokens,
615         uint32_t n_tokens,
616         char *out,
617         size_t out_size)
618 {
619         char *name;
620         struct tap *tap;
621
622         if (n_tokens != 2) {
623                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
624                 return;
625         }
626
627         name = tokens[1];
628
629         tap = tap_create(name);
630         if (tap == NULL) {
631                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
632                 return;
633         }
634 }
635
636 /**
637  * kni <kni_name>
638  *  link <link_name>
639  *  mempool <mempool_name>
640  *  [thread <thread_id>]
641  */
642 static void
643 cmd_kni(char **tokens,
644         uint32_t n_tokens,
645         char *out,
646         size_t out_size)
647 {
648         struct kni_params p;
649         char *name;
650         struct kni *kni;
651
652         if ((n_tokens != 6) && (n_tokens != 8)) {
653                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
654                 return;
655         }
656
657         name = tokens[1];
658
659         if (strcmp(tokens[2], "link") != 0) {
660                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link");
661                 return;
662         }
663
664         p.link_name = tokens[3];
665
666         if (strcmp(tokens[4], "mempool") != 0) {
667                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool");
668                 return;
669         }
670
671         p.mempool_name = tokens[5];
672
673         if (n_tokens == 8) {
674                 if (strcmp(tokens[6], "thread") != 0) {
675                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread");
676                         return;
677                 }
678
679                 if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) {
680                         snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
681                         return;
682                 }
683
684                 p.force_bind = 1;
685         } else
686                 p.force_bind = 0;
687
688         kni = kni_create(name, &p);
689         if (kni == NULL) {
690                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
691                 return;
692         }
693 }
694
695 /**
696  * port in action profile <profile_name>
697  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
698  *  [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
699  */
700 static void
701 cmd_port_in_action_profile(char **tokens,
702         uint32_t n_tokens,
703         char *out,
704         size_t out_size)
705 {
706         struct port_in_action_profile_params p;
707         struct port_in_action_profile *ap;
708         char *name;
709         uint32_t t0;
710
711         memset(&p, 0, sizeof(p));
712
713         if (n_tokens < 5) {
714                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
715                 return;
716         }
717
718         if (strcmp(tokens[1], "in") != 0) {
719                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
720                 return;
721         }
722
723         if (strcmp(tokens[2], "action") != 0) {
724                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
725                 return;
726         }
727
728         if (strcmp(tokens[3], "profile") != 0) {
729                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
730                 return;
731         }
732
733         name = tokens[4];
734
735         t0 = 5;
736
737         if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) {
738                 uint32_t size;
739
740                 if (n_tokens < t0 + 10) {
741                         snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
742                         return;
743                 }
744
745                 if (strcmp(tokens[t0 + 1], "match") == 0)
746                         p.fltr.filter_on_match = 1;
747                 else if (strcmp(tokens[t0 + 1], "mismatch") == 0)
748                         p.fltr.filter_on_match = 0;
749                 else {
750                         snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
751                         return;
752                 }
753
754                 if (strcmp(tokens[t0 + 2], "offset") != 0) {
755                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
756                         return;
757                 }
758
759                 if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) {
760                         snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
761                         return;
762                 }
763
764                 if (strcmp(tokens[t0 + 4], "mask") != 0) {
765                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
766                         return;
767                 }
768
769                 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
770                 if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) ||
771                         (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
772                         snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
773                         return;
774                 }
775
776                 if (strcmp(tokens[t0 + 6], "key") != 0) {
777                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
778                         return;
779                 }
780
781                 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
782                 if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) ||
783                         (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
784                         snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
785                         return;
786                 }
787
788                 if (strcmp(tokens[t0 + 8], "port") != 0) {
789                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
790                         return;
791                 }
792
793                 if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) {
794                         snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
795                         return;
796                 }
797
798                 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
799                 t0 += 10;
800         } /* filter */
801
802         if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) {
803                 uint32_t i;
804
805                 if (n_tokens < t0 + 22) {
806                         snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile balance");
807                         return;
808                 }
809
810                 if (strcmp(tokens[t0 + 1], "offset") != 0) {
811                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
812                         return;
813                 }
814
815                 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) {
816                         snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
817                         return;
818                 }
819
820                 if (strcmp(tokens[t0 + 3], "mask") != 0) {
821                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
822                         return;
823                 }
824
825                 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
826                 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) {
827                         snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
828                         return;
829                 }
830
831                 if (strcmp(tokens[t0 + 5], "port") != 0) {
832                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
833                         return;
834                 }
835
836                 for (i = 0; i < 16; i++)
837                         if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) {
838                                 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
839                                 return;
840                         }
841
842                 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
843                 t0 += 22;
844         } /* balance */
845
846         if (t0 < n_tokens) {
847                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
848                 return;
849         }
850
851         ap = port_in_action_profile_create(name, &p);
852         if (ap == NULL) {
853                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
854                 return;
855         }
856 }
857
858 /**
859  * table action profile <profile_name>
860  *  ipv4 | ipv6
861  *  offset <ip_offset>
862  *  fwd
863  *  [meter srtcm | trtcm
864  *      tc <n_tc>
865  *      stats none | pkts | bytes | both]
866  *  [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
867  *  [encap ether | vlan | qinq | mpls | pppoe]
868  *  [nat src | dst
869  *      proto udp | tcp]
870  *  [ttl drop | fwd
871  *      stats none | pkts]
872  *  [stats pkts | bytes | both]
873  *  [time]
874  */
875 static void
876 cmd_table_action_profile(char **tokens,
877         uint32_t n_tokens,
878         char *out,
879         size_t out_size)
880 {
881         struct table_action_profile_params p;
882         struct table_action_profile *ap;
883         char *name;
884         uint32_t t0;
885
886         memset(&p, 0, sizeof(p));
887
888         if (n_tokens < 8) {
889                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
890                 return;
891         }
892
893         if (strcmp(tokens[1], "action") != 0) {
894                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
895                 return;
896         }
897
898         if (strcmp(tokens[2], "profile") != 0) {
899                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
900                 return;
901         }
902
903         name = tokens[3];
904
905         if (strcmp(tokens[4], "ipv4") == 0)
906                 p.common.ip_version = 1;
907         else if (strcmp(tokens[4], "ipv6") == 0)
908                 p.common.ip_version = 0;
909         else {
910                 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
911                 return;
912         }
913
914         if (strcmp(tokens[5], "offset") != 0) {
915                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
916                 return;
917         }
918
919         if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) {
920                 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
921                 return;
922         }
923
924         if (strcmp(tokens[7], "fwd") != 0) {
925                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
926                 return;
927         }
928
929         p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
930
931         t0 = 8;
932         if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) {
933                 if (n_tokens < t0 + 6) {
934                         snprintf(out, out_size, MSG_ARG_MISMATCH,
935                                 "table action profile meter");
936                         return;
937                 }
938
939                 if (strcmp(tokens[t0 + 1], "srtcm") == 0)
940                         p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
941                 else if (strcmp(tokens[t0 + 1], "trtcm") == 0)
942                         p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
943                 else {
944                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
945                                 "srtcm or trtcm");
946                         return;
947                 }
948
949                 if (strcmp(tokens[t0 + 2], "tc") != 0) {
950                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
951                         return;
952                 }
953
954                 if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) {
955                         snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
956                         return;
957                 }
958
959                 if (strcmp(tokens[t0 + 4], "stats") != 0) {
960                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
961                         return;
962                 }
963
964                 if (strcmp(tokens[t0 + 5], "none") == 0) {
965                         p.mtr.n_packets_enabled = 0;
966                         p.mtr.n_bytes_enabled = 0;
967                 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
968                         p.mtr.n_packets_enabled = 1;
969                         p.mtr.n_bytes_enabled = 0;
970                 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
971                         p.mtr.n_packets_enabled = 0;
972                         p.mtr.n_bytes_enabled = 1;
973                 } else if (strcmp(tokens[t0 + 5], "both") == 0) {
974                         p.mtr.n_packets_enabled = 1;
975                         p.mtr.n_bytes_enabled = 1;
976                 } else {
977                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
978                                 "none or pkts or bytes or both");
979                         return;
980                 }
981
982                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
983                 t0 += 6;
984         } /* meter */
985
986         if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) {
987                 if (n_tokens < t0 + 5) {
988                         snprintf(out, out_size, MSG_ARG_MISMATCH,
989                                 "table action profile tm");
990                         return;
991                 }
992
993                 if (strcmp(tokens[t0 + 1], "spp") != 0) {
994                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
995                         return;
996                 }
997
998                 if (parser_read_uint32(&p.tm.n_subports_per_port,
999                         tokens[t0 + 2]) != 0) {
1000                         snprintf(out, out_size, MSG_ARG_INVALID,
1001                                 "n_subports_per_port");
1002                         return;
1003                 }
1004
1005                 if (strcmp(tokens[t0 + 3], "pps") != 0) {
1006                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
1007                         return;
1008                 }
1009
1010                 if (parser_read_uint32(&p.tm.n_pipes_per_subport,
1011                         tokens[t0 + 4]) != 0) {
1012                         snprintf(out, out_size, MSG_ARG_INVALID,
1013                                 "n_pipes_per_subport");
1014                         return;
1015                 }
1016
1017                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
1018                 t0 += 5;
1019         } /* tm */
1020
1021         if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) {
1022                 if (n_tokens < t0 + 2) {
1023                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1024                                 "action profile encap");
1025                         return;
1026                 }
1027
1028                 if (strcmp(tokens[t0 + 1], "ether") == 0)
1029                         p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
1030                 else if (strcmp(tokens[t0 + 1], "vlan") == 0)
1031                         p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
1032                 else if (strcmp(tokens[t0 + 1], "qinq") == 0)
1033                         p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
1034                 else if (strcmp(tokens[t0 + 1], "mpls") == 0)
1035                         p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
1036                 else if (strcmp(tokens[t0 + 1], "pppoe") == 0)
1037                         p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
1038                 else {
1039                         snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
1040                         return;
1041                 }
1042
1043                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
1044                 t0 += 2;
1045         } /* encap */
1046
1047         if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) {
1048                 if (n_tokens < t0 + 4) {
1049                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1050                                 "table action profile nat");
1051                         return;
1052                 }
1053
1054                 if (strcmp(tokens[t0 + 1], "src") == 0)
1055                         p.nat.source_nat = 1;
1056                 else if (strcmp(tokens[t0 + 1], "dst") == 0)
1057                         p.nat.source_nat = 0;
1058                 else {
1059                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1060                                 "src or dst");
1061                         return;
1062                 }
1063
1064                 if (strcmp(tokens[t0 + 2], "proto") != 0) {
1065                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
1066                         return;
1067                 }
1068
1069                 if (strcmp(tokens[t0 + 3], "tcp") == 0)
1070                         p.nat.proto = 0x06;
1071                 else if (strcmp(tokens[t0 + 3], "udp") == 0)
1072                         p.nat.proto = 0x11;
1073                 else {
1074                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1075                                 "tcp or udp");
1076                         return;
1077                 }
1078
1079                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
1080                 t0 += 4;
1081         } /* nat */
1082
1083         if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) {
1084                 if (n_tokens < t0 + 4) {
1085                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1086                                 "table action profile ttl");
1087                         return;
1088                 }
1089
1090                 if (strcmp(tokens[t0 + 1], "drop") == 0)
1091                         p.ttl.drop = 1;
1092                 else if (strcmp(tokens[t0 + 1], "fwd") == 0)
1093                         p.ttl.drop = 0;
1094                 else {
1095                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1096                                 "drop or fwd");
1097                         return;
1098                 }
1099
1100                 if (strcmp(tokens[t0 + 2], "stats") != 0) {
1101                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1102                         return;
1103                 }
1104
1105                 if (strcmp(tokens[t0 + 3], "none") == 0)
1106                         p.ttl.n_packets_enabled = 0;
1107                 else if (strcmp(tokens[t0 + 3], "pkts") == 0)
1108                         p.ttl.n_packets_enabled = 1;
1109                 else {
1110                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1111                                 "none or pkts");
1112                         return;
1113                 }
1114
1115                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
1116                 t0 += 4;
1117         } /* ttl */
1118
1119         if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) {
1120                 if (n_tokens < t0 + 2) {
1121                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1122                                 "table action profile stats");
1123                         return;
1124                 }
1125
1126                 if (strcmp(tokens[t0 + 1], "pkts") == 0) {
1127                         p.stats.n_packets_enabled = 1;
1128                         p.stats.n_bytes_enabled = 0;
1129                 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
1130                         p.stats.n_packets_enabled = 0;
1131                         p.stats.n_bytes_enabled = 1;
1132                 } else if (strcmp(tokens[t0 + 1], "both") == 0) {
1133                         p.stats.n_packets_enabled = 1;
1134                         p.stats.n_bytes_enabled = 1;
1135                 } else {
1136                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1137                                 "pkts or bytes or both");
1138                         return;
1139                 }
1140
1141                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
1142                 t0 += 2;
1143         } /* stats */
1144
1145         if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) {
1146                 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
1147                 t0 += 1;
1148         } /* time */
1149
1150         if (t0 < n_tokens) {
1151                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1152                 return;
1153         }
1154
1155         ap = table_action_profile_create(name, &p);
1156         if (ap == NULL) {
1157                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1158                 return;
1159         }
1160 }
1161
1162 /**
1163  * pipeline <pipeline_name>
1164  *  period <timer_period_ms>
1165  *  offset_port_id <offset_port_id>
1166  *  cpu <cpu_id>
1167  */
1168 static void
1169 cmd_pipeline(char **tokens,
1170         uint32_t n_tokens,
1171         char *out,
1172         size_t out_size)
1173 {
1174         struct pipeline_params p;
1175         char *name;
1176         struct pipeline *pipeline;
1177
1178         if (n_tokens != 8) {
1179                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1180                 return;
1181         }
1182
1183         name = tokens[1];
1184
1185         if (strcmp(tokens[2], "period") != 0) {
1186                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
1187                 return;
1188         }
1189
1190         if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) {
1191                 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
1192                 return;
1193         }
1194
1195         if (strcmp(tokens[4], "offset_port_id") != 0) {
1196                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
1197                 return;
1198         }
1199
1200         if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) {
1201                 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
1202                 return;
1203         }
1204
1205         if (strcmp(tokens[6], "cpu") != 0) {
1206                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
1207                 return;
1208         }
1209
1210         if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) {
1211                 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
1212                 return;
1213         }
1214
1215         pipeline = pipeline_create(name, &p);
1216         if (pipeline == NULL) {
1217                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1218                 return;
1219         }
1220 }
1221
1222 /**
1223  * pipeline <pipeline_name> port in
1224  *  bsz <burst_size>
1225  *  link <link_name> rxq <queue_id>
1226  *  | swq <swq_name>
1227  *  | tmgr <tmgr_name>
1228  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
1229  *  | kni <kni_name>
1230  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
1231  *  [action <port_in_action_profile_name>]
1232  *  [disabled]
1233  */
1234 static void
1235 cmd_pipeline_port_in(char **tokens,
1236         uint32_t n_tokens,
1237         char *out,
1238         size_t out_size)
1239 {
1240         struct port_in_params p;
1241         char *pipeline_name;
1242         uint32_t t0;
1243         int enabled, status;
1244
1245         if (n_tokens < 7) {
1246                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1247                 return;
1248         }
1249
1250         pipeline_name = tokens[1];
1251
1252         if (strcmp(tokens[2], "port") != 0) {
1253                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1254                 return;
1255         }
1256
1257         if (strcmp(tokens[3], "in") != 0) {
1258                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1259                 return;
1260         }
1261
1262         if (strcmp(tokens[4], "bsz") != 0) {
1263                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1264                 return;
1265         }
1266
1267         if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1268                 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1269                 return;
1270         }
1271
1272         t0 = 6;
1273
1274         if (strcmp(tokens[t0], "link") == 0) {
1275                 if (n_tokens < t0 + 4) {
1276                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1277                                 "pipeline port in link");
1278                         return;
1279                 }
1280
1281                 p.type = PORT_IN_RXQ;
1282
1283                 p.dev_name = tokens[t0 + 1];
1284
1285                 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
1286                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
1287                         return;
1288                 }
1289
1290                 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) {
1291                         snprintf(out, out_size, MSG_ARG_INVALID,
1292                                 "queue_id");
1293                         return;
1294                 }
1295                 t0 += 4;
1296         } else if (strcmp(tokens[t0], "swq") == 0) {
1297                 if (n_tokens < t0 + 2) {
1298                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1299                                 "pipeline port in swq");
1300                         return;
1301                 }
1302
1303                 p.type = PORT_IN_SWQ;
1304
1305                 p.dev_name = tokens[t0 + 1];
1306
1307                 t0 += 2;
1308         } else if (strcmp(tokens[t0], "tmgr") == 0) {
1309                 if (n_tokens < t0 + 2) {
1310                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1311                                 "pipeline port in tmgr");
1312                         return;
1313                 }
1314
1315                 p.type = PORT_IN_TMGR;
1316
1317                 p.dev_name = tokens[t0 + 1];
1318
1319                 t0 += 2;
1320         } else if (strcmp(tokens[t0], "tap") == 0) {
1321                 if (n_tokens < t0 + 6) {
1322                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1323                                 "pipeline port in tap");
1324                         return;
1325                 }
1326
1327                 p.type = PORT_IN_TAP;
1328
1329                 p.dev_name = tokens[t0 + 1];
1330
1331                 if (strcmp(tokens[t0 + 2], "mempool") != 0) {
1332                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1333                                 "mempool");
1334                         return;
1335                 }
1336
1337                 p.tap.mempool_name = tokens[t0 + 3];
1338
1339                 if (strcmp(tokens[t0 + 4], "mtu") != 0) {
1340                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1341                                 "mtu");
1342                         return;
1343                 }
1344
1345                 if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) {
1346                         snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
1347                         return;
1348                 }
1349
1350                 t0 += 6;
1351         } else if (strcmp(tokens[t0], "kni") == 0) {
1352                 if (n_tokens < t0 + 2) {
1353                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1354                                 "pipeline port in kni");
1355                         return;
1356                 }
1357
1358                 p.type = PORT_IN_KNI;
1359
1360                 p.dev_name = tokens[t0 + 1];
1361
1362                 t0 += 2;
1363         } else if (strcmp(tokens[t0], "source") == 0) {
1364                 if (n_tokens < t0 + 6) {
1365                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1366                                 "pipeline port in source");
1367                         return;
1368                 }
1369
1370                 p.type = PORT_IN_SOURCE;
1371
1372                 p.dev_name = NULL;
1373
1374                 if (strcmp(tokens[t0 + 1], "mempool") != 0) {
1375                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1376                                 "mempool");
1377                         return;
1378                 }
1379
1380                 p.source.mempool_name = tokens[t0 + 2];
1381
1382                 if (strcmp(tokens[t0 + 3], "file") != 0) {
1383                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1384                                 "file");
1385                         return;
1386                 }
1387
1388                 p.source.file_name = tokens[t0 + 4];
1389
1390                 if (strcmp(tokens[t0 + 5], "bpp") != 0) {
1391                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1392                                 "bpp");
1393                         return;
1394                 }
1395
1396                 if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) {
1397                         snprintf(out, out_size, MSG_ARG_INVALID,
1398                                 "n_bytes_per_pkt");
1399                         return;
1400                 }
1401
1402                 t0 += 7;
1403         } else {
1404                 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1405                 return;
1406         }
1407
1408         p.action_profile_name = NULL;
1409         if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
1410                 if (n_tokens < t0 + 2) {
1411                         snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1412                         return;
1413                 }
1414
1415                 p.action_profile_name = tokens[t0 + 1];
1416
1417                 t0 += 2;
1418         }
1419
1420         enabled = 1;
1421         if ((n_tokens > t0) &&
1422                 (strcmp(tokens[t0], "disabled") == 0)) {
1423                 enabled = 0;
1424
1425                 t0 += 1;
1426         }
1427
1428         if (n_tokens != t0) {
1429                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1430                 return;
1431         }
1432
1433         status = pipeline_port_in_create(pipeline_name,
1434                 &p, enabled);
1435         if (status) {
1436                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1437                 return;
1438         }
1439 }
1440
1441 /**
1442  * pipeline <pipeline_name> port out
1443  *  bsz <burst_size>
1444  *  link <link_name> txq <txq_id>
1445  *  | swq <swq_name>
1446  *  | tmgr <tmgr_name>
1447  *  | tap <tap_name>
1448  *  | kni <kni_name>
1449  *  | sink [file <file_name> pkts <max_n_pkts>]
1450  */
1451 static void
1452 cmd_pipeline_port_out(char **tokens,
1453         uint32_t n_tokens,
1454         char *out,
1455         size_t out_size)
1456 {
1457         struct port_out_params p;
1458         char *pipeline_name;
1459         int status;
1460
1461         memset(&p, 0, sizeof(p));
1462
1463         if (n_tokens < 7) {
1464                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1465                 return;
1466         }
1467
1468         pipeline_name = tokens[1];
1469
1470         if (strcmp(tokens[2], "port") != 0) {
1471                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1472                 return;
1473         }
1474
1475         if (strcmp(tokens[3], "out") != 0) {
1476                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
1477                 return;
1478         }
1479
1480         if (strcmp(tokens[4], "bsz") != 0) {
1481                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1482                 return;
1483         }
1484
1485         if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1486                 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1487                 return;
1488         }
1489
1490         if (strcmp(tokens[6], "link") == 0) {
1491                 if (n_tokens != 10) {
1492                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1493                                 "pipeline port out link");
1494                         return;
1495                 }
1496
1497                 p.type = PORT_OUT_TXQ;
1498
1499                 p.dev_name = tokens[7];
1500
1501                 if (strcmp(tokens[8], "txq") != 0) {
1502                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
1503                         return;
1504                 }
1505
1506                 if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) {
1507                         snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1508                         return;
1509                 }
1510         } else if (strcmp(tokens[6], "swq") == 0) {
1511                 if (n_tokens != 8) {
1512                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1513                                 "pipeline port out swq");
1514                         return;
1515                 }
1516
1517                 p.type = PORT_OUT_SWQ;
1518
1519                 p.dev_name = tokens[7];
1520         } else if (strcmp(tokens[6], "tmgr") == 0) {
1521                 if (n_tokens != 8) {
1522                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1523                                 "pipeline port out tmgr");
1524                         return;
1525                 }
1526
1527                 p.type = PORT_OUT_TMGR;
1528
1529                 p.dev_name = tokens[7];
1530         } else if (strcmp(tokens[6], "tap") == 0) {
1531                 if (n_tokens != 8) {
1532                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1533                                 "pipeline port out tap");
1534                         return;
1535                 }
1536
1537                 p.type = PORT_OUT_TAP;
1538
1539                 p.dev_name = tokens[7];
1540         } else if (strcmp(tokens[6], "kni") == 0) {
1541                 if (n_tokens != 8) {
1542                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1543                                 "pipeline port out kni");
1544                         return;
1545                 }
1546
1547                 p.type = PORT_OUT_KNI;
1548
1549                 p.dev_name = tokens[7];
1550         } else if (strcmp(tokens[6], "sink") == 0) {
1551                 if ((n_tokens != 7) && (n_tokens != 11)) {
1552                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1553                                 "pipeline port out sink");
1554                         return;
1555                 }
1556
1557                 p.type = PORT_OUT_SINK;
1558
1559                 p.dev_name = NULL;
1560
1561                 if (n_tokens == 7) {
1562                         p.sink.file_name = NULL;
1563                         p.sink.max_n_pkts = 0;
1564                 } else {
1565                         if (strcmp(tokens[7], "file") != 0) {
1566                                 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1567                                         "file");
1568                                 return;
1569                         }
1570
1571                         p.sink.file_name = tokens[8];
1572
1573                         if (strcmp(tokens[9], "pkts") != 0) {
1574                                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
1575                                 return;
1576                         }
1577
1578                         if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) {
1579                                 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
1580                                 return;
1581                         }
1582                 }
1583         } else {
1584                 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1585                 return;
1586         }
1587
1588         status = pipeline_port_out_create(pipeline_name, &p);
1589         if (status) {
1590                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1591                 return;
1592         }
1593 }
1594
1595 /**
1596  * pipeline <pipeline_name> table
1597  *      match
1598  *      acl
1599  *          ipv4 | ipv6
1600  *          offset <ip_header_offset>
1601  *          size <n_rules>
1602  *      | array
1603  *          offset <key_offset>
1604  *          size <n_keys>
1605  *      | hash
1606  *          ext | lru
1607  *          key <key_size>
1608  *          mask <key_mask>
1609  *          offset <key_offset>
1610  *          buckets <n_buckets>
1611  *          size <n_keys>
1612  *      | lpm
1613  *          ipv4 | ipv6
1614  *          offset <ip_header_offset>
1615  *          size <n_rules>
1616  *      | stub
1617  *  [action <table_action_profile_name>]
1618  */
1619 static void
1620 cmd_pipeline_table(char **tokens,
1621         uint32_t n_tokens,
1622         char *out,
1623         size_t out_size)
1624 {
1625         uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
1626         struct table_params p;
1627         char *pipeline_name;
1628         uint32_t t0;
1629         int status;
1630
1631         if (n_tokens < 5) {
1632                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1633                 return;
1634         }
1635
1636         pipeline_name = tokens[1];
1637
1638         if (strcmp(tokens[2], "table") != 0) {
1639                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1640                 return;
1641         }
1642
1643         if (strcmp(tokens[3], "match") != 0) {
1644                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
1645                 return;
1646         }
1647
1648         t0 = 4;
1649         if (strcmp(tokens[t0], "acl") == 0) {
1650                 if (n_tokens < t0 + 6) {
1651                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1652                                 "pipeline table acl");
1653                         return;
1654                 }
1655
1656                 p.match_type = TABLE_ACL;
1657
1658                 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
1659                         p.match.acl.ip_version = 1;
1660                 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
1661                         p.match.acl.ip_version = 0;
1662                 else {
1663                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1664                                 "ipv4 or ipv6");
1665                         return;
1666                 }
1667
1668                 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1669                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1670                         return;
1671                 }
1672
1673                 if (parser_read_uint32(&p.match.acl.ip_header_offset,
1674                         tokens[t0 + 3]) != 0) {
1675                         snprintf(out, out_size, MSG_ARG_INVALID,
1676                                 "ip_header_offset");
1677                         return;
1678                 }
1679
1680                 if (strcmp(tokens[t0 + 4], "size") != 0) {
1681                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1682                         return;
1683                 }
1684
1685                 if (parser_read_uint32(&p.match.acl.n_rules,
1686                         tokens[t0 + 5]) != 0) {
1687                         snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
1688                         return;
1689                 }
1690
1691                 t0 += 6;
1692         } else if (strcmp(tokens[t0], "array") == 0) {
1693                 if (n_tokens < t0 + 5) {
1694                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1695                                 "pipeline table array");
1696                         return;
1697                 }
1698
1699                 p.match_type = TABLE_ARRAY;
1700
1701                 if (strcmp(tokens[t0 + 1], "offset") != 0) {
1702                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1703                         return;
1704                 }
1705
1706                 if (parser_read_uint32(&p.match.array.key_offset,
1707                         tokens[t0 + 2]) != 0) {
1708                         snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1709                         return;
1710                 }
1711
1712                 if (strcmp(tokens[t0 + 3], "size") != 0) {
1713                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1714                         return;
1715                 }
1716
1717                 if (parser_read_uint32(&p.match.array.n_keys,
1718                         tokens[t0 + 4]) != 0) {
1719                         snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1720                         return;
1721                 }
1722
1723                 t0 += 5;
1724         } else if (strcmp(tokens[t0], "hash") == 0) {
1725                 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
1726
1727                 if (n_tokens < t0 + 12) {
1728                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1729                                 "pipeline table hash");
1730                         return;
1731                 }
1732
1733                 p.match_type = TABLE_HASH;
1734
1735                 if (strcmp(tokens[t0 + 1], "ext") == 0)
1736                         p.match.hash.extendable_bucket = 1;
1737                 else if (strcmp(tokens[t0 + 1], "lru") == 0)
1738                         p.match.hash.extendable_bucket = 0;
1739                 else {
1740                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1741                                 "ext or lru");
1742                         return;
1743                 }
1744
1745                 if (strcmp(tokens[t0 + 2], "key") != 0) {
1746                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
1747                         return;
1748                 }
1749
1750                 if ((parser_read_uint32(&p.match.hash.key_size,
1751                         tokens[t0 + 3]) != 0) ||
1752                         (p.match.hash.key_size == 0) ||
1753                         (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) {
1754                         snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
1755                         return;
1756                 }
1757
1758                 if (strcmp(tokens[t0 + 4], "mask") != 0) {
1759                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1760                         return;
1761                 }
1762
1763                 if ((parse_hex_string(tokens[t0 + 5],
1764                         key_mask, &key_mask_size) != 0) ||
1765                         (key_mask_size != p.match.hash.key_size)) {
1766                         snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1767                         return;
1768                 }
1769                 p.match.hash.key_mask = key_mask;
1770
1771                 if (strcmp(tokens[t0 + 6], "offset") != 0) {
1772                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1773                         return;
1774                 }
1775
1776                 if (parser_read_uint32(&p.match.hash.key_offset,
1777                         tokens[t0 + 7]) != 0) {
1778                         snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1779                         return;
1780                 }
1781
1782                 if (strcmp(tokens[t0 + 8], "buckets") != 0) {
1783                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
1784                         return;
1785                 }
1786
1787                 if (parser_read_uint32(&p.match.hash.n_buckets,
1788                         tokens[t0 + 9]) != 0) {
1789                         snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
1790                         return;
1791                 }
1792
1793                 if (strcmp(tokens[t0 + 10], "size") != 0) {
1794                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1795                         return;
1796                 }
1797
1798                 if (parser_read_uint32(&p.match.hash.n_keys,
1799                         tokens[t0 + 11]) != 0) {
1800                         snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1801                         return;
1802                 }
1803
1804                 t0 += 12;
1805         } else if (strcmp(tokens[t0], "lpm") == 0) {
1806                 if (n_tokens < t0 + 6) {
1807                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1808                                 "pipeline table lpm");
1809                         return;
1810                 }
1811
1812                 p.match_type = TABLE_LPM;
1813
1814                 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
1815                         p.match.lpm.key_size = 4;
1816                 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
1817                         p.match.lpm.key_size = 16;
1818                 else {
1819                         snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1820                                 "ipv4 or ipv6");
1821                         return;
1822                 }
1823
1824                 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1825                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1826                         return;
1827                 }
1828
1829                 if (parser_read_uint32(&p.match.lpm.key_offset,
1830                         tokens[t0 + 3]) != 0) {
1831                         snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1832                         return;
1833                 }
1834
1835                 if (strcmp(tokens[t0 + 4], "size") != 0) {
1836                         snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1837                         return;
1838                 }
1839
1840                 if (parser_read_uint32(&p.match.lpm.n_rules,
1841                         tokens[t0 + 5]) != 0) {
1842                         snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
1843                         return;
1844                 }
1845
1846                 t0 += 6;
1847         } else if (strcmp(tokens[t0], "stub") == 0) {
1848                 if (n_tokens < t0 + 1) {
1849                         snprintf(out, out_size, MSG_ARG_MISMATCH,
1850                                 "pipeline table stub");
1851                         return;
1852                 }
1853
1854                 p.match_type = TABLE_STUB;
1855
1856                 t0 += 1;
1857         } else {
1858                 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1859                 return;
1860         }
1861
1862         p.action_profile_name = NULL;
1863         if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
1864                 if (n_tokens < t0 + 2) {
1865                         snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1866                         return;
1867                 }
1868
1869                 p.action_profile_name = tokens[t0 + 1];
1870
1871                 t0 += 2;
1872         }
1873
1874         if (n_tokens > t0) {
1875                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1876                 return;
1877         }
1878
1879         status = pipeline_table_create(pipeline_name, &p);
1880         if (status) {
1881                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1882                 return;
1883         }
1884 }
1885
1886 /**
1887  * pipeline <pipeline_name> port in <port_id> table <table_id>
1888  */
1889 static void
1890 cmd_pipeline_port_in_table(char **tokens,
1891         uint32_t n_tokens,
1892         char *out,
1893         size_t out_size)
1894 {
1895         char *pipeline_name;
1896         uint32_t port_id, table_id;
1897         int status;
1898
1899         if (n_tokens != 7) {
1900                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1901                 return;
1902         }
1903
1904         pipeline_name = tokens[1];
1905
1906         if (strcmp(tokens[2], "port") != 0) {
1907                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1908                 return;
1909         }
1910
1911         if (strcmp(tokens[3], "in") != 0) {
1912                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1913                 return;
1914         }
1915
1916         if (parser_read_uint32(&port_id, tokens[4]) != 0) {
1917                 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
1918                 return;
1919         }
1920
1921         if (strcmp(tokens[5], "table") != 0) {
1922                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1923                 return;
1924         }
1925
1926         if (parser_read_uint32(&table_id, tokens[6]) != 0) {
1927                 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
1928                 return;
1929         }
1930
1931         status = pipeline_port_in_connect_to_table(pipeline_name,
1932                 port_id,
1933                 table_id);
1934         if (status) {
1935                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1936                 return;
1937         }
1938 }
1939
1940 /**
1941  * thread <thread_id> pipeline <pipeline_name> enable
1942  */
1943 static void
1944 cmd_thread_pipeline_enable(char **tokens,
1945         uint32_t n_tokens,
1946         char *out,
1947         size_t out_size)
1948 {
1949         char *pipeline_name;
1950         uint32_t thread_id;
1951         int status;
1952
1953         if (n_tokens != 5) {
1954                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1955                 return;
1956         }
1957
1958         if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1959                 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1960                 return;
1961         }
1962
1963         if (strcmp(tokens[2], "pipeline") != 0) {
1964                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1965                 return;
1966         }
1967
1968         pipeline_name = tokens[3];
1969
1970         if (strcmp(tokens[4], "enable") != 0) {
1971                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1972                 return;
1973         }
1974
1975         status = thread_pipeline_enable(thread_id, pipeline_name);
1976         if (status) {
1977                 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
1978                 return;
1979         }
1980 }
1981
1982 /**
1983  * thread <thread_id> pipeline <pipeline_name> disable
1984  */
1985 static void
1986 cmd_thread_pipeline_disable(char **tokens,
1987         uint32_t n_tokens,
1988         char *out,
1989         size_t out_size)
1990 {
1991         char *pipeline_name;
1992         uint32_t thread_id;
1993         int status;
1994
1995         if (n_tokens != 5) {
1996                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1997                 return;
1998         }
1999
2000         if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
2001                 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
2002                 return;
2003         }
2004
2005         if (strcmp(tokens[2], "pipeline") != 0) {
2006                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2007                 return;
2008         }
2009
2010         pipeline_name = tokens[3];
2011
2012         if (strcmp(tokens[4], "disable") != 0) {
2013                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2014                 return;
2015         }
2016
2017         status = thread_pipeline_disable(thread_id, pipeline_name);
2018         if (status) {
2019                 snprintf(out, out_size, MSG_CMD_FAIL,
2020                         "thread pipeline disable");
2021                 return;
2022         }
2023 }
2024
2025 void
2026 cli_process(char *in, char *out, size_t out_size)
2027 {
2028         char *tokens[CMD_MAX_TOKENS];
2029         uint32_t n_tokens = RTE_DIM(tokens);
2030         int status;
2031
2032         if (is_comment(in))
2033                 return;
2034
2035         status = parse_tokenize_string(in, tokens, &n_tokens);
2036         if (status) {
2037                 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
2038                 return;
2039         }
2040
2041         if (n_tokens == 0)
2042                 return;
2043
2044         if (strcmp(tokens[0], "mempool") == 0) {
2045                 cmd_mempool(tokens, n_tokens, out, out_size);
2046                 return;
2047         }
2048
2049         if (strcmp(tokens[0], "link") == 0) {
2050                 cmd_link(tokens, n_tokens, out, out_size);
2051                 return;
2052         }
2053
2054         if (strcmp(tokens[0], "swq") == 0) {
2055                 cmd_swq(tokens, n_tokens, out, out_size);
2056                 return;
2057         }
2058
2059         if (strcmp(tokens[0], "tmgr") == 0) {
2060                 if ((n_tokens >= 3) &&
2061                         (strcmp(tokens[1], "subport") == 0) &&
2062                         (strcmp(tokens[2], "profile") == 0)) {
2063                         cmd_tmgr_subport_profile(tokens, n_tokens,
2064                                 out, out_size);
2065                         return;
2066                 }
2067
2068                 if ((n_tokens >= 3) &&
2069                         (strcmp(tokens[1], "pipe") == 0) &&
2070                         (strcmp(tokens[2], "profile") == 0)) {
2071                         cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size);
2072                         return;
2073                 }
2074
2075                 if ((n_tokens >= 5) &&
2076                         (strcmp(tokens[2], "subport") == 0) &&
2077                         (strcmp(tokens[4], "profile") == 0)) {
2078                         cmd_tmgr_subport(tokens, n_tokens, out, out_size);
2079                         return;
2080                 }
2081
2082                 if ((n_tokens >= 5) &&
2083                         (strcmp(tokens[2], "subport") == 0) &&
2084                         (strcmp(tokens[4], "pipe") == 0)) {
2085                         cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size);
2086                         return;
2087                 }
2088
2089                 cmd_tmgr(tokens, n_tokens, out, out_size);
2090                 return;
2091         }
2092
2093         if (strcmp(tokens[0], "tap") == 0) {
2094                 cmd_tap(tokens, n_tokens, out, out_size);
2095                 return;
2096         }
2097
2098         if (strcmp(tokens[0], "kni") == 0) {
2099                 cmd_kni(tokens, n_tokens, out, out_size);
2100                 return;
2101         }
2102
2103         if (strcmp(tokens[0], "port") == 0) {
2104                 cmd_port_in_action_profile(tokens, n_tokens, out, out_size);
2105                 return;
2106         }
2107
2108         if (strcmp(tokens[0], "table") == 0) {
2109                 cmd_table_action_profile(tokens, n_tokens, out, out_size);
2110                 return;
2111         }
2112
2113         if (strcmp(tokens[0], "pipeline") == 0) {
2114                 if ((n_tokens >= 3) &&
2115                         (strcmp(tokens[2], "period") == 0)) {
2116                         cmd_pipeline(tokens, n_tokens, out, out_size);
2117                         return;
2118                 }
2119
2120                 if ((n_tokens >= 5) &&
2121                         (strcmp(tokens[2], "port") == 0) &&
2122                         (strcmp(tokens[3], "in") == 0) &&
2123                         (strcmp(tokens[4], "bsz") == 0)) {
2124                         cmd_pipeline_port_in(tokens, n_tokens, out, out_size);
2125                         return;
2126                 }
2127
2128                 if ((n_tokens >= 5) &&
2129                         (strcmp(tokens[2], "port") == 0) &&
2130                         (strcmp(tokens[3], "out") == 0) &&
2131                         (strcmp(tokens[4], "bsz") == 0)) {
2132                         cmd_pipeline_port_out(tokens, n_tokens, out, out_size);
2133                         return;
2134                 }
2135
2136                 if ((n_tokens >= 4) &&
2137                         (strcmp(tokens[2], "table") == 0) &&
2138                         (strcmp(tokens[3], "match") == 0)) {
2139                         cmd_pipeline_table(tokens, n_tokens, out, out_size);
2140                         return;
2141                 }
2142
2143                 if ((n_tokens >= 6) &&
2144                         (strcmp(tokens[2], "port") == 0) &&
2145                         (strcmp(tokens[3], "in") == 0) &&
2146                         (strcmp(tokens[5], "table") == 0)) {
2147                         cmd_pipeline_port_in_table(tokens, n_tokens,
2148                                 out, out_size);
2149                         return;
2150                 }
2151         }
2152
2153         if (strcmp(tokens[0], "thread") == 0) {
2154                 if ((n_tokens >= 5) &&
2155                         (strcmp(tokens[4], "enable") == 0)) {
2156                         cmd_thread_pipeline_enable(tokens, n_tokens,
2157                                 out, out_size);
2158                         return;
2159                 }
2160
2161                 if ((n_tokens >= 5) &&
2162                         (strcmp(tokens[4], "disable") == 0)) {
2163                         cmd_thread_pipeline_disable(tokens, n_tokens,
2164                                 out, out_size);
2165                         return;
2166                 }
2167         }
2168
2169         snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
2170 }
2171
2172 int
2173 cli_script_process(const char *file_name,
2174         size_t msg_in_len_max,
2175         size_t msg_out_len_max)
2176 {
2177         char *msg_in = NULL, *msg_out = NULL;
2178         FILE *f = NULL;
2179
2180         /* Check input arguments */
2181         if ((file_name == NULL) ||
2182                 (strlen(file_name) == 0) ||
2183                 (msg_in_len_max == 0) ||
2184                 (msg_out_len_max == 0))
2185                 return -EINVAL;
2186
2187         msg_in = malloc(msg_in_len_max + 1);
2188         msg_out = malloc(msg_out_len_max + 1);
2189         if ((msg_in == NULL) ||
2190                 (msg_out == NULL)) {
2191                 free(msg_out);
2192                 free(msg_in);
2193                 return -ENOMEM;
2194         }
2195
2196         /* Open input file */
2197         f = fopen(file_name, "r");
2198         if (f == NULL) {
2199                 free(msg_out);
2200                 free(msg_in);
2201                 return -EIO;
2202         }
2203
2204         /* Read file */
2205         for ( ; ; ) {
2206                 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
2207                         break;
2208
2209                 printf("%s", msg_in);
2210                 msg_out[0] = 0;
2211
2212                 cli_process(msg_in,
2213                         msg_out,
2214                         msg_out_len_max);
2215
2216                 if (strlen(msg_out))
2217                         printf("%s", msg_out);
2218         }
2219
2220         /* Close file */
2221         fclose(f);
2222         free(msg_out);
2223         free(msg_in);
2224         return 0;
2225 }