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