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