957f5df109d8555ee60723cb37c77363d8492dbe
[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 #include "lib_arp.h"
36 #include "gateway.h"
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         if (ifm_add_ipv4_port(link_id, rte_bswap32(ip), depth) == IFM_FAILURE)
363             return -1;
364
365         return 0;
366 }
367
368
369 void convert_prefixlen_to_netmask_ipv6(uint32_t depth, uint8_t netmask_ipv6[])
370 {
371         int mod, div, i;
372
373         memset(netmask_ipv6, 0, 16);
374
375         mod = depth % 8;
376         div = depth / 8;
377
378         for (i = 0; i < div; i++)
379                 netmask_ipv6[i] = 0xff;
380
381         netmask_ipv6[i] = (~0 << (8 - mod));
382
383         return;
384 }
385
386 void
387 get_host_portion_ipv6(uint8_t ipv6[], uint8_t netmask[], uint8_t host_ipv6[])
388 {
389         int i;
390
391         for (i = 0; i < 16; i++) {
392                 host_ipv6[i] = ipv6[i] & netmask[i];
393         }
394
395         return;
396 }
397
398 void
399 get_bcast_portion_ipv6(uint8_t host[], uint8_t netmask[], uint8_t bcast_ipv6[])
400 {
401         int i;
402
403         for (i = 0; i < 16; i++) {
404                 bcast_ipv6[i] = host[i] | ~netmask[i];
405         }
406
407         return;
408 }
409
410 int
411 app_link_config_ipv6(struct app_params *app,
412                                  uint32_t link_id, uint8_t ipv6[], uint32_t depth)
413 {
414         struct app_link_params *p;
415         uint32_t i;
416         uint8_t netmask_ipv6[16], host[16], bcast[16];
417
418         /* Check input arguments */
419         if (app == NULL)
420                 return -1;
421
422         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
423         if (p == NULL) {
424                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
425                         link_id);
426                 return -1;
427         }
428
429         if (p->state) {
430                 APP_LOG(app, HIGH, "%s is UP, please bring it DOWN first",
431                         p->name);
432                 return -1;
433         }
434
435         convert_prefixlen_to_netmask_ipv6(depth, netmask_ipv6);
436         get_host_portion_ipv6(ipv6, netmask_ipv6, host);
437         get_bcast_portion_ipv6(host, netmask_ipv6, bcast);
438
439         for (i = 0; i < app->n_links; i++) {
440                 struct app_link_params *link = &app->link_params[i];
441
442                 if (strcmp(p->name, link->name) == 0)
443                         continue;
444
445                 if (!memcmp(link->ipv6, ipv6, 16)) {
446                         APP_LOG(app, HIGH,
447                                 "%s is already assigned this IPv6 address",
448                                 link->name);
449                         return -1;
450                 }
451         }
452
453         if ((depth == 0) || (depth > 128)) {
454                 APP_LOG(app, HIGH, "Illegal value for depth parameter "
455                         "(%" PRIu32 ")", depth);
456                 return -1;
457         }
458
459         /* Save link parameters */
460         memcpy(p->ipv6, ipv6, 16);
461
462         p->depth_ipv6 = depth;
463 /*
464          printf("IPv6: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x",
465                                         ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5],
466                 ipv6[6], ipv6[7], ipv6[8], ipv6[9], ipv6[10], ipv6[11],
467                 ipv6[12], ipv6[13], ipv6[14], ipv6[15]);
468 */
469         if (ifm_add_ipv6_port(link_id, ipv6, depth) == IFM_FAILURE)
470                 return -1;
471         return 0;
472 }
473
474 int
475 app_link_up(struct app_params *app,
476         uint32_t link_id)
477 {
478         struct app_link_params *p;
479
480         /* Check input arguments */
481         if (app == NULL)
482                 return -1;
483
484         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
485         if (p == NULL) {
486                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
487                         link_id);
488                 return -1;
489         }
490
491         /* Check link state */
492         if (p->state) {
493                 APP_LOG(app, HIGH, "%s is already UP", p->name);
494                 return 0;
495         }
496
497         /* Check that IP address is valid */
498         uint8_t temp[16];
499
500         memset(temp, 0, 16);
501
502         if ((p->ip || memcmp(p->ipv6, temp, 16)) == 0) {
503                 APP_LOG(app, HIGH, "%s IP address is not set", p->name);
504                 return 0;
505         }
506
507         app_link_up_internal(app, p);
508
509         return 0;
510 }
511
512 int
513 app_link_down(struct app_params *app,
514         uint32_t link_id)
515 {
516         struct app_link_params *p;
517
518         /* Check input arguments */
519         if (app == NULL)
520                 return -1;
521
522         APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
523         if (p == NULL) {
524                 APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link",
525                         link_id);
526                 return -1;
527         }
528
529         /* Check link state */
530         if (p->state == 0) {
531                 APP_LOG(app, HIGH, "%s is already DOWN", p->name);
532                 return 0;
533         }
534
535         app_link_down_internal(app, p);
536
537         return 0;
538 }
539
540 /*
541  * Route add
542  */
543 struct cmd_routeadd_config_result {
544         cmdline_fixed_string_t routeadd_string;
545         cmdline_fixed_string_t type_string;
546         uint32_t port_id;
547         cmdline_ipaddr_t ip;
548         cmdline_fixed_string_t depth;
549 };
550
551 extern struct arp_data *p_arp_data;
552 extern uint32_t nd_route_tbl_index;
553
554 /*
555  * This implements route add entries for ipv4
556  */
557 int app_routeadd_config_ipv4(__attribute__((unused)) struct app_params *app,
558         uint32_t port_id, uint32_t ip, uint32_t mask)
559 {
560         uint32_t i = 0;
561         if (port_id >= gw_get_num_ports()) {
562                 printf("Max ports allowed is %d\n", gw_get_num_ports());
563                 return 1;
564         }
565
566         printf("port id:%d ip: %x mask:%x\n", port_id, ip, mask);
567
568         struct route_table_entry *lentry = NULL;
569
570         /* Check for matching entry */
571         for(i = 0 ; i< p_route_data[port_id]->route_ent_cnt; i++) {
572
573                 lentry = &p_route_data[port_id]->route_table[i];
574
575                 /* Entry already exists? */
576                 if(mask == 0) {
577                         if(lentry->nh == ip)
578                                 return 1;
579                 } else {
580                         if( lentry->nh_mask == (ip & mask))
581                                 return 1;
582                 }
583         }
584         if(i < MAX_ROUTE_ENTRY_SIZE) {
585
586                 lentry = &p_route_data[port_id]->route_table[i];
587
588                 p_route_data[port_id]->route_ent_cnt++;
589                 lentry->mask = mask;
590                 lentry->port = port_id;
591                 lentry->nh = ip;
592                 lentry->nh_mask = (ip & mask);
593                 /* Set the VNF Gateway flag */
594                 vnf_gateway = 1;
595                 return 0;
596         } else {
597
598                 printf("Error: Number of entries more than supported\n");
599                 return 1;
600         }
601
602 }
603
604 /*
605  * This implements route add entries for ipv6
606  */
607 int app_routeadd_config_ipv6(__attribute__((unused)) struct app_params *app,
608         uint32_t port_id, uint8_t ipv6[], uint32_t depth)
609 {
610         int i;
611
612         if (port_id >= gw_get_num_ports()) {
613                 printf("Max ports allowed is %d\n", gw_get_num_ports());
614                 return 1;
615         }
616
617         if (port_id >= nd_route_tbl_index)
618                 nd_route_tbl_index++;
619
620         printf("port id:%d depth:%d\n", port_id, depth);
621         printf("ipv6 address: ");
622         for(i = 0; i < IPV6_ADD_SIZE; i++)
623                 printf("%02x ", ipv6[i]);
624         printf("\n");
625
626         struct nd_route_table_entry *lentry = NULL;
627         int k;
628         uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
629         uint8_t depthflags = 0, depthflags1 = 0;
630
631         i = 0;
632
633         /* Check for matching entry */
634         for(i = 0 ; i< p_nd_route_data[port_id]->nd_route_ent_cnt; i++) {
635
636                 lentry = &p_nd_route_data[port_id]->nd_route_table[i];
637
638                 memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
639                 memset(netip_nd, 0, sizeof(netip_nd));
640                 memset(netip_in, 0, sizeof(netip_in));
641
642                 /* Create netmask from depth */
643                 convert_prefixlen_to_netmask_ipv6(lentry->depth, netmask_ipv6);
644
645                 for (k = 0; k < 16; k++) {
646                         if (lentry->nhipv6[k] & netmask_ipv6[k]) {
647                                 depthflags++;
648                                 netip_nd[k] = lentry->nhipv6[k];
649                         }
650
651                         if (ipv6[k] & netmask_ipv6[k]) {
652                                 depthflags1++;
653                                 netip_in[k] = ipv6[k];
654                         }
655                 }
656
657                 if ((depthflags == depthflags1)
658                                 && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) {
659                                 /* Route already exists */
660                         printf("Route already exists \n");
661                                 return 1;
662                 }
663         }
664
665         if(i < MAX_ND_ROUTE_ENTRY_SIZE) {
666
667                 lentry = &p_nd_route_data[port_id]->nd_route_table[i];
668
669                 rte_mov16(lentry->nhipv6, ipv6);
670
671                 lentry->depth = depth;
672                 lentry->port = port_id;
673                 p_nd_route_data[port_id]->nd_route_ent_cnt++;
674                 /* Set the VNF Gateway flag */
675                 vnf_gateway = 1;
676
677                 return 0;
678         } else {
679
680                 printf("Error: Number of entries more than supported\n");
681                 return 1;
682         }
683 }
684
685 /*
686  * cmd handler for handling route abj entry at runtime.
687  * the same handle takes care of both ipv4 & ipv6
688  */
689 static void
690 cmd_routeadd_parsed(
691         void *parsed_result,
692         __attribute__((unused)) struct cmdline *cl,
693          void *data)
694 {
695         struct cmd_routeadd_config_result *params = parsed_result;
696         struct app_params *app = data;
697         int status;
698
699         uint32_t port_id = params->port_id;
700         uint32_t i, ip = 0, depth = 0, mask = 0;
701         uint8_t ipv6[16];
702
703         printf("Adding route for %s \n", params->type_string);
704
705         if (params->ip.family == AF_INET) {
706                 ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
707
708                 if(strcmp(params->type_string, "net") == 0)
709                 {
710                         mask = strtoul(params->depth, NULL, 16);
711                 } else {
712                         mask = 0xffffffff;
713                 }
714
715                 printf("nhip:0x%08x mask:%x port_id:%d\n", ip, mask, port_id);
716         } else {
717                 memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16);
718                 if(strcmp(params->type_string, "net") == 0)
719                 {
720                         depth = atoi(params->depth);
721                 } else {
722                         depth = 64;
723                 }
724
725                 for (i=0; i < 16; i++)
726                         printf("%02x ", ipv6[i]);
727                 printf("\n port_id:%d depth:%d \n", port_id, depth);
728         }
729
730
731         if (params->ip.family == AF_INET)
732                 status = app_routeadd_config_ipv4(app, port_id, ip, mask);
733         else
734                 status = app_routeadd_config_ipv6(app, port_id, ipv6, depth);
735
736         if (status)
737                 printf("Command failed\n");
738         else
739                 printf("Command Success\n");
740 }
741
742 cmdline_parse_token_string_t cmd_routeadd_config_string =
743         TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, routeadd_string,
744                 "routeadd");
745
746 cmdline_parse_token_string_t cmd_routeadd_net_string =
747         TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, type_string,
748                 "net");
749
750 cmdline_parse_token_string_t cmd_routeadd_host_string =
751         TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, type_string,
752                 "host");
753
754 cmdline_parse_token_num_t cmd_routeadd_config_port_id =
755         TOKEN_NUM_INITIALIZER(struct cmd_routeadd_config_result, port_id, UINT32);
756
757 cmdline_parse_token_ipaddr_t cmd_routeadd_config_ip =
758         TOKEN_IPADDR_INITIALIZER(struct cmd_routeadd_config_result, ip);
759
760 cmdline_parse_token_string_t cmd_routeadd_config_depth_string =
761         TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, depth, NULL);
762
763 cmdline_parse_inst_t cmd_routeadd_net = {
764         .f = cmd_routeadd_parsed,
765         .data = NULL,
766         .help_str = "Add Route entry for gateway",
767         .tokens = {
768                 (void *) &cmd_routeadd_config_string,
769                 (void *) &cmd_routeadd_net_string,
770                 (void *) &cmd_routeadd_config_port_id,
771                 (void *) &cmd_routeadd_config_ip,
772                 (void *) &cmd_routeadd_config_depth_string,
773                 NULL,
774         },
775 };
776
777 cmdline_parse_inst_t cmd_routeadd_host = {
778         .f = cmd_routeadd_parsed,
779         .data = NULL,
780         .help_str = "Add Route entry for host",
781         .tokens = {
782                 (void *) &cmd_routeadd_config_string,
783                 (void *) &cmd_routeadd_host_string,
784                 (void *) &cmd_routeadd_config_port_id,
785                 (void *) &cmd_routeadd_config_ip,
786                 NULL,
787         },
788 };
789
790 /*
791  * ping
792  */
793
794 struct cmd_ping_result {
795         cmdline_fixed_string_t p_string;
796         uint32_t pipeline_id;
797         cmdline_fixed_string_t ping_string;
798 };
799
800 static void
801 cmd_ping_parsed(
802         void *parsed_result,
803         __rte_unused struct cmdline *cl,
804         void *data)
805 {
806         struct cmd_ping_result *params = parsed_result;
807         struct app_params *app = data;
808         int status;
809
810         status = app_pipeline_ping(app, params->pipeline_id);
811         if (status != 0)
812                 printf("Command failed\n");
813 }
814
815 cmdline_parse_token_string_t cmd_ping_p_string =
816         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p");
817
818 cmdline_parse_token_num_t cmd_ping_pipeline_id =
819         TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32);
820
821 cmdline_parse_token_string_t cmd_ping_ping_string =
822         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping");
823
824 cmdline_parse_inst_t cmd_ping = {
825         .f = cmd_ping_parsed,
826         .data = NULL,
827         .help_str = "Pipeline ping",
828         .tokens = {
829                 (void *) &cmd_ping_p_string,
830                 (void *) &cmd_ping_pipeline_id,
831                 (void *) &cmd_ping_ping_string,
832                 NULL,
833         },
834 };
835
836 /*
837  * stats port in
838  */
839
840 struct cmd_stats_port_in_result {
841         cmdline_fixed_string_t p_string;
842         uint32_t pipeline_id;
843         cmdline_fixed_string_t stats_string;
844         cmdline_fixed_string_t port_string;
845         cmdline_fixed_string_t in_string;
846         uint32_t port_in_id;
847
848 };
849 static void
850 cmd_stats_port_in_parsed(
851         void *parsed_result,
852         __rte_unused struct cmdline *cl,
853         void *data)
854 {
855         struct cmd_stats_port_in_result *params = parsed_result;
856         struct app_params *app = data;
857         struct rte_pipeline_port_in_stats stats;
858         int status;
859
860         status = app_pipeline_stats_port_in(app,
861                         params->pipeline_id,
862                         params->port_in_id,
863                         &stats);
864
865         if (status != 0) {
866                 printf("Command failed\n");
867                 return;
868         }
869
870         /* Display stats */
871         printf("Pipeline %" PRIu32 " - stats for input port %" PRIu32 ":\n"
872                 "\tPkts in: %" PRIu64 "\n"
873                 "\tPkts dropped by AH: %" PRIu64 "\n"
874                 "\tPkts dropped by other: %" PRIu64 "\n",
875                 params->pipeline_id,
876                 params->port_in_id,
877                 stats.stats.n_pkts_in,
878                 stats.n_pkts_dropped_by_ah,
879                 stats.stats.n_pkts_drop);
880 }
881
882 cmdline_parse_token_string_t cmd_stats_port_in_p_string =
883         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string,
884                 "p");
885
886 cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id =
887         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id,
888                 UINT32);
889
890 cmdline_parse_token_string_t cmd_stats_port_in_stats_string =
891         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string,
892                 "stats");
893
894 cmdline_parse_token_string_t cmd_stats_port_in_port_string =
895         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string,
896                 "port");
897
898 cmdline_parse_token_string_t cmd_stats_port_in_in_string =
899         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string,
900                 "in");
901
902         cmdline_parse_token_num_t cmd_stats_port_in_port_in_id =
903         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id,
904                 UINT32);
905
906 cmdline_parse_inst_t cmd_stats_port_in = {
907         .f = cmd_stats_port_in_parsed,
908         .data = NULL,
909         .help_str = "Pipeline input port stats",
910         .tokens = {
911                 (void *) &cmd_stats_port_in_p_string,
912                 (void *) &cmd_stats_port_in_pipeline_id,
913                 (void *) &cmd_stats_port_in_stats_string,
914                 (void *) &cmd_stats_port_in_port_string,
915                 (void *) &cmd_stats_port_in_in_string,
916                 (void *) &cmd_stats_port_in_port_in_id,
917                 NULL,
918         },
919 };
920
921 /*
922  * stats port out
923  */
924
925 struct cmd_stats_port_out_result {
926         cmdline_fixed_string_t p_string;
927         uint32_t pipeline_id;
928         cmdline_fixed_string_t stats_string;
929         cmdline_fixed_string_t port_string;
930         cmdline_fixed_string_t out_string;
931         uint32_t port_out_id;
932 };
933
934 static void
935 cmd_stats_port_out_parsed(
936         void *parsed_result,
937         __rte_unused struct cmdline *cl,
938         void *data)
939 {
940
941         struct cmd_stats_port_out_result *params = parsed_result;
942         struct app_params *app = data;
943         struct rte_pipeline_port_out_stats stats;
944         int status;
945
946         status = app_pipeline_stats_port_out(app,
947                         params->pipeline_id,
948                         params->port_out_id,
949                         &stats);
950
951         if (status != 0) {
952                 printf("Command failed\n");
953                 return;
954         }
955
956         /* Display stats */
957         printf("Pipeline %" PRIu32 " - stats for output port %" PRIu32 ":\n"
958                 "\tPkts in: %" PRIu64 "\n"
959                 "\tPkts dropped by AH: %" PRIu64 "\n"
960                 "\tPkts dropped by other: %" PRIu64 "\n",
961                 params->pipeline_id,
962                 params->port_out_id,
963                 stats.stats.n_pkts_in,
964                 stats.n_pkts_dropped_by_ah,
965                 stats.stats.n_pkts_drop);
966 }
967
968 cmdline_parse_token_string_t cmd_stats_port_out_p_string =
969         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string,
970         "p");
971
972 cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id =
973         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id,
974                 UINT32);
975
976 cmdline_parse_token_string_t cmd_stats_port_out_stats_string =
977         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string,
978                 "stats");
979
980 cmdline_parse_token_string_t cmd_stats_port_out_port_string =
981         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string,
982                 "port");
983
984 cmdline_parse_token_string_t cmd_stats_port_out_out_string =
985         TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string,
986                 "out");
987
988 cmdline_parse_token_num_t cmd_stats_port_out_port_out_id =
989         TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id,
990                 UINT32);
991
992 cmdline_parse_inst_t cmd_stats_port_out = {
993         .f = cmd_stats_port_out_parsed,
994         .data = NULL,
995         .help_str = "Pipeline output port stats",
996         .tokens = {
997                 (void *) &cmd_stats_port_out_p_string,
998                 (void *) &cmd_stats_port_out_pipeline_id,
999                 (void *) &cmd_stats_port_out_stats_string,
1000                 (void *) &cmd_stats_port_out_port_string,
1001                 (void *) &cmd_stats_port_out_out_string,
1002                 (void *) &cmd_stats_port_out_port_out_id,
1003                 NULL,
1004         },
1005 };
1006
1007 /*
1008  * stats table
1009  */
1010
1011 struct cmd_stats_table_result {
1012         cmdline_fixed_string_t p_string;
1013         uint32_t pipeline_id;
1014         cmdline_fixed_string_t stats_string;
1015         cmdline_fixed_string_t table_string;
1016         uint32_t table_id;
1017 };
1018
1019 static void
1020 cmd_stats_table_parsed(
1021         void *parsed_result,
1022         __rte_unused struct cmdline *cl,
1023         void *data)
1024 {
1025         struct cmd_stats_table_result *params = parsed_result;
1026         struct app_params *app = data;
1027         struct rte_pipeline_table_stats stats;
1028         int status;
1029
1030         status = app_pipeline_stats_table(app,
1031                         params->pipeline_id,
1032                         params->table_id,
1033                         &stats);
1034
1035         if (status != 0) {
1036                 printf("Command failed\n");
1037                 return;
1038         }
1039
1040         /* Display stats */
1041         printf("Pipeline %" PRIu32 " - stats for table %" PRIu32 ":\n"
1042                 "\tPkts in: %" PRIu64 "\n"
1043                 "\tPkts in with lookup miss: %" PRIu64 "\n"
1044                 "\tPkts in with lookup hit dropped by AH: %" PRIu64 "\n"
1045                 "\tPkts in with lookup hit dropped by others: %" PRIu64 "\n"
1046                 "\tPkts in with lookup miss dropped by AH: %" PRIu64 "\n"
1047                 "\tPkts in with lookup miss dropped by others: %" PRIu64 "\n",
1048                 params->pipeline_id,
1049                 params->table_id,
1050                 stats.stats.n_pkts_in,
1051                 stats.stats.n_pkts_lookup_miss,
1052                 stats.n_pkts_dropped_by_lkp_hit_ah,
1053                 stats.n_pkts_dropped_lkp_hit,
1054                 stats.n_pkts_dropped_by_lkp_miss_ah,
1055                 stats.n_pkts_dropped_lkp_miss);
1056 }
1057
1058 cmdline_parse_token_string_t cmd_stats_table_p_string =
1059         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string,
1060                 "p");
1061
1062 cmdline_parse_token_num_t cmd_stats_table_pipeline_id =
1063         TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id,
1064                 UINT32);
1065
1066 cmdline_parse_token_string_t cmd_stats_table_stats_string =
1067         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string,
1068                 "stats");
1069
1070 cmdline_parse_token_string_t cmd_stats_table_table_string =
1071         TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string,
1072                 "table");
1073
1074 cmdline_parse_token_num_t cmd_stats_table_table_id =
1075         TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32);
1076
1077 cmdline_parse_inst_t cmd_stats_table = {
1078         .f = cmd_stats_table_parsed,
1079         .data = NULL,
1080         .help_str = "Pipeline table stats",
1081         .tokens = {
1082                 (void *) &cmd_stats_table_p_string,
1083                 (void *) &cmd_stats_table_pipeline_id,
1084                 (void *) &cmd_stats_table_stats_string,
1085                 (void *) &cmd_stats_table_table_string,
1086                 (void *) &cmd_stats_table_table_id,
1087                 NULL,
1088         },
1089 };
1090
1091 /*
1092  * port in enable
1093  */
1094
1095 struct cmd_port_in_enable_result {
1096         cmdline_fixed_string_t p_string;
1097         uint32_t pipeline_id;
1098         cmdline_fixed_string_t port_string;
1099         cmdline_fixed_string_t in_string;
1100         uint32_t port_in_id;
1101         cmdline_fixed_string_t enable_string;
1102 };
1103
1104 static void
1105 cmd_port_in_enable_parsed(
1106         void *parsed_result,
1107         __rte_unused struct cmdline *cl,
1108         void *data)
1109 {
1110         struct cmd_port_in_enable_result *params = parsed_result;
1111         struct app_params *app = data;
1112         int status;
1113
1114         status = app_pipeline_port_in_enable(app,
1115                         params->pipeline_id,
1116                         params->port_in_id);
1117
1118         if (status != 0)
1119                 printf("Command failed\n");
1120 }
1121
1122 cmdline_parse_token_string_t cmd_port_in_enable_p_string =
1123         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string,
1124                 "p");
1125
1126 cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id =
1127         TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id,
1128                 UINT32);
1129
1130 cmdline_parse_token_string_t cmd_port_in_enable_port_string =
1131         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string,
1132         "port");
1133
1134 cmdline_parse_token_string_t cmd_port_in_enable_in_string =
1135         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string,
1136                 "in");
1137
1138 cmdline_parse_token_num_t cmd_port_in_enable_port_in_id =
1139         TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id,
1140                 UINT32);
1141
1142 cmdline_parse_token_string_t cmd_port_in_enable_enable_string =
1143         TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result,
1144                 enable_string, "enable");
1145
1146 cmdline_parse_inst_t cmd_port_in_enable = {
1147         .f = cmd_port_in_enable_parsed,
1148         .data = NULL,
1149         .help_str = "Pipeline input port enable",
1150         .tokens = {
1151                 (void *) &cmd_port_in_enable_p_string,
1152                 (void *) &cmd_port_in_enable_pipeline_id,
1153                 (void *) &cmd_port_in_enable_port_string,
1154                 (void *) &cmd_port_in_enable_in_string,
1155                 (void *) &cmd_port_in_enable_port_in_id,
1156                 (void *) &cmd_port_in_enable_enable_string,
1157                 NULL,
1158         },
1159 };
1160
1161 /*
1162  * port in disable
1163  */
1164
1165 struct cmd_port_in_disable_result {
1166         cmdline_fixed_string_t p_string;
1167         uint32_t pipeline_id;
1168         cmdline_fixed_string_t port_string;
1169         cmdline_fixed_string_t in_string;
1170         uint32_t port_in_id;
1171         cmdline_fixed_string_t disable_string;
1172 };
1173
1174 static void
1175 cmd_port_in_disable_parsed(
1176         void *parsed_result,
1177         __rte_unused struct cmdline *cl,
1178         void *data)
1179 {
1180         struct cmd_port_in_disable_result *params = parsed_result;
1181         struct app_params *app = data;
1182         int status;
1183
1184         status = app_pipeline_port_in_disable(app,
1185                         params->pipeline_id,
1186                         params->port_in_id);
1187
1188         if (status != 0)
1189                 printf("Command failed\n");
1190 }
1191
1192 cmdline_parse_token_string_t cmd_port_in_disable_p_string =
1193         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string,
1194                 "p");
1195
1196 cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id =
1197         TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id,
1198                 UINT32);
1199
1200 cmdline_parse_token_string_t cmd_port_in_disable_port_string =
1201         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string,
1202                 "port");
1203
1204 cmdline_parse_token_string_t cmd_port_in_disable_in_string =
1205         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string,
1206                 "in");
1207
1208 cmdline_parse_token_num_t cmd_port_in_disable_port_in_id =
1209         TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id,
1210                 UINT32);
1211
1212 cmdline_parse_token_string_t cmd_port_in_disable_disable_string =
1213         TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result,
1214                 disable_string, "disable");
1215
1216 cmdline_parse_inst_t cmd_port_in_disable = {
1217         .f = cmd_port_in_disable_parsed,
1218         .data = NULL,
1219         .help_str = "Pipeline input port disable",
1220         .tokens = {
1221                 (void *) &cmd_port_in_disable_p_string,
1222                 (void *) &cmd_port_in_disable_pipeline_id,
1223                 (void *) &cmd_port_in_disable_port_string,
1224                 (void *) &cmd_port_in_disable_in_string,
1225                 (void *) &cmd_port_in_disable_port_in_id,
1226                 (void *) &cmd_port_in_disable_disable_string,
1227                 NULL,
1228         },
1229 };
1230
1231 /*
1232  * link config
1233  */
1234
1235 static void
1236 print_link_info(struct app_link_params *p)
1237 {
1238         struct rte_eth_stats stats;
1239         struct ether_addr *mac_addr;
1240         uint32_t netmask = (~0U) << (32 - p->depth);
1241         uint32_t host = p->ip & netmask;
1242         uint32_t bcast = host | (~netmask);
1243
1244         memset(&stats, 0, sizeof(stats));
1245         rte_eth_stats_get(p->pmd_id, &stats);
1246
1247         mac_addr = (struct ether_addr *) &p->mac_addr;
1248
1249         if (strlen(p->pci_bdf))
1250                 printf("%s(%s): flags=<%s>\n",
1251                         p->name,
1252                         p->pci_bdf,
1253                         (p->state) ? "UP" : "DOWN");
1254         else
1255                 printf("%s: flags=<%s>\n",
1256                         p->name,
1257                         (p->state) ? "UP" : "DOWN");
1258
1259         if (p->ip)
1260                 printf("\tinet %" PRIu32 ".%" PRIu32
1261                         ".%" PRIu32 ".%" PRIu32
1262                         " netmask %" PRIu32 ".%" PRIu32
1263                         ".%" PRIu32 ".%" PRIu32 " "
1264                         "broadcast %" PRIu32 ".%" PRIu32
1265                         ".%" PRIu32 ".%" PRIu32 "\n",
1266                         (p->ip >> 24) & 0xFF,
1267                         (p->ip >> 16) & 0xFF,
1268                         (p->ip >> 8) & 0xFF,
1269                         p->ip & 0xFF,
1270                         (netmask >> 24) & 0xFF,
1271                         (netmask >> 16) & 0xFF,
1272                         (netmask >> 8) & 0xFF,
1273                         netmask & 0xFF,
1274                         (bcast >> 24) & 0xFF,
1275                         (bcast >> 16) & 0xFF,
1276                         (bcast >> 8) & 0xFF,
1277                         bcast & 0xFF);
1278
1279         printf("\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
1280                 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
1281                 mac_addr->addr_bytes[0],
1282                 mac_addr->addr_bytes[1],
1283                 mac_addr->addr_bytes[2],
1284                 mac_addr->addr_bytes[3],
1285                 mac_addr->addr_bytes[4],
1286                 mac_addr->addr_bytes[5]);
1287
1288         printf("\tRX packets %" PRIu64
1289                 "  bytes %" PRIu64
1290                 "\n",
1291                 stats.ipackets,
1292                 stats.ibytes);
1293
1294         printf("\tRX errors %" PRIu64
1295                 "  missed %" PRIu64
1296                 "  no-mbuf %" PRIu64
1297                 "\n",
1298                 stats.ierrors,
1299                 stats.imissed,
1300                 stats.rx_nombuf);
1301
1302         printf("\tTX packets %" PRIu64
1303                 "  bytes %" PRIu64 "\n",
1304                 stats.opackets,
1305                 stats.obytes);
1306
1307         printf("\tTX errors %" PRIu64
1308                 "\n",
1309                 stats.oerrors);
1310
1311         printf("\n");
1312 }
1313 #endif
1314 struct cmd_link_config_result {
1315         cmdline_fixed_string_t link_string;
1316         uint32_t link_id;
1317         cmdline_fixed_string_t config_string;
1318         cmdline_ipaddr_t ip;
1319         uint32_t depth;
1320 };
1321
1322 static void
1323 cmd_link_config_parsed(
1324         void *parsed_result,
1325         __attribute__((unused)) struct cmdline *cl,
1326          void *data)
1327 {
1328         struct cmd_link_config_result *params = parsed_result;
1329         struct app_params *app = data;
1330         int status;
1331
1332         uint32_t link_id = params->link_id;
1333         uint32_t ip;
1334         uint8_t ipv6[16];
1335         if (params->ip.family == AF_INET)
1336                 ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
1337         else
1338                 memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16);
1339
1340         uint32_t depth = params->depth;
1341
1342         if (params->ip.family == AF_INET)
1343                 status = app_link_config(app, link_id, ip, depth);
1344         else
1345                 status = app_link_config_ipv6(app, link_id, ipv6, depth);
1346
1347         if (status)
1348                 printf("Command failed\n");
1349         else {
1350                 struct app_link_params *p;
1351
1352                 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
1353                 if (p)
1354                 print_link_info(p);
1355         }
1356 }
1357
1358 cmdline_parse_token_string_t cmd_link_config_link_string =
1359         TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, link_string,
1360                 "link");
1361
1362 cmdline_parse_token_num_t cmd_link_config_link_id =
1363         TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, link_id, UINT32);
1364
1365 cmdline_parse_token_string_t cmd_link_config_config_string =
1366         TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, config_string,
1367                 "config");
1368
1369 cmdline_parse_token_ipaddr_t cmd_link_config_ip =
1370         TOKEN_IPADDR_INITIALIZER(struct cmd_link_config_result, ip);
1371
1372 cmdline_parse_token_num_t cmd_link_config_depth =
1373         TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, depth, UINT32);
1374
1375 cmdline_parse_inst_t cmd_link_config = {
1376         .f = cmd_link_config_parsed,
1377         .data = NULL,
1378         .help_str = "Link configuration",
1379         .tokens = {
1380                 (void *)&cmd_link_config_link_string,
1381                 (void *)&cmd_link_config_link_id,
1382                 (void *)&cmd_link_config_config_string,
1383                 (void *)&cmd_link_config_ip,
1384                 (void *)&cmd_link_config_depth,
1385                 NULL,
1386         },
1387 };
1388
1389 /*
1390  * link up
1391  */
1392
1393 struct cmd_link_up_result {
1394         cmdline_fixed_string_t link_string;
1395         uint32_t link_id;
1396         cmdline_fixed_string_t up_string;
1397 };
1398
1399 static void
1400 cmd_link_up_parsed(
1401         void *parsed_result,
1402         __attribute__((unused)) struct cmdline *cl,
1403         void *data)
1404 {
1405         struct cmd_link_up_result *params = parsed_result;
1406         struct app_params *app = data;
1407         int status;
1408
1409         status = app_link_up(app, params->link_id);
1410         if (status != 0)
1411                 printf("Command failed\n");
1412         else {
1413                 struct app_link_params *p;
1414
1415                 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id,
1416                         p);
1417                if (p)
1418                 print_link_info(p);
1419         }
1420 }
1421
1422 cmdline_parse_token_string_t cmd_link_up_link_string =
1423         TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, link_string,
1424                 "link");
1425
1426 cmdline_parse_token_num_t cmd_link_up_link_id =
1427         TOKEN_NUM_INITIALIZER(struct cmd_link_up_result, link_id, UINT32);
1428
1429 cmdline_parse_token_string_t cmd_link_up_up_string =
1430         TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up");
1431
1432 cmdline_parse_inst_t cmd_link_up = {
1433         .f = cmd_link_up_parsed,
1434         .data = NULL,
1435         .help_str = "Link UP",
1436         .tokens = {
1437                 (void *)&cmd_link_up_link_string,
1438                 (void *)&cmd_link_up_link_id,
1439                 (void *)&cmd_link_up_up_string,
1440                 NULL,
1441         },
1442 };
1443
1444 /*
1445  * link down
1446  */
1447
1448 struct cmd_link_down_result {
1449         cmdline_fixed_string_t link_string;
1450         uint32_t link_id;
1451         cmdline_fixed_string_t down_string;
1452 };
1453
1454 static void
1455 cmd_link_down_parsed(
1456         void *parsed_result,
1457         __attribute__((unused)) struct cmdline *cl,
1458         void *data)
1459 {
1460         struct cmd_link_down_result *params = parsed_result;
1461         struct app_params *app = data;
1462         int status;
1463
1464         status = app_link_down(app, params->link_id);
1465         if (status != 0)
1466                 printf("Command failed\n");
1467         else {
1468                 struct app_link_params *p;
1469
1470                 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id,
1471                         p);
1472                  if (p)
1473                         print_link_info(p);
1474         }
1475 }
1476
1477 cmdline_parse_token_string_t cmd_link_down_link_string =
1478         TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string,
1479                 "link");
1480
1481 cmdline_parse_token_num_t cmd_link_down_link_id =
1482         TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32);
1483
1484 cmdline_parse_token_string_t cmd_link_down_down_string =
1485         TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string,
1486                 "down");
1487
1488 cmdline_parse_inst_t cmd_link_down = {
1489         .f = cmd_link_down_parsed,
1490         .data = NULL,
1491         .help_str = "Link DOWN",
1492         .tokens = {
1493                 (void *) &cmd_link_down_link_string,
1494                 (void *) &cmd_link_down_link_id,
1495                 (void *) &cmd_link_down_down_string,
1496                 NULL,
1497         },
1498 };
1499
1500 /*
1501  * link ls
1502  */
1503
1504 struct cmd_link_ls_result {
1505         cmdline_fixed_string_t link_string;
1506         cmdline_fixed_string_t ls_string;
1507 };
1508
1509 static void
1510 cmd_link_ls_parsed(
1511         __attribute__((unused)) void *parsed_result,
1512         __attribute__((unused)) struct cmdline *cl,
1513          void *data)
1514 {
1515         struct app_params *app = data;
1516         uint32_t link_id;
1517
1518         for (link_id = 0; link_id < app->n_links; link_id++) {
1519                 struct app_link_params *p;
1520
1521                 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
1522                 if (p)
1523                 print_link_info(p);
1524         }
1525         print_interface_details();
1526 }
1527
1528 cmdline_parse_token_string_t cmd_link_ls_link_string =
1529         TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string,
1530                 "link");
1531
1532 cmdline_parse_token_string_t cmd_link_ls_ls_string =
1533         TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, ls_string, "ls");
1534
1535 cmdline_parse_inst_t cmd_link_ls = {
1536         .f = cmd_link_ls_parsed,
1537         .data = NULL,
1538         .help_str = "Link list",
1539         .tokens = {
1540                 (void *)&cmd_link_ls_link_string,
1541                 (void *)&cmd_link_ls_ls_string,
1542                 NULL,
1543         },
1544 };
1545
1546 /*
1547  * quit
1548  */
1549
1550 struct cmd_quit_result {
1551         cmdline_fixed_string_t quit;
1552 };
1553
1554 static void
1555 cmd_quit_parsed(
1556         __rte_unused void *parsed_result,
1557         struct cmdline *cl,
1558         __rte_unused void *data)
1559 {
1560         cmdline_quit(cl);
1561 }
1562
1563 static cmdline_parse_token_string_t cmd_quit_quit =
1564         TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
1565
1566 static cmdline_parse_inst_t cmd_quit = {
1567         .f = cmd_quit_parsed,
1568         .data = NULL,
1569         .help_str = "Quit",
1570         .tokens = {
1571                 (void *) &cmd_quit_quit,
1572                 NULL,
1573         },
1574 };
1575
1576 /*
1577  * run
1578  */
1579
1580 static void
1581 app_run_file(
1582         cmdline_parse_ctx_t *ctx,
1583         const char *file_name)
1584 {
1585         struct cmdline *file_cl;
1586         int fd;
1587
1588         fd = open(file_name, O_RDONLY);
1589         if (fd < 0) {
1590                 printf("Cannot open file \"%s\"\n", file_name);
1591                 return;
1592         }
1593
1594         file_cl = cmdline_new(ctx, "", fd, 1);
1595         cmdline_interact(file_cl);
1596         close(fd);
1597 }
1598
1599 struct cmd_run_file_result {
1600         cmdline_fixed_string_t run_string;
1601         char file_name[APP_FILE_NAME_SIZE];
1602 };
1603
1604 static void
1605 cmd_run_parsed(
1606         void *parsed_result,
1607         struct cmdline *cl,
1608         __attribute__((unused)) void *data)
1609 {
1610         struct cmd_run_file_result *params = parsed_result;
1611
1612         app_run_file(cl->ctx, params->file_name);
1613 }
1614
1615 cmdline_parse_token_string_t cmd_run_run_string =
1616         TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string,
1617                 "run");
1618
1619 cmdline_parse_token_string_t cmd_run_file_name =
1620         TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_name, NULL);
1621
1622 cmdline_parse_inst_t cmd_run = {
1623         .f = cmd_run_parsed,
1624         .data = NULL,
1625         .help_str = "Run CLI script file",
1626         .tokens = {
1627                 (void *) &cmd_run_run_string,
1628                 (void *) &cmd_run_file_name,
1629                 NULL,
1630         },
1631 };
1632
1633 static cmdline_parse_ctx_t pipeline_common_cmds[] = {
1634         (cmdline_parse_inst_t *) &cmd_quit,
1635         (cmdline_parse_inst_t *) &cmd_run,
1636         (cmdline_parse_inst_t *) &cmd_routeadd_net,
1637         (cmdline_parse_inst_t *) &cmd_routeadd_host,
1638
1639         (cmdline_parse_inst_t *) &cmd_link_config,
1640         (cmdline_parse_inst_t *) &cmd_link_up,
1641         (cmdline_parse_inst_t *) &cmd_link_down,
1642         (cmdline_parse_inst_t *) &cmd_link_ls,
1643
1644         (cmdline_parse_inst_t *) &cmd_ping,
1645         (cmdline_parse_inst_t *) &cmd_stats_port_in,
1646         (cmdline_parse_inst_t *) &cmd_stats_port_out,
1647         (cmdline_parse_inst_t *) &cmd_stats_table,
1648         (cmdline_parse_inst_t *) &cmd_port_in_enable,
1649         (cmdline_parse_inst_t *) &cmd_port_in_disable,
1650         NULL,
1651 };
1652
1653 int
1654 app_pipeline_common_cmd_push(struct app_params *app)
1655 {
1656         uint32_t n_cmds, i;
1657
1658         /* Check for available slots in the application commands array */
1659         n_cmds = RTE_DIM(pipeline_common_cmds) - 1;
1660         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1661                 return -ENOMEM;
1662
1663         /* Push pipeline commands into the application */
1664         memcpy(&app->cmds[app->n_cmds],
1665                 pipeline_common_cmds,
1666                 n_cmds * sizeof(cmdline_parse_ctx_t));
1667
1668         for (i = 0; i < n_cmds; i++)
1669                 app->cmds[app->n_cmds + i]->data = app;
1670
1671         app->n_cmds += n_cmds;
1672         app->cmds[app->n_cmds] = NULL;
1673
1674         return 0;
1675 }