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