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