examples/ip_pipeline: add port 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  * pipeline <pipeline_name> port in <port_id> enable
1942  */
1943 static void
1944 cmd_pipeline_port_in_enable(char **tokens,
1945         uint32_t n_tokens,
1946         char *out,
1947         size_t out_size)
1948 {
1949         char *pipeline_name;
1950         uint32_t port_id;
1951         int status;
1952
1953         if (n_tokens != 6) {
1954                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1955                 return;
1956         }
1957
1958         pipeline_name = tokens[1];
1959
1960         if (strcmp(tokens[2], "port") != 0) {
1961                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1962                 return;
1963         }
1964
1965         if (strcmp(tokens[3], "in") != 0) {
1966                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1967                 return;
1968         }
1969
1970         if (parser_read_uint32(&port_id, tokens[4]) != 0) {
1971                 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
1972                 return;
1973         }
1974
1975         if (strcmp(tokens[5], "enable") != 0) {
1976                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1977                 return;
1978         }
1979
1980         status = pipeline_port_in_enable(pipeline_name, port_id);
1981         if (status) {
1982                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1983                 return;
1984         }
1985 }
1986
1987 /**
1988  * pipeline <pipeline_name> port in <port_id> disable
1989  */
1990 static void
1991 cmd_pipeline_port_in_disable(char **tokens,
1992         uint32_t n_tokens,
1993         char *out,
1994         size_t out_size)
1995 {
1996         char *pipeline_name;
1997         uint32_t port_id;
1998         int status;
1999
2000         if (n_tokens != 6) {
2001                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2002                 return;
2003         }
2004
2005         pipeline_name = tokens[1];
2006
2007         if (strcmp(tokens[2], "port") != 0) {
2008                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2009                 return;
2010         }
2011
2012         if (strcmp(tokens[3], "in") != 0) {
2013                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2014                 return;
2015         }
2016
2017         if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2018                 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2019                 return;
2020         }
2021
2022         if (strcmp(tokens[5], "disable") != 0) {
2023                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2024                 return;
2025         }
2026
2027         status = pipeline_port_in_disable(pipeline_name, port_id);
2028         if (status) {
2029                 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2030                 return;
2031         }
2032 }
2033
2034 /**
2035  * thread <thread_id> pipeline <pipeline_name> enable
2036  */
2037 static void
2038 cmd_thread_pipeline_enable(char **tokens,
2039         uint32_t n_tokens,
2040         char *out,
2041         size_t out_size)
2042 {
2043         char *pipeline_name;
2044         uint32_t thread_id;
2045         int status;
2046
2047         if (n_tokens != 5) {
2048                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2049                 return;
2050         }
2051
2052         if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
2053                 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
2054                 return;
2055         }
2056
2057         if (strcmp(tokens[2], "pipeline") != 0) {
2058                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2059                 return;
2060         }
2061
2062         pipeline_name = tokens[3];
2063
2064         if (strcmp(tokens[4], "enable") != 0) {
2065                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
2066                 return;
2067         }
2068
2069         status = thread_pipeline_enable(thread_id, pipeline_name);
2070         if (status) {
2071                 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
2072                 return;
2073         }
2074 }
2075
2076 /**
2077  * thread <thread_id> pipeline <pipeline_name> disable
2078  */
2079 static void
2080 cmd_thread_pipeline_disable(char **tokens,
2081         uint32_t n_tokens,
2082         char *out,
2083         size_t out_size)
2084 {
2085         char *pipeline_name;
2086         uint32_t thread_id;
2087         int status;
2088
2089         if (n_tokens != 5) {
2090                 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2091                 return;
2092         }
2093
2094         if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
2095                 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
2096                 return;
2097         }
2098
2099         if (strcmp(tokens[2], "pipeline") != 0) {
2100                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2101                 return;
2102         }
2103
2104         pipeline_name = tokens[3];
2105
2106         if (strcmp(tokens[4], "disable") != 0) {
2107                 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2108                 return;
2109         }
2110
2111         status = thread_pipeline_disable(thread_id, pipeline_name);
2112         if (status) {
2113                 snprintf(out, out_size, MSG_CMD_FAIL,
2114                         "thread pipeline disable");
2115                 return;
2116         }
2117 }
2118
2119 void
2120 cli_process(char *in, char *out, size_t out_size)
2121 {
2122         char *tokens[CMD_MAX_TOKENS];
2123         uint32_t n_tokens = RTE_DIM(tokens);
2124         int status;
2125
2126         if (is_comment(in))
2127                 return;
2128
2129         status = parse_tokenize_string(in, tokens, &n_tokens);
2130         if (status) {
2131                 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
2132                 return;
2133         }
2134
2135         if (n_tokens == 0)
2136                 return;
2137
2138         if (strcmp(tokens[0], "mempool") == 0) {
2139                 cmd_mempool(tokens, n_tokens, out, out_size);
2140                 return;
2141         }
2142
2143         if (strcmp(tokens[0], "link") == 0) {
2144                 cmd_link(tokens, n_tokens, out, out_size);
2145                 return;
2146         }
2147
2148         if (strcmp(tokens[0], "swq") == 0) {
2149                 cmd_swq(tokens, n_tokens, out, out_size);
2150                 return;
2151         }
2152
2153         if (strcmp(tokens[0], "tmgr") == 0) {
2154                 if ((n_tokens >= 3) &&
2155                         (strcmp(tokens[1], "subport") == 0) &&
2156                         (strcmp(tokens[2], "profile") == 0)) {
2157                         cmd_tmgr_subport_profile(tokens, n_tokens,
2158                                 out, out_size);
2159                         return;
2160                 }
2161
2162                 if ((n_tokens >= 3) &&
2163                         (strcmp(tokens[1], "pipe") == 0) &&
2164                         (strcmp(tokens[2], "profile") == 0)) {
2165                         cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size);
2166                         return;
2167                 }
2168
2169                 if ((n_tokens >= 5) &&
2170                         (strcmp(tokens[2], "subport") == 0) &&
2171                         (strcmp(tokens[4], "profile") == 0)) {
2172                         cmd_tmgr_subport(tokens, n_tokens, out, out_size);
2173                         return;
2174                 }
2175
2176                 if ((n_tokens >= 5) &&
2177                         (strcmp(tokens[2], "subport") == 0) &&
2178                         (strcmp(tokens[4], "pipe") == 0)) {
2179                         cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size);
2180                         return;
2181                 }
2182
2183                 cmd_tmgr(tokens, n_tokens, out, out_size);
2184                 return;
2185         }
2186
2187         if (strcmp(tokens[0], "tap") == 0) {
2188                 cmd_tap(tokens, n_tokens, out, out_size);
2189                 return;
2190         }
2191
2192         if (strcmp(tokens[0], "kni") == 0) {
2193                 cmd_kni(tokens, n_tokens, out, out_size);
2194                 return;
2195         }
2196
2197         if (strcmp(tokens[0], "port") == 0) {
2198                 cmd_port_in_action_profile(tokens, n_tokens, out, out_size);
2199                 return;
2200         }
2201
2202         if (strcmp(tokens[0], "table") == 0) {
2203                 cmd_table_action_profile(tokens, n_tokens, out, out_size);
2204                 return;
2205         }
2206
2207         if (strcmp(tokens[0], "pipeline") == 0) {
2208                 if ((n_tokens >= 3) &&
2209                         (strcmp(tokens[2], "period") == 0)) {
2210                         cmd_pipeline(tokens, n_tokens, out, out_size);
2211                         return;
2212                 }
2213
2214                 if ((n_tokens >= 5) &&
2215                         (strcmp(tokens[2], "port") == 0) &&
2216                         (strcmp(tokens[3], "in") == 0) &&
2217                         (strcmp(tokens[4], "bsz") == 0)) {
2218                         cmd_pipeline_port_in(tokens, n_tokens, out, out_size);
2219                         return;
2220                 }
2221
2222                 if ((n_tokens >= 5) &&
2223                         (strcmp(tokens[2], "port") == 0) &&
2224                         (strcmp(tokens[3], "out") == 0) &&
2225                         (strcmp(tokens[4], "bsz") == 0)) {
2226                         cmd_pipeline_port_out(tokens, n_tokens, out, out_size);
2227                         return;
2228                 }
2229
2230                 if ((n_tokens >= 4) &&
2231                         (strcmp(tokens[2], "table") == 0) &&
2232                         (strcmp(tokens[3], "match") == 0)) {
2233                         cmd_pipeline_table(tokens, n_tokens, out, out_size);
2234                         return;
2235                 }
2236
2237                 if ((n_tokens >= 6) &&
2238                         (strcmp(tokens[2], "port") == 0) &&
2239                         (strcmp(tokens[3], "in") == 0) &&
2240                         (strcmp(tokens[5], "table") == 0)) {
2241                         cmd_pipeline_port_in_table(tokens, n_tokens,
2242                                 out, out_size);
2243                         return;
2244                 }
2245
2246                 if ((n_tokens >= 6) &&
2247                         (strcmp(tokens[2], "port") == 0) &&
2248                         (strcmp(tokens[3], "in") == 0) &&
2249                         (strcmp(tokens[5], "enable") == 0)) {
2250                         cmd_pipeline_port_in_enable(tokens, n_tokens,
2251                                 out, out_size);
2252                         return;
2253                 }
2254
2255                 if ((n_tokens >= 6) &&
2256                         (strcmp(tokens[2], "port") == 0) &&
2257                         (strcmp(tokens[3], "in") == 0) &&
2258                         (strcmp(tokens[5], "disable") == 0)) {
2259                         cmd_pipeline_port_in_disable(tokens, n_tokens,
2260                                 out, out_size);
2261                         return;
2262                 }
2263         }
2264
2265         if (strcmp(tokens[0], "thread") == 0) {
2266                 if ((n_tokens >= 5) &&
2267                         (strcmp(tokens[4], "enable") == 0)) {
2268                         cmd_thread_pipeline_enable(tokens, n_tokens,
2269                                 out, out_size);
2270                         return;
2271                 }
2272
2273                 if ((n_tokens >= 5) &&
2274                         (strcmp(tokens[4], "disable") == 0)) {
2275                         cmd_thread_pipeline_disable(tokens, n_tokens,
2276                                 out, out_size);
2277                         return;
2278                 }
2279         }
2280
2281         snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
2282 }
2283
2284 int
2285 cli_script_process(const char *file_name,
2286         size_t msg_in_len_max,
2287         size_t msg_out_len_max)
2288 {
2289         char *msg_in = NULL, *msg_out = NULL;
2290         FILE *f = NULL;
2291
2292         /* Check input arguments */
2293         if ((file_name == NULL) ||
2294                 (strlen(file_name) == 0) ||
2295                 (msg_in_len_max == 0) ||
2296                 (msg_out_len_max == 0))
2297                 return -EINVAL;
2298
2299         msg_in = malloc(msg_in_len_max + 1);
2300         msg_out = malloc(msg_out_len_max + 1);
2301         if ((msg_in == NULL) ||
2302                 (msg_out == NULL)) {
2303                 free(msg_out);
2304                 free(msg_in);
2305                 return -ENOMEM;
2306         }
2307
2308         /* Open input file */
2309         f = fopen(file_name, "r");
2310         if (f == NULL) {
2311                 free(msg_out);
2312                 free(msg_in);
2313                 return -EIO;
2314         }
2315
2316         /* Read file */
2317         for ( ; ; ) {
2318                 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
2319                         break;
2320
2321                 printf("%s", msg_in);
2322                 msg_out[0] = 0;
2323
2324                 cli_process(msg_in,
2325                         msg_out,
2326                         msg_out_len_max);
2327
2328                 if (strlen(msg_out))
2329                         printf("%s", msg_out);
2330         }
2331
2332         /* Close file */
2333         fclose(f);
2334         free(msg_out);
2335         free(msg_in);
2336         return 0;
2337 }