dc37a5f06f4f5ba29389a850479f7adbce37071d
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_common_fe.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37
38 #include <rte_common.h>
39 #include <rte_ring.h>
40 #include <rte_malloc.h>
41 #include <cmdline_rdline.h>
42 #include <cmdline_parse.h>
43 #include <cmdline_parse_num.h>
44 #include <cmdline_parse_string.h>
45 #include <cmdline.h>
46
47 #include "pipeline_common_fe.h"
48 #include "parser.h"
49
50 int
51 app_pipeline_ping(struct app_params *app,
52         uint32_t pipeline_id)
53 {
54         struct app_pipeline_params *p;
55         struct pipeline_msg_req *req;
56         struct pipeline_msg_rsp *rsp;
57         int status = 0;
58
59         /* Check input arguments */
60         if (app == NULL)
61                 return -1;
62
63         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
64         if (p == NULL)
65                 return -1;
66
67         /* Message buffer allocation */
68         req = app_msg_alloc(app);
69         if (req == NULL)
70                 return -1;
71
72         /* Fill in request */
73         req->type = PIPELINE_MSG_REQ_PING;
74
75         /* Send request and wait for response */
76         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
77         if (rsp == NULL)
78                 return -1;
79
80         /* Check response */
81         status = rsp->status;
82
83         /* Message buffer free */
84         app_msg_free(app, rsp);
85
86         return status;
87 }
88
89 int
90 app_pipeline_stats_port_in(struct app_params *app,
91         uint32_t pipeline_id,
92         uint32_t port_id,
93         struct rte_pipeline_port_in_stats *stats)
94 {
95         struct app_pipeline_params *p;
96         struct pipeline_stats_msg_req *req;
97         struct pipeline_stats_port_in_msg_rsp *rsp;
98         int status = 0;
99
100         /* Check input arguments */
101         if ((app == NULL) ||
102                 (stats == NULL))
103                 return -1;
104
105         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
106         if ((p == NULL) ||
107                 (port_id >= p->n_pktq_in))
108                 return -1;
109
110         /* Message buffer allocation */
111         req = app_msg_alloc(app);
112         if (req == NULL)
113                 return -1;
114
115         /* Fill in request */
116         req->type = PIPELINE_MSG_REQ_STATS_PORT_IN;
117         req->id = port_id;
118
119         /* Send request and wait for response */
120         rsp = (struct pipeline_stats_port_in_msg_rsp *)
121                 app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
122         if (rsp == NULL)
123                 return -1;
124
125         /* Check response */
126         status = rsp->status;
127         if (status == 0)
128                 memcpy(stats, &rsp->stats, sizeof(rsp->stats));
129
130         /* Message buffer free */
131         app_msg_free(app, rsp);
132
133         return status;
134 }
135
136 int
137 app_pipeline_stats_port_out(struct app_params *app,
138         uint32_t pipeline_id,
139         uint32_t port_id,
140         struct rte_pipeline_port_out_stats *stats)
141 {
142         struct app_pipeline_params *p;
143         struct pipeline_stats_msg_req *req;
144         struct pipeline_stats_port_out_msg_rsp *rsp;
145         int status = 0;
146
147         /* Check input arguments */
148         if ((app == NULL) ||
149                 (pipeline_id >= app->n_pipelines) ||
150                 (stats == NULL))
151                 return -1;
152
153         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
154         if ((p == NULL) ||
155                 (port_id >= p->n_pktq_out))
156                 return -1;
157
158         /* Message buffer allocation */
159         req = app_msg_alloc(app);
160         if (req == NULL)
161                 return -1;
162
163         /* Fill in request */
164         req->type = PIPELINE_MSG_REQ_STATS_PORT_OUT;
165         req->id = port_id;
166
167         /* Send request and wait for response */
168         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
169         if (rsp == NULL)
170                 return -1;
171
172         /* Check response */
173         status = rsp->status;
174         if (status == 0)
175                 memcpy(stats, &rsp->stats, sizeof(rsp->stats));
176
177         /* Message buffer free */
178         app_msg_free(app, rsp);
179
180         return status;
181 }
182
183 int
184 app_pipeline_stats_table(struct app_params *app,
185         uint32_t pipeline_id,
186         uint32_t table_id,
187         struct rte_pipeline_table_stats *stats)
188 {
189         struct app_pipeline_params *p;
190         struct pipeline_stats_msg_req *req;
191         struct pipeline_stats_table_msg_rsp *rsp;
192         int status = 0;
193
194         /* Check input arguments */
195         if ((app == NULL) ||
196                 (stats == NULL))
197                 return -1;
198
199         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
200         if (p == NULL)
201                 return -1;
202
203         /* Message buffer allocation */
204         req = app_msg_alloc(app);
205         if (req == NULL)
206                 return -1;
207
208         /* Fill in request */
209         req->type = PIPELINE_MSG_REQ_STATS_TABLE;
210         req->id = table_id;
211
212         /* Send request and wait for response */
213         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
214         if (rsp == NULL)
215                 return -1;
216
217         /* Check response */
218         status = rsp->status;
219         if (status == 0)
220                 memcpy(stats, &rsp->stats, sizeof(rsp->stats));
221
222         /* Message buffer free */
223         app_msg_free(app, rsp);
224
225         return status;
226 }
227
228 int
229 app_pipeline_port_in_enable(struct app_params *app,
230         uint32_t pipeline_id,
231         uint32_t port_id)
232 {
233         struct app_pipeline_params *p;
234         struct pipeline_port_in_msg_req *req;
235         struct pipeline_msg_rsp *rsp;
236         int status = 0;
237
238         /* Check input arguments */
239         if (app == NULL)
240                 return -1;
241
242         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
243         if ((p == NULL) ||
244                 (port_id >= p->n_pktq_in))
245                 return -1;
246
247         /* Message buffer allocation */
248         req = app_msg_alloc(app);
249         if (req == NULL)
250                 return -1;
251
252         /* Fill in request */
253         req->type = PIPELINE_MSG_REQ_PORT_IN_ENABLE;
254         req->port_id = port_id;
255
256         /* Send request and wait for response */
257         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
258         if (rsp == NULL)
259                 return -1;
260
261         /* Check response */
262         status = rsp->status;
263
264         /* Message buffer free */
265         app_msg_free(app, rsp);
266
267         return status;
268 }
269
270 int
271 app_pipeline_port_in_disable(struct app_params *app,
272         uint32_t pipeline_id,
273         uint32_t port_id)
274 {
275         struct app_pipeline_params *p;
276         struct pipeline_port_in_msg_req *req;
277         struct pipeline_msg_rsp *rsp;
278         int status = 0;
279
280         /* Check input arguments */
281         if (app == NULL)
282                 return -1;
283
284         APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
285         if ((p == NULL) ||
286                 (port_id >= p->n_pktq_in))
287                 return -1;
288
289         /* Message buffer allocation */
290         req = app_msg_alloc(app);
291         if (req == NULL)
292                 return -1;
293
294         /* Fill in request */
295         req->type = PIPELINE_MSG_REQ_PORT_IN_DISABLE;
296         req->port_id = port_id;
297
298         /* Send request and wait for response */
299         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
300         if (rsp == NULL)
301                 return -1;
302
303         /* Check response */
304         status = rsp->status;
305
306         /* Message buffer free */
307         app_msg_free(app, rsp);
308
309         return status;
310 }
311
312 int
313 app_link_config(struct app_params *app,
314         uint32_t link_id,
315         uint32_t ip,
316         uint32_t depth)
317 {
318         struct app_link_params *p;
319         uint32_t i, netmask, host, bcast;
320
321         /* Check input arguments */
322         if (app == NULL)
323                 return -1;
324
325         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
326         if (p == NULL) {
327                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
328                         link_id);
329                 return -1;
330         }
331
332         if (p->state) {
333                 APP_LOG(app, HIGH, "%s is UP, please bring it DOWN first",
334                         p->name);
335                 return -1;
336         }
337
338         netmask = (~0U) << (32 - depth);
339         host = ip & netmask;
340         bcast = host | (~netmask);
341
342         if ((ip == 0) ||
343                 (ip == UINT32_MAX) ||
344                 (ip == host) ||
345                 (ip == bcast)) {
346                 APP_LOG(app, HIGH, "Illegal IP address");
347                 return -1;
348         }
349
350         for (i = 0; i < app->n_links; i++) {
351                 struct app_link_params *link = &app->link_params[i];
352
353                 if (strcmp(p->name, link->name) == 0)
354                         continue;
355
356                 if (link->ip == ip) {
357                         APP_LOG(app, HIGH,
358                                 "%s is already assigned this IP address",
359                                 link->name);
360                         return -1;
361                 }
362         }
363
364         if ((depth == 0) || (depth > 32)) {
365                 APP_LOG(app, HIGH, "Illegal value for depth parameter "
366                         "(%" PRIu32 ")",
367                         depth);
368                 return -1;
369         }
370
371         /* Save link parameters */
372         p->ip = ip;
373         p->depth = depth;
374
375         return 0;
376 }
377
378 int
379 app_link_up(struct app_params *app,
380         uint32_t link_id)
381 {
382         struct app_link_params *p;
383
384         /* Check input arguments */
385         if (app == NULL)
386                 return -1;
387
388         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
389         if (p == NULL) {
390                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
391                         link_id);
392                 return -1;
393         }
394
395         /* Check link state */
396         if (p->state) {
397                 APP_LOG(app, HIGH, "%s is already UP", p->name);
398                 return 0;
399         }
400
401         /* Check that IP address is valid */
402         if (p->ip == 0) {
403                 APP_LOG(app, HIGH, "%s IP address is not set", p->name);
404                 return 0;
405         }
406
407         app_link_up_internal(app, p);
408
409         return 0;
410 }
411
412 int
413 app_link_down(struct app_params *app,
414         uint32_t link_id)
415 {
416         struct app_link_params *p;
417
418         /* Check input arguments */
419         if (app == NULL)
420                 return -1;
421
422         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
423         if (p == NULL) {
424                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
425                         link_id);
426                 return -1;
427         }
428
429         /* Check link state */
430         if (p->state == 0) {
431                 APP_LOG(app, HIGH, "%s is already DOWN", p->name);
432                 return 0;
433         }
434
435         app_link_down_internal(app, p);
436
437         return 0;
438 }
439
440 /*
441  * ping
442  */
443
444 struct cmd_ping_result {
445         cmdline_fixed_string_t p_string;
446         uint32_t pipeline_id;
447         cmdline_fixed_string_t ping_string;
448 };
449
450 static void
451 cmd_ping_parsed(
452         void *parsed_result,
453         __rte_unused struct cmdline *cl,
454         void *data)
455 {
456         struct cmd_ping_result *params = parsed_result;
457         struct app_params *app = data;
458         int status;
459
460         status = app_pipeline_ping(app, params->pipeline_id);
461         if (status != 0)
462                 printf("Command failed\n");
463 }
464
465 static cmdline_parse_token_string_t cmd_ping_p_string =
466         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p");
467
468 static cmdline_parse_token_num_t cmd_ping_pipeline_id =
469         TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32);
470
471 static cmdline_parse_token_string_t cmd_ping_ping_string =
472         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping");
473
474 static cmdline_parse_inst_t cmd_ping = {
475         .f = cmd_ping_parsed,
476         .data = NULL,
477         .help_str = "Pipeline ping",
478         .tokens = {
479                 (void *) &cmd_ping_p_string,
480                 (void *) &cmd_ping_pipeline_id,
481                 (void *) &cmd_ping_ping_string,
482                 NULL,
483         },
484 };
485
486 /*
487  * stats port in
488  */
489
490 struct cmd_stats_port_in_result {
491         cmdline_fixed_string_t p_string;
492         uint32_t pipeline_id;
493         cmdline_fixed_string_t stats_string;
494         cmdline_fixed_string_t port_string;
495         cmdline_fixed_string_t in_string;
496         uint32_t port_in_id;
497
498 };
499
500 static void
501 cmd_stats_port_in_parsed(
502         void *parsed_result,
503         __rte_unused struct cmdline *cl,
504         void *data)
505 {
506         struct cmd_stats_port_in_result *params = parsed_result;
507         struct app_params *app = data;
508         struct rte_pipeline_port_in_stats stats;
509         int status;
510
511         status = app_pipeline_stats_port_in(app,
512                         params->pipeline_id,
513                         params->port_in_id,
514                         &stats);
515
516         if (status != 0) {
517                 printf("Command failed\n");
518                 return;
519         }
520
521         /* Display stats */
522         printf("Pipeline %" PRIu32 " - stats for input port %" PRIu32 ":\n"
523                 "\tPkts in: %" PRIu64 "\n"
524                 "\tPkts dropped by AH: %" PRIu64 "\n"
525                 "\tPkts dropped by other: %" PRIu64 "\n",
526                 params->pipeline_id,
527                 params->port_in_id,
528                 stats.stats.n_pkts_in,
529                 stats.n_pkts_dropped_by_ah,
530                 stats.stats.n_pkts_drop);
531 }
532
533 static cmdline_parse_token_string_t cmd_stats_port_in_p_string =
534         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string,
535                 "p");
536
537 static cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id =
538         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id,
539                 UINT32);
540
541 static cmdline_parse_token_string_t cmd_stats_port_in_stats_string =
542         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string,
543                 "stats");
544
545 static cmdline_parse_token_string_t cmd_stats_port_in_port_string =
546         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string,
547                 "port");
548
549 static cmdline_parse_token_string_t cmd_stats_port_in_in_string =
550         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string,
551                 "in");
552
553         cmdline_parse_token_num_t cmd_stats_port_in_port_in_id =
554         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id,
555                 UINT32);
556
557 static cmdline_parse_inst_t cmd_stats_port_in = {
558         .f = cmd_stats_port_in_parsed,
559         .data = NULL,
560         .help_str = "Pipeline input port stats",
561         .tokens = {
562                 (void *) &cmd_stats_port_in_p_string,
563                 (void *) &cmd_stats_port_in_pipeline_id,
564                 (void *) &cmd_stats_port_in_stats_string,
565                 (void *) &cmd_stats_port_in_port_string,
566                 (void *) &cmd_stats_port_in_in_string,
567                 (void *) &cmd_stats_port_in_port_in_id,
568                 NULL,
569         },
570 };
571
572 /*
573  * stats port out
574  */
575
576 struct cmd_stats_port_out_result {
577         cmdline_fixed_string_t p_string;
578         uint32_t pipeline_id;
579         cmdline_fixed_string_t stats_string;
580         cmdline_fixed_string_t port_string;
581         cmdline_fixed_string_t out_string;
582         uint32_t port_out_id;
583 };
584
585 static void
586 cmd_stats_port_out_parsed(
587         void *parsed_result,
588         __rte_unused struct cmdline *cl,
589         void *data)
590 {
591
592         struct cmd_stats_port_out_result *params = parsed_result;
593         struct app_params *app = data;
594         struct rte_pipeline_port_out_stats stats;
595         int status;
596
597         status = app_pipeline_stats_port_out(app,
598                         params->pipeline_id,
599                         params->port_out_id,
600                         &stats);
601
602         if (status != 0) {
603                 printf("Command failed\n");
604                 return;
605         }
606
607         /* Display stats */
608         printf("Pipeline %" PRIu32 " - stats for output port %" PRIu32 ":\n"
609                 "\tPkts in: %" PRIu64 "\n"
610                 "\tPkts dropped by AH: %" PRIu64 "\n"
611                 "\tPkts dropped by other: %" PRIu64 "\n",
612                 params->pipeline_id,
613                 params->port_out_id,
614                 stats.stats.n_pkts_in,
615                 stats.n_pkts_dropped_by_ah,
616                 stats.stats.n_pkts_drop);
617 }
618
619 static cmdline_parse_token_string_t cmd_stats_port_out_p_string =
620         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string,
621         "p");
622
623 static cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id =
624         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id,
625                 UINT32);
626
627 static cmdline_parse_token_string_t cmd_stats_port_out_stats_string =
628         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string,
629                 "stats");
630
631 static cmdline_parse_token_string_t cmd_stats_port_out_port_string =
632         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string,
633                 "port");
634
635 static cmdline_parse_token_string_t cmd_stats_port_out_out_string =
636         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string,
637                 "out");
638
639 static cmdline_parse_token_num_t cmd_stats_port_out_port_out_id =
640         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id,
641                 UINT32);
642
643 static cmdline_parse_inst_t cmd_stats_port_out = {
644         .f = cmd_stats_port_out_parsed,
645         .data = NULL,
646         .help_str = "Pipeline output port stats",
647         .tokens = {
648                 (void *) &cmd_stats_port_out_p_string,
649                 (void *) &cmd_stats_port_out_pipeline_id,
650                 (void *) &cmd_stats_port_out_stats_string,
651                 (void *) &cmd_stats_port_out_port_string,
652                 (void *) &cmd_stats_port_out_out_string,
653                 (void *) &cmd_stats_port_out_port_out_id,
654                 NULL,
655         },
656 };
657
658 /*
659  * stats table
660  */
661
662 struct cmd_stats_table_result {
663         cmdline_fixed_string_t p_string;
664         uint32_t pipeline_id;
665         cmdline_fixed_string_t stats_string;
666         cmdline_fixed_string_t table_string;
667         uint32_t table_id;
668 };
669
670 static void
671 cmd_stats_table_parsed(
672         void *parsed_result,
673         __rte_unused struct cmdline *cl,
674         void *data)
675 {
676         struct cmd_stats_table_result *params = parsed_result;
677         struct app_params *app = data;
678         struct rte_pipeline_table_stats stats;
679         int status;
680
681         status = app_pipeline_stats_table(app,
682                         params->pipeline_id,
683                         params->table_id,
684                         &stats);
685
686         if (status != 0) {
687                 printf("Command failed\n");
688                 return;
689         }
690
691         /* Display stats */
692         printf("Pipeline %" PRIu32 " - stats for table %" PRIu32 ":\n"
693                 "\tPkts in: %" PRIu64 "\n"
694                 "\tPkts in with lookup miss: %" PRIu64 "\n"
695                 "\tPkts in with lookup hit dropped by AH: %" PRIu64 "\n"
696                 "\tPkts in with lookup hit dropped by others: %" PRIu64 "\n"
697                 "\tPkts in with lookup miss dropped by AH: %" PRIu64 "\n"
698                 "\tPkts in with lookup miss dropped by others: %" PRIu64 "\n",
699                 params->pipeline_id,
700                 params->table_id,
701                 stats.stats.n_pkts_in,
702                 stats.stats.n_pkts_lookup_miss,
703                 stats.n_pkts_dropped_by_lkp_hit_ah,
704                 stats.n_pkts_dropped_lkp_hit,
705                 stats.n_pkts_dropped_by_lkp_miss_ah,
706                 stats.n_pkts_dropped_lkp_miss);
707 }
708
709 static cmdline_parse_token_string_t cmd_stats_table_p_string =
710         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string,
711                 "p");
712
713 static cmdline_parse_token_num_t cmd_stats_table_pipeline_id =
714         TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id,
715                 UINT32);
716
717 static cmdline_parse_token_string_t cmd_stats_table_stats_string =
718         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string,
719                 "stats");
720
721 static cmdline_parse_token_string_t cmd_stats_table_table_string =
722         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string,
723                 "table");
724
725 static cmdline_parse_token_num_t cmd_stats_table_table_id =
726         TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32);
727
728 static cmdline_parse_inst_t cmd_stats_table = {
729         .f = cmd_stats_table_parsed,
730         .data = NULL,
731         .help_str = "Pipeline table stats",
732         .tokens = {
733                 (void *) &cmd_stats_table_p_string,
734                 (void *) &cmd_stats_table_pipeline_id,
735                 (void *) &cmd_stats_table_stats_string,
736                 (void *) &cmd_stats_table_table_string,
737                 (void *) &cmd_stats_table_table_id,
738                 NULL,
739         },
740 };
741
742 /*
743  * port in enable
744  */
745
746 struct cmd_port_in_enable_result {
747         cmdline_fixed_string_t p_string;
748         uint32_t pipeline_id;
749         cmdline_fixed_string_t port_string;
750         cmdline_fixed_string_t in_string;
751         uint32_t port_in_id;
752         cmdline_fixed_string_t enable_string;
753 };
754
755 static void
756 cmd_port_in_enable_parsed(
757         void *parsed_result,
758         __rte_unused struct cmdline *cl,
759         void *data)
760 {
761         struct cmd_port_in_enable_result *params = parsed_result;
762         struct app_params *app = data;
763         int status;
764
765         status = app_pipeline_port_in_enable(app,
766                         params->pipeline_id,
767                         params->port_in_id);
768
769         if (status != 0)
770                 printf("Command failed\n");
771 }
772
773 static cmdline_parse_token_string_t cmd_port_in_enable_p_string =
774         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string,
775                 "p");
776
777 static cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id =
778         TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id,
779                 UINT32);
780
781 static cmdline_parse_token_string_t cmd_port_in_enable_port_string =
782         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string,
783         "port");
784
785 static cmdline_parse_token_string_t cmd_port_in_enable_in_string =
786         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string,
787                 "in");
788
789 static cmdline_parse_token_num_t cmd_port_in_enable_port_in_id =
790         TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id,
791                 UINT32);
792
793 static cmdline_parse_token_string_t cmd_port_in_enable_enable_string =
794         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result,
795                 enable_string, "enable");
796
797 static cmdline_parse_inst_t cmd_port_in_enable = {
798         .f = cmd_port_in_enable_parsed,
799         .data = NULL,
800         .help_str = "Pipeline input port enable",
801         .tokens = {
802                 (void *) &cmd_port_in_enable_p_string,
803                 (void *) &cmd_port_in_enable_pipeline_id,
804                 (void *) &cmd_port_in_enable_port_string,
805                 (void *) &cmd_port_in_enable_in_string,
806                 (void *) &cmd_port_in_enable_port_in_id,
807                 (void *) &cmd_port_in_enable_enable_string,
808                 NULL,
809         },
810 };
811
812 /*
813  * port in disable
814  */
815
816 struct cmd_port_in_disable_result {
817         cmdline_fixed_string_t p_string;
818         uint32_t pipeline_id;
819         cmdline_fixed_string_t port_string;
820         cmdline_fixed_string_t in_string;
821         uint32_t port_in_id;
822         cmdline_fixed_string_t disable_string;
823 };
824
825 static void
826 cmd_port_in_disable_parsed(
827         void *parsed_result,
828         __rte_unused struct cmdline *cl,
829         void *data)
830 {
831         struct cmd_port_in_disable_result *params = parsed_result;
832         struct app_params *app = data;
833         int status;
834
835         status = app_pipeline_port_in_disable(app,
836                         params->pipeline_id,
837                         params->port_in_id);
838
839         if (status != 0)
840                 printf("Command failed\n");
841 }
842
843 static cmdline_parse_token_string_t cmd_port_in_disable_p_string =
844         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string,
845                 "p");
846
847 static cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id =
848         TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id,
849                 UINT32);
850
851 static cmdline_parse_token_string_t cmd_port_in_disable_port_string =
852         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string,
853                 "port");
854
855 static cmdline_parse_token_string_t cmd_port_in_disable_in_string =
856         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string,
857                 "in");
858
859 static cmdline_parse_token_num_t cmd_port_in_disable_port_in_id =
860         TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id,
861                 UINT32);
862
863 static cmdline_parse_token_string_t cmd_port_in_disable_disable_string =
864         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result,
865                 disable_string, "disable");
866
867 static cmdline_parse_inst_t cmd_port_in_disable = {
868         .f = cmd_port_in_disable_parsed,
869         .data = NULL,
870         .help_str = "Pipeline input port disable",
871         .tokens = {
872                 (void *) &cmd_port_in_disable_p_string,
873                 (void *) &cmd_port_in_disable_pipeline_id,
874                 (void *) &cmd_port_in_disable_port_string,
875                 (void *) &cmd_port_in_disable_in_string,
876                 (void *) &cmd_port_in_disable_port_in_id,
877                 (void *) &cmd_port_in_disable_disable_string,
878                 NULL,
879         },
880 };
881
882 /*
883  * link config
884  */
885
886 static void
887 print_link_info(struct app_link_params *p)
888 {
889         struct rte_eth_stats stats;
890         struct ether_addr *mac_addr;
891         uint32_t netmask = (~0U) << (32 - p->depth);
892         uint32_t host = p->ip & netmask;
893         uint32_t bcast = host | (~netmask);
894
895         memset(&stats, 0, sizeof(stats));
896         rte_eth_stats_get(p->pmd_id, &stats);
897
898         mac_addr = (struct ether_addr *) &p->mac_addr;
899
900         if (strlen(p->pci_bdf))
901                 printf("%s(%s): flags=<%s>\n",
902                         p->name,
903                         p->pci_bdf,
904                         (p->state) ? "UP" : "DOWN");
905         else
906                 printf("%s: flags=<%s>\n",
907                         p->name,
908                         (p->state) ? "UP" : "DOWN");
909
910         if (p->ip)
911                 printf("\tinet %" PRIu32 ".%" PRIu32
912                         ".%" PRIu32 ".%" PRIu32
913                         " netmask %" PRIu32 ".%" PRIu32
914                         ".%" PRIu32 ".%" PRIu32 " "
915                         "broadcast %" PRIu32 ".%" PRIu32
916                         ".%" PRIu32 ".%" PRIu32 "\n",
917                         (p->ip >> 24) & 0xFF,
918                         (p->ip >> 16) & 0xFF,
919                         (p->ip >> 8) & 0xFF,
920                         p->ip & 0xFF,
921                         (netmask >> 24) & 0xFF,
922                         (netmask >> 16) & 0xFF,
923                         (netmask >> 8) & 0xFF,
924                         netmask & 0xFF,
925                         (bcast >> 24) & 0xFF,
926                         (bcast >> 16) & 0xFF,
927                         (bcast >> 8) & 0xFF,
928                         bcast & 0xFF);
929
930         printf("\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
931                 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
932                 mac_addr->addr_bytes[0],
933                 mac_addr->addr_bytes[1],
934                 mac_addr->addr_bytes[2],
935                 mac_addr->addr_bytes[3],
936                 mac_addr->addr_bytes[4],
937                 mac_addr->addr_bytes[5]);
938
939         printf("\tRX packets %" PRIu64
940                 "  bytes %" PRIu64
941                 "\n",
942                 stats.ipackets,
943                 stats.ibytes);
944
945         printf("\tRX errors %" PRIu64
946                 "  missed %" PRIu64
947                 "  no-mbuf %" PRIu64
948                 "\n",
949                 stats.ierrors,
950                 stats.imissed,
951                 stats.rx_nombuf);
952
953         printf("\tTX packets %" PRIu64
954                 "  bytes %" PRIu64 "\n",
955                 stats.opackets,
956                 stats.obytes);
957
958         printf("\tTX errors %" PRIu64
959                 "\n",
960                 stats.oerrors);
961
962         printf("\n");
963 }
964
965 /*
966  * link
967  *
968  * link config:
969  *    link <linkid> config <ipaddr> <depth>
970  *
971  * link up:
972  *    link <linkid> up
973  *
974  * link down:
975  *    link <linkid> down
976  *
977  * link ls:
978  *    link ls
979  */
980
981 struct cmd_link_result {
982         cmdline_fixed_string_t link_string;
983         cmdline_multi_string_t multi_string;
984 };
985
986 static void
987 cmd_link_parsed(
988         void *parsed_result,
989         __attribute__((unused)) struct cmdline *cl,
990          void *data)
991 {
992         struct cmd_link_result *params = parsed_result;
993         struct app_params *app = data;
994
995         char *tokens[16];
996         uint32_t n_tokens = RTE_DIM(tokens);
997         int status;
998
999         uint32_t link_id;
1000
1001         status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1002         if (status != 0) {
1003                 printf(CMD_MSG_TOO_MANY_ARGS, "link");
1004                 return;
1005         }
1006
1007         /* link ls */
1008         if ((n_tokens == 1) && (strcmp(tokens[0], "ls") == 0)) {
1009                 for (link_id = 0; link_id < app->n_links; link_id++) {
1010                         struct app_link_params *p;
1011
1012                         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
1013                         print_link_info(p);
1014                 }
1015                 return;
1016         } /* link ls */
1017
1018         if (n_tokens < 2) {
1019                 printf(CMD_MSG_MISMATCH_ARGS, "link");
1020                 return;
1021         }
1022
1023         if (parser_read_uint32(&link_id, tokens[0])) {
1024                 printf(CMD_MSG_INVALID_ARG, "linkid");
1025                 return;
1026         }
1027
1028         /* link config */
1029         if (strcmp(tokens[1], "config") == 0) {
1030                 struct in_addr ipaddr_ipv4;
1031                 uint32_t depth;
1032
1033                 if (n_tokens != 4) {
1034                         printf(CMD_MSG_MISMATCH_ARGS, "link config");
1035                         return;
1036                 }
1037
1038                 if (parse_ipv4_addr(tokens[2], &ipaddr_ipv4)) {
1039                         printf(CMD_MSG_INVALID_ARG, "ipaddr");
1040                         return;
1041                 }
1042
1043                 if (parser_read_uint32(&depth, tokens[3])) {
1044                         printf(CMD_MSG_INVALID_ARG, "depth");
1045                         return;
1046                 }
1047
1048                 status = app_link_config(app,
1049                         link_id,
1050                         rte_be_to_cpu_32(ipaddr_ipv4.s_addr),
1051                         depth);
1052                 if (status)
1053                         printf(CMD_MSG_FAIL, "link config");
1054
1055                 return;
1056         } /* link config */
1057
1058         /* link up */
1059         if (strcmp(tokens[1], "up") == 0) {
1060                 if (n_tokens != 2) {
1061                         printf(CMD_MSG_MISMATCH_ARGS, "link up");
1062                         return;
1063                 }
1064
1065                 status = app_link_up(app, link_id);
1066                 if (status)
1067                         printf(CMD_MSG_FAIL, "link up");
1068
1069                 return;
1070         } /* link up */
1071
1072         /* link down */
1073         if (strcmp(tokens[1], "down") == 0) {
1074                 if (n_tokens != 2) {
1075                         printf(CMD_MSG_MISMATCH_ARGS, "link down");
1076                         return;
1077                 }
1078
1079                 status = app_link_down(app, link_id);
1080                 if (status)
1081                         printf(CMD_MSG_FAIL, "link down");
1082
1083                 return;
1084         } /* link down */
1085
1086         printf(CMD_MSG_MISMATCH_ARGS, "link");
1087 }
1088
1089 static cmdline_parse_token_string_t cmd_link_link_string =
1090         TOKEN_STRING_INITIALIZER(struct cmd_link_result, link_string, "link");
1091
1092 static cmdline_parse_token_string_t cmd_link_multi_string =
1093         TOKEN_STRING_INITIALIZER(struct cmd_link_result, multi_string,
1094         TOKEN_STRING_MULTI);
1095
1096 static cmdline_parse_inst_t cmd_link = {
1097         .f = cmd_link_parsed,
1098         .data = NULL,
1099         .help_str = "link config / up / down / ls",
1100         .tokens = {
1101                 (void *) &cmd_link_link_string,
1102                 (void *) &cmd_link_multi_string,
1103                 NULL,
1104         },
1105 };
1106
1107 /*
1108  * quit
1109  */
1110
1111 struct cmd_quit_result {
1112         cmdline_fixed_string_t quit;
1113 };
1114
1115 static void
1116 cmd_quit_parsed(
1117         __rte_unused void *parsed_result,
1118         struct cmdline *cl,
1119         __rte_unused void *data)
1120 {
1121         cmdline_quit(cl);
1122 }
1123
1124 static cmdline_parse_token_string_t cmd_quit_quit =
1125         TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
1126
1127 static cmdline_parse_inst_t cmd_quit = {
1128         .f = cmd_quit_parsed,
1129         .data = NULL,
1130         .help_str = "Quit",
1131         .tokens = {
1132                 (void *) &cmd_quit_quit,
1133                 NULL,
1134         },
1135 };
1136
1137 /*
1138  * run
1139  *
1140  *    run <file>
1141  *    run <file> [<count> [<interval>]]
1142          <count> default is 1
1143  *       <interval> is measured in milliseconds, default is 1 second
1144  */
1145
1146 static void
1147 app_run_file(
1148         cmdline_parse_ctx_t *ctx,
1149         const char *file_name)
1150 {
1151         struct cmdline *file_cl;
1152         int fd;
1153
1154         fd = open(file_name, O_RDONLY);
1155         if (fd < 0) {
1156                 printf("Cannot open file \"%s\"\n", file_name);
1157                 return;
1158         }
1159
1160         file_cl = cmdline_new(ctx, "", fd, 1);
1161         cmdline_interact(file_cl);
1162         close(fd);
1163 }
1164
1165 struct cmd_run_result {
1166         cmdline_fixed_string_t run_string;
1167         cmdline_multi_string_t multi_string;
1168 };
1169
1170 static void
1171 cmd_run_parsed(
1172         void *parsed_result,
1173         struct cmdline *cl,
1174         __attribute__((unused)) void *data)
1175 {
1176         struct cmd_run_result *params = parsed_result;
1177
1178         char *tokens[16];
1179         uint32_t n_tokens = RTE_DIM(tokens);
1180         int status;
1181
1182         char *file_name;
1183         uint32_t count, interval, i;
1184
1185         status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1186         if (status) {
1187                 printf(CMD_MSG_TOO_MANY_ARGS, "run");
1188                 return;
1189         }
1190
1191         switch (n_tokens) {
1192         case 0:
1193                 printf(CMD_MSG_NOT_ENOUGH_ARGS, "run");
1194                 return;
1195
1196         case 1:
1197                 file_name = tokens[0];
1198                 count = 1;
1199                 interval = 1000;
1200                 break;
1201
1202         case 2:
1203                 file_name = tokens[0];
1204
1205                 if (parser_read_uint32(&count, tokens[1]) ||
1206                         (count == 0)) {
1207                         printf(CMD_MSG_INVALID_ARG, "count");
1208                         return;
1209                 }
1210
1211                 interval = 1000;
1212                 break;
1213
1214         case 3:
1215                 file_name = tokens[0];
1216
1217                 if (parser_read_uint32(&count, tokens[1]) ||
1218                         (count == 0)) {
1219                         printf(CMD_MSG_INVALID_ARG, "count");
1220                         return;
1221                 }
1222
1223                 if (parser_read_uint32(&interval, tokens[2]) ||
1224                         (interval == 0)) {
1225                         printf(CMD_MSG_INVALID_ARG, "interval");
1226                         return;
1227                 }
1228                 break;
1229
1230         default:
1231                 printf(CMD_MSG_MISMATCH_ARGS, "run");
1232                 return;
1233         }
1234
1235         for (i = 0; i < count; i++) {
1236                 app_run_file(cl->ctx, file_name);
1237                 if (interval)
1238                         usleep(interval * 1000);
1239         }
1240 }
1241
1242 static cmdline_parse_token_string_t cmd_run_run_string =
1243         TOKEN_STRING_INITIALIZER(struct cmd_run_result, run_string, "run");
1244
1245 static cmdline_parse_token_string_t cmd_run_multi_string =
1246         TOKEN_STRING_INITIALIZER(struct cmd_run_result, multi_string,
1247         TOKEN_STRING_MULTI);
1248
1249
1250 static cmdline_parse_inst_t cmd_run = {
1251         .f = cmd_run_parsed,
1252         .data = NULL,
1253         .help_str = "Run CLI script file",
1254         .tokens = {
1255                 (void *) &cmd_run_run_string,
1256                 (void *) &cmd_run_multi_string,
1257                 NULL,
1258         },
1259 };
1260
1261 static cmdline_parse_ctx_t pipeline_common_cmds[] = {
1262         (cmdline_parse_inst_t *) &cmd_quit,
1263         (cmdline_parse_inst_t *) &cmd_run,
1264         (cmdline_parse_inst_t *) &cmd_link,
1265         (cmdline_parse_inst_t *) &cmd_ping,
1266         (cmdline_parse_inst_t *) &cmd_stats_port_in,
1267         (cmdline_parse_inst_t *) &cmd_stats_port_out,
1268         (cmdline_parse_inst_t *) &cmd_stats_table,
1269         (cmdline_parse_inst_t *) &cmd_port_in_enable,
1270         (cmdline_parse_inst_t *) &cmd_port_in_disable,
1271         NULL,
1272 };
1273
1274 int
1275 app_pipeline_common_cmd_push(struct app_params *app)
1276 {
1277         uint32_t n_cmds, i;
1278
1279         /* Check for available slots in the application commands array */
1280         n_cmds = RTE_DIM(pipeline_common_cmds) - 1;
1281         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1282                 return -ENOMEM;
1283
1284         /* Push pipeline commands into the application */
1285         memcpy(&app->cmds[app->n_cmds],
1286                 pipeline_common_cmds,
1287                 n_cmds * sizeof(cmdline_parse_ctx_t));
1288
1289         for (i = 0; i < n_cmds; i++)
1290                 app->cmds[app->n_cmds + i]->data = app;
1291
1292         app->n_cmds += n_cmds;
1293         app->cmds[app->n_cmds] = NULL;
1294
1295         return 0;
1296 }