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