examples/ip_pipeline: fix memory allocation check
[dpdk.git] / examples / ip_pipeline / cmdline.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <termios.h>
36 #include <inttypes.h>
37 #include <string.h>
38 #include <netinet/in.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41
42 #include <rte_ether.h>
43 #include <rte_byteorder.h>
44 #include <rte_ring.h>
45 #include <rte_mbuf.h>
46 #include <rte_malloc.h>
47 #include <rte_string_fns.h>
48 #include <cmdline_rdline.h>
49 #include <cmdline_parse.h>
50 #include <cmdline_parse_num.h>
51 #include <cmdline_parse_string.h>
52 #include <cmdline_parse_ipaddr.h>
53 #include <cmdline_parse_etheraddr.h>
54 #include <cmdline_socket.h>
55 #include <cmdline.h>
56
57 #include "main.h"
58
59 #define IS_RULE_PRESENT(res, rule_key, table, type)                     \
60 do {                                                                    \
61         struct app_rule *it;                                            \
62                                                                         \
63         (res) = NULL;                                                   \
64         TAILQ_FOREACH(it, &table, entries) {                            \
65                 if (memcmp(&rule_key, &it->type.key, sizeof(rule_key)) == 0) {\
66                         (res) = it;                                     \
67                         break;                                          \
68                 }                                                       \
69         }                                                               \
70 } while (0)
71
72 /* Rules */
73 static void
74 app_init_rule_tables(void);
75
76 TAILQ_HEAD(linked_list, app_rule) arp_table, routing_table, firewall_table,
77         flow_table;
78
79 uint32_t n_arp_rules;
80 uint32_t n_routing_rules;
81 uint32_t n_firewall_rules;
82 uint32_t n_flow_rules;
83
84 struct app_arp_rule {
85         struct {
86                 uint8_t out_iface;
87                 uint32_t nh_ip;
88         } key;
89
90         struct ether_addr nh_arp;
91 };
92
93 struct app_routing_rule {
94         struct {
95                 uint32_t ip;
96                 uint8_t depth;
97         } key;
98
99         uint8_t port;
100         uint32_t nh_ip;
101 };
102
103 struct app_firewall_rule {
104         struct {
105                 uint32_t src_ip;
106                 uint32_t src_ip_mask;
107                 uint32_t dst_ip;
108                 uint32_t dst_ip_mask;
109                 uint16_t src_port_from;
110                 uint16_t src_port_to;
111                 uint16_t dst_port_from;
112                 uint16_t dst_port_to;
113                 uint8_t proto;
114                 uint8_t proto_mask;
115         } key;
116
117         int32_t priority;
118         uint8_t port;
119 };
120
121 struct app_flow_rule {
122         struct {
123                 uint32_t src_ip;
124                 uint32_t dst_ip;
125                 uint16_t src_port;
126                 uint16_t dst_port;
127                 uint8_t proto;
128         } key;
129
130         uint8_t port;
131 };
132
133 struct app_rule {
134         union {
135                 struct app_arp_rule arp;
136                 struct app_routing_rule routing;
137                 struct app_firewall_rule firewall;
138                 struct app_flow_rule flow;
139         };
140
141         TAILQ_ENTRY(app_rule) entries;
142 };
143
144 /* Initialization */
145 static void
146 app_init_rule_tables(void)
147 {
148         TAILQ_INIT(&arp_table);
149         TAILQ_INIT(&routing_table);
150         TAILQ_INIT(&firewall_table);
151         TAILQ_INIT(&flow_table);
152
153         n_arp_rules = 0;
154         n_routing_rules = 0;
155         n_firewall_rules = 0;
156         n_flow_rules = 0;
157 }
158
159 /* Printing */
160 static void
161 print_arp_rule(struct app_arp_rule rule)
162 {
163         printf("(Iface = %u, Address = %u.%u.%u.%u) => "
164                 "HWaddress = %02x:%02x:%02x:%02x:%02x:%02x\n",
165                 rule.key.out_iface,
166                 (rule.key.nh_ip >> 24) & 0xFF,
167                 (rule.key.nh_ip >> 16) & 0xFF,
168                 (rule.key.nh_ip >> 8) & 0xFF,
169                 rule.key.nh_ip & 0xFF,
170
171                 rule.nh_arp.addr_bytes[0],
172                 rule.nh_arp.addr_bytes[1],
173                 rule.nh_arp.addr_bytes[2],
174                 rule.nh_arp.addr_bytes[3],
175                 rule.nh_arp.addr_bytes[4],
176                 rule.nh_arp.addr_bytes[5]);
177 }
178
179 static void
180 print_routing_rule(struct app_routing_rule rule)
181 {
182         printf("IP Prefix = %u.%u.%u.%u/%u => "
183                 "(Iface = %u, Gateway = %u.%u.%u.%u)\n",
184                 (rule.key.ip >> 24) & 0xFF,
185                 (rule.key.ip >> 16) & 0xFF,
186                 (rule.key.ip >> 8) & 0xFF,
187                 rule.key.ip & 0xFF,
188
189                 rule.key.depth,
190                 rule.port,
191
192                 (rule.nh_ip >> 24) & 0xFF,
193                 (rule.nh_ip >> 16) & 0xFF,
194                 (rule.nh_ip >> 8) & 0xFF,
195                 rule.nh_ip & 0xFF);
196 }
197
198 #ifdef RTE_LIBRTE_ACL
199
200 static void
201 print_firewall_rule(struct app_firewall_rule rule)
202 {
203         printf("Priority %d: (IP Src = %u.%u.%u.%u/%u, "
204                 "IP Dst = %u.%u.%u.%u/%u, "
205                 "Port Src = %u-%u, Port Dst = %u-%u, Proto = %u (%u)) => "
206                 "Port = %u\n",
207                 rule.priority,
208
209                 (rule.key.src_ip >> 24) & 0xFF,
210                 (rule.key.src_ip >> 16) & 0xFF,
211                 (rule.key.src_ip >> 8) & 0xFF,
212                 rule.key.src_ip & 0xFF,
213                 rule.key.src_ip_mask,
214
215                 (rule.key.dst_ip >> 24) & 0xFF,
216                 (rule.key.dst_ip >> 16) & 0xFF,
217                 (rule.key.dst_ip >> 8) & 0xFF,
218                 rule.key.dst_ip & 0xFF,
219                 rule.key.dst_ip_mask,
220
221                 rule.key.src_port_from,
222                 rule.key.src_port_to,
223                 rule.key.dst_port_from,
224                 rule.key.dst_port_to,
225                 rule.key.proto,
226                 rule.key.proto_mask,
227                 rule.port);
228 }
229
230 #endif
231
232 static void
233 print_flow_rule(struct app_flow_rule rule)
234 {
235         printf("(IP Src = %u.%u.%u.%u, IP Dst = %u.%u.%u.%u, Port Src = %u, "
236                 "Port Dst = %u, Proto = %u) => Port = %u\n",
237                 (rule.key.src_ip >> 24) & 0xFF,
238                 (rule.key.src_ip >> 16) & 0xFF,
239                 (rule.key.src_ip >> 8) & 0xFF,
240                 rule.key.src_ip & 0xFF,
241
242                 (rule.key.dst_ip >> 24) & 0xFF,
243                 (rule.key.dst_ip >> 16) & 0xFF,
244                 (rule.key.dst_ip >> 8) & 0xFF,
245                 rule.key.dst_ip  & 0xFF,
246
247                 rule.key.src_port,
248                 rule.key.dst_port,
249                 (uint32_t) rule.key.proto,
250                 rule.port);
251 }
252
253 /* Commands */
254
255 /* *** Run file (script) *** */
256 struct cmd_run_file_result {
257         cmdline_fixed_string_t run_string;
258         char file_path[100];
259 };
260
261 static void
262 cmd_run_file_parsed(
263         void *parsed_result,
264         struct cmdline *cl,
265         __attribute__((unused)) void *data)
266 {
267         struct cmd_run_file_result *params = parsed_result;
268         struct cmdline *file_cl;
269         int fd;
270
271         /* Check params */
272         if (!params->file_path) {
273                 printf("Illegal value for file path (%s)\n", params->file_path);
274                 return;
275         }
276
277         fd = open(params->file_path, O_RDONLY, 0);
278         if (fd < 0) {
279                 printf("Illegal value for file path (%s)\n", params->file_path);
280                 return;
281         }
282
283         file_cl = cmdline_new(cl->ctx, "", fd, 1);
284         cmdline_interact(file_cl);
285         close(fd);
286 }
287
288 cmdline_parse_token_string_t cmd_run_file_run_string =
289         TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
290
291 cmdline_parse_token_string_t cmd_run_file_file_path =
292         TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_path, NULL);
293
294 cmdline_parse_inst_t cmd_run_file = {
295         .f = cmd_run_file_parsed,
296         .data = NULL,
297         .help_str = "Run commands from file",
298         .tokens = {
299                 (void *)&cmd_run_file_run_string,
300                 (void *)&cmd_run_file_file_path,
301                 NULL,
302         },
303 };
304
305 /* *** Link - Enable *** */
306 struct cmd_link_enable_result {
307         cmdline_fixed_string_t link_string;
308         uint8_t port;
309         cmdline_fixed_string_t up_string;
310 };
311
312 static void
313 cmd_link_enable_parsed(
314         void *parsed_result,
315         __attribute__((unused)) struct cmdline *cl,
316         __attribute__((unused)) void *data)
317 {
318         struct cmd_link_enable_result *params = parsed_result;
319         void *msg;
320         struct app_msg_req *req;
321         struct app_msg_resp *resp;
322         int status;
323
324         uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
325
326         if (core_id == RTE_MAX_LCORE) {
327                 printf("RX core not preformed by any CPU core\n");
328                 return;
329         }
330
331         struct rte_ring *ring_req = app_get_ring_req(core_id);
332         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
333
334         /* Check params */
335         if (params->port >= app.n_ports) {
336                 printf("Illegal value for port parameter (%u)\n", params->port);
337                 return;
338         }
339
340         printf("Enabling port %d\n", params->port);
341
342         /* Allocate message buffer */
343         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
344         if (msg == NULL)
345                 rte_panic("Unable to allocate new message\n");
346
347         /* Fill request message */
348         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
349         req->type = APP_MSG_REQ_RX_PORT_ENABLE;
350         req->rx_up.port = params->port;
351
352         /* Send request */
353         do {
354                 status = rte_ring_sp_enqueue(ring_req, msg);
355         } while (status == -ENOBUFS);
356
357         /* Wait for response */
358         do {
359                 status = rte_ring_sc_dequeue(ring_resp, &msg);
360         } while (status != 0);
361         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
362         /* Check response */
363         if (resp->result != 0)
364                 printf("Request LINK_UP failed (%u)\n", resp->result);
365
366         /* Free message buffer */
367         rte_ctrlmbuf_free(msg);
368 }
369
370 cmdline_parse_token_string_t cmd_link_enable_link_string =
371         TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, link_string,
372         "link");
373
374 cmdline_parse_token_num_t cmd_link_enable_port =
375         TOKEN_NUM_INITIALIZER(struct cmd_link_enable_result, port, UINT8);
376
377 cmdline_parse_token_string_t cmd_link_enable_up_string =
378         TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, up_string,
379         "up");
380
381 cmdline_parse_inst_t cmd_link_enable = {
382         .f = cmd_link_enable_parsed,
383         .data = NULL,
384         .help_str = "Link down",
385         .tokens = {
386                 (void *)&cmd_link_enable_link_string,
387                 (void *)&cmd_link_enable_port,
388                 (void *)&cmd_link_enable_up_string,
389                 NULL,
390         },
391 };
392
393 /* *** Link - Disable *** */
394 struct cmd_link_disable_result {
395         cmdline_fixed_string_t link_string;
396         uint8_t port;
397         cmdline_fixed_string_t down_string;
398 };
399
400 static void
401 cmd_link_disable_parsed(
402         void *parsed_result,
403         __attribute__((unused)) struct cmdline *cl,
404         __attribute__((unused)) void *data)
405 {
406         struct cmd_link_disable_result *params = parsed_result;
407         struct app_msg_req *req;
408         struct app_msg_resp *resp;
409         void *msg;
410         int status;
411
412         uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
413
414         if (core_id == RTE_MAX_LCORE) {
415                 printf("RX not performed by any CPU core\n");
416                 return;
417         }
418
419         struct rte_ring *ring_req = app_get_ring_req(core_id);
420         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
421
422         /* Check params */
423         if (params->port >= app.n_ports) {
424                 printf("Illegal value for port parameter (%u)\n", params->port);
425                 return;
426         }
427
428         printf("Disabling port %d\n", params->port);
429
430         /* Allocate message buffer */
431         msg = rte_ctrlmbuf_alloc(app.msg_pool);
432         if (msg == NULL)
433                 rte_panic("Unable to allocate new message\n");
434
435         /* Fill request message */
436         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
437         req->type = APP_MSG_REQ_RX_PORT_DISABLE;
438         req->rx_down.port = params->port;
439
440         /* Send request */
441         do {
442                 status = rte_ring_sp_enqueue(ring_req, msg);
443         } while (status == -ENOBUFS);
444
445         /* Wait for response */
446         do {
447                 status = rte_ring_sc_dequeue(ring_resp, &msg);
448         } while (status != 0);
449         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
450
451         /* Check response */
452         if (resp->result != 0)
453                 printf("Request LINK_DOWN failed (%u)\n", resp->result);
454
455         /* Free message buffer */
456         rte_ctrlmbuf_free((struct rte_mbuf *)msg);
457 }
458
459 cmdline_parse_token_string_t cmd_link_disable_link_string =
460         TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, link_string,
461         "link");
462
463 cmdline_parse_token_num_t cmd_link_disable_port =
464         TOKEN_NUM_INITIALIZER(struct cmd_link_disable_result, port, UINT8);
465
466 cmdline_parse_token_string_t cmd_link_disable_down_string =
467         TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, down_string,
468         "down");
469
470 cmdline_parse_inst_t cmd_link_disable = {
471         .f = cmd_link_disable_parsed,
472         .data = NULL,
473         .help_str = "Link up",
474         .tokens = {
475                 (void *)&cmd_link_disable_link_string,
476                 (void *)&cmd_link_disable_port,
477                 (void *)&cmd_link_disable_down_string,
478                 NULL,
479         },
480 };
481
482
483 /* *** ARP - Add *** */
484 struct cmd_arp_add_result {
485         cmdline_fixed_string_t arp_string;
486         cmdline_fixed_string_t add_string;
487         uint8_t out_iface;
488         cmdline_ipaddr_t nh_ip;
489         struct ether_addr nh_arp;
490
491 };
492
493 static void
494 cmd_arp_add_parsed(
495         void *parsed_result,
496         __attribute__((unused)) struct cmdline *cl,
497         __attribute__((unused)) void *data)
498 {
499         struct cmd_arp_add_result *params = parsed_result;
500         struct app_rule rule, *old_rule;
501         struct app_msg_req *req;
502         struct app_msg_resp *resp;
503         void *msg;
504         int status;
505
506         uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
507
508         if (core_id == RTE_MAX_LCORE) {
509                 printf("ARP not performed by any CPU core\n");
510                 return;
511         }
512
513         struct rte_ring *ring_req = app_get_ring_req(core_id);
514         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
515
516         /* Check params */
517         if (params->out_iface >= app.n_ports) {
518                 printf("Illegal value for output interface parameter (%u)\n",
519                         params->out_iface);
520                 return;
521         }
522
523         /* Create rule */
524         memset(&rule, 0, sizeof(rule));
525         rule.arp.key.out_iface = params->out_iface;
526         rule.arp.key.nh_ip =
527                 rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
528         rule.arp.nh_arp = params->nh_arp;
529
530         /* Check rule existence */
531         IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
532         if ((old_rule == NULL) && (n_arp_rules == app.max_arp_rules)) {
533                 printf("ARP table is full.\n");
534                 return;
535         }
536
537         printf("Adding ARP entry: ");
538         print_arp_rule(rule.arp);
539
540         /* Allocate message buffer */
541         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
542         if (msg == NULL)
543                 rte_panic("Unable to allocate new message\n");
544
545         /* Fill request message */
546         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
547         req->type = APP_MSG_REQ_ARP_ADD;
548         req->arp_add.out_iface = rule.arp.key.out_iface;
549         req->arp_add.nh_ip = rule.arp.key.nh_ip;
550         req->arp_add.nh_arp = rule.arp.nh_arp;
551
552         /* Send request */
553         do {
554                 status = rte_ring_sp_enqueue(ring_req, msg);
555         } while (status == -ENOBUFS);
556
557         /* Wait for response */
558         do {
559                 status = rte_ring_sc_dequeue(ring_resp, &msg);
560         } while (status != 0);
561         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
562
563         /* Check response */
564         if (resp->result != 0)
565                 printf("Request ARP_ADD failed (%u)\n", resp->result);
566         else {
567                 if (old_rule == NULL) {
568                         struct app_rule *new_rule = (struct app_rule *)
569                                 rte_zmalloc_socket("CLI",
570                                 sizeof(struct app_rule),
571                                 RTE_CACHE_LINE_SIZE,
572                                 rte_socket_id());
573
574                         if (new_rule == NULL)
575                                 rte_panic("Unable to allocate new rule\n");
576
577                         memcpy(new_rule, &rule, sizeof(rule));
578                         TAILQ_INSERT_TAIL(&arp_table, new_rule, entries);
579                         n_arp_rules++;
580                 } else
581                         old_rule->arp.nh_arp = rule.arp.nh_arp;
582         }
583
584         /* Free message buffer */
585         rte_ctrlmbuf_free((struct rte_mbuf *) msg);
586 }
587
588 cmdline_parse_token_string_t cmd_arp_add_arp_string =
589         TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp");
590
591 cmdline_parse_token_string_t cmd_arp_add_add_string =
592         TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add");
593
594 cmdline_parse_token_num_t cmd_arp_add_out_iface =
595         TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, out_iface, UINT8);
596
597 cmdline_parse_token_ipaddr_t cmd_arp_add_nh_ip =
598         TOKEN_IPADDR_INITIALIZER(struct cmd_arp_add_result, nh_ip);
599
600 cmdline_parse_token_etheraddr_t cmd_arp_add_nh_arp =
601         TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, nh_arp);
602
603 cmdline_parse_inst_t cmd_arp_add = {
604         .f = cmd_arp_add_parsed,
605         .data = NULL,
606         .help_str = "ARP add",
607         .tokens = {
608                 (void *)&cmd_arp_add_arp_string,
609                 (void *)&cmd_arp_add_add_string,
610                 (void *)&cmd_arp_add_out_iface,
611                 (void *)&cmd_arp_add_nh_ip,
612                 (void *)&cmd_arp_add_nh_arp,
613                 NULL,
614         },
615         };
616
617 /* *** ARP - Del *** */
618 struct cmd_arp_del_result {
619         cmdline_fixed_string_t arp_string;
620         cmdline_fixed_string_t del_string;
621         uint8_t out_iface;
622         cmdline_ipaddr_t nh_ip;
623 };
624
625 static void
626 cmd_arp_del_parsed(
627         void *parsed_result,
628         __attribute__((unused)) struct cmdline *cl,
629         __attribute__((unused)) void *data)
630 {
631         struct cmd_arp_del_result *params = parsed_result;
632         struct app_rule rule, *old_rule;
633         struct app_msg_req *req;
634         struct app_msg_resp *resp;
635         void *msg;
636         int status;
637
638         uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
639
640         if (core_id == RTE_MAX_LCORE) {
641                 printf("ARP not performed by any CPU core\n");
642                 return;
643         }
644
645         struct rte_ring *ring_req = app_get_ring_req(core_id);
646         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
647
648         /* Check params */
649         if (params->out_iface > app.n_ports) {
650                 printf("Illegal value for output interface parameter (%u)\n",
651                         params->out_iface);
652                 return;
653         }
654
655         /* Create rule */
656         memset(&rule, 0, sizeof(rule));
657         rule.arp.key.out_iface = params->out_iface;
658         rule.arp.key.nh_ip =
659                 rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
660
661         /* Check rule existence */
662         IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
663         if (old_rule == NULL)
664                 return;
665
666         printf("Deleting ARP entry: ");
667         print_arp_rule(old_rule->arp);
668
669         /* Allocate message buffer */
670         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
671         if (msg == NULL)
672                 rte_panic("Unable to allocate new message\n");
673
674         /* Fill request message */
675         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
676         req->type = APP_MSG_REQ_ARP_DEL;
677         req->arp_del.out_iface = rule.arp.key.out_iface;
678         req->arp_del.nh_ip = rule.arp.key.nh_ip;
679
680         /* Send request */
681         do {
682                 status = rte_ring_sp_enqueue(ring_req, msg);
683         } while (status == -ENOBUFS);
684
685         /* Wait for response */
686         do {
687                 status = rte_ring_sc_dequeue(ring_resp, &msg);
688         } while (status != 0);
689         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
690
691         /* Check response */
692         if (resp->result != 0)
693                 printf("Request ARP_DEL failed (%u)\n", resp->result);
694         else {
695                 TAILQ_REMOVE(&arp_table, old_rule, entries);
696                 n_arp_rules--;
697                 rte_free(old_rule);
698         }
699
700         /* Free message buffer */
701         rte_ctrlmbuf_free((struct rte_mbuf *) msg);
702 }
703
704 cmdline_parse_token_string_t cmd_arp_del_arp_string =
705         TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp");
706
707 cmdline_parse_token_string_t cmd_arp_del_del_string =
708         TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del");
709
710 cmdline_parse_token_num_t cmd_arp_del_out_iface =
711         TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, out_iface, UINT8);
712
713 cmdline_parse_token_ipaddr_t cmd_arp_del_nh_ip =
714         TOKEN_IPADDR_INITIALIZER(struct cmd_arp_del_result, nh_ip);
715
716 cmdline_parse_inst_t cmd_arp_del = {
717         .f = cmd_arp_del_parsed,
718         .data = NULL,
719         .help_str = "ARP delete",
720         .tokens = {
721                 (void *)&cmd_arp_del_arp_string,
722                 (void *)&cmd_arp_del_del_string,
723                 (void *)&cmd_arp_del_out_iface,
724                 (void *)&cmd_arp_del_nh_ip,
725                 NULL,
726         },
727 };
728
729 /* *** ARP - Print *** */
730 struct cmd_arp_print_result {
731         cmdline_fixed_string_t arp_string;
732         cmdline_fixed_string_t print_string;
733 };
734
735 static void
736 cmd_arp_print_parsed(
737         __attribute__((unused)) void *parsed_result,
738         __attribute__((unused)) struct cmdline *cl,
739         __attribute__((unused)) void *data)
740 {
741         struct app_rule *it;
742
743         TAILQ_FOREACH(it, &arp_table, entries) {
744                 print_arp_rule(it->arp);
745         }
746 }
747
748 cmdline_parse_token_string_t cmd_arp_print_arp_string =
749         TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, arp_string,
750         "arp");
751
752 cmdline_parse_token_string_t cmd_arp_print_print_string =
753         TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, print_string,
754         "ls");
755
756 cmdline_parse_inst_t cmd_arp_print = {
757         .f = cmd_arp_print_parsed,
758         .data = NULL,
759         .help_str = "ARP list",
760         .tokens = {
761                 (void *)&cmd_arp_print_arp_string,
762                 (void *)&cmd_arp_print_print_string,
763                 NULL,
764         },
765 };
766
767 /* *** Routing - Add *** */
768 struct cmd_route_add_result {
769         cmdline_fixed_string_t route_string;
770         cmdline_fixed_string_t add_string;
771         cmdline_ipaddr_t ip;
772         uint8_t depth;
773         uint8_t port;
774         cmdline_ipaddr_t nh_ip;
775 };
776
777 static void
778 cmd_route_add_parsed(
779         void *parsed_result,
780         __attribute__((unused)) struct cmdline *cl,
781         __attribute__((unused)) void *data)
782 {
783         struct cmd_route_add_result *params = parsed_result;
784         struct app_rule rule, *old_rule;
785         struct app_msg_req *req;
786         struct app_msg_resp *resp;
787         void *msg;
788         int status;
789
790         uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
791
792         if (core_id == RTE_MAX_LCORE) {
793                 printf("Routing not performed by any CPU core\n");
794                 return;
795         }
796
797         struct rte_ring *ring_req = app_get_ring_req(core_id);
798         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
799
800         /* Check params */
801         if ((params->depth == 0) || (params->depth > 32)) {
802                 printf("Illegal value for depth parameter (%u)\n",
803                         params->depth);
804                 return;
805         }
806
807         if (params->port >= app.n_ports) {
808                 printf("Illegal value for port parameter (%u)\n", params->port);
809                 return;
810         }
811
812         /* Create rule */
813         memset(&rule, 0, sizeof(rule));
814         rule.routing.key.ip = rte_bswap32((uint32_t)
815                 params->ip.addr.ipv4.s_addr);
816         rule.routing.key.depth = params->depth;
817         rule.routing.port = params->port;
818         rule.routing.nh_ip =
819                 rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
820
821         /* Check rule existence */
822         IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
823         if ((old_rule == NULL) && (n_routing_rules == app.max_routing_rules)) {
824                 printf("Routing table is full.\n");
825                 return;
826         }
827
828         printf("Adding route: ");
829         print_routing_rule(rule.routing);
830
831         /* Allocate message buffer */
832         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
833         if (msg == NULL)
834                 rte_panic("Unable to allocate new message\n");
835
836         /* Fill request message */
837         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
838         req->type = APP_MSG_REQ_RT_ADD;
839         req->routing_add.ip = rule.routing.key.ip;
840         req->routing_add.depth = rule.routing.key.depth;
841         req->routing_add.port = rule.routing.port;
842         req->routing_add.nh_ip = rule.routing.nh_ip;
843
844         /* Send request */
845         do {
846                 status = rte_ring_sp_enqueue(ring_req, msg);
847         } while (status == -ENOBUFS);
848
849         /* Wait for response */
850         do {
851                 status = rte_ring_sc_dequeue(ring_resp, &msg);
852         } while (status != 0);
853         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
854
855         /* Check response */
856         if (resp->result != 0)
857                 printf("Request ROUTE_ADD failed (%u)\n", resp->result);
858         else {
859                 if (old_rule == NULL) {
860                         struct app_rule *new_rule = (struct app_rule *)
861                                 rte_zmalloc_socket("CLI",
862                                 sizeof(struct app_rule),
863                                 RTE_CACHE_LINE_SIZE,
864                                 rte_socket_id());
865
866                         if (new_rule == NULL)
867                                 rte_panic("Unable to allocate new rule\n");
868
869                         memcpy(new_rule, &rule, sizeof(rule));
870                         TAILQ_INSERT_TAIL(&routing_table, new_rule, entries);
871                         n_routing_rules++;
872                 } else {
873                         old_rule->routing.port = rule.routing.port;
874                         old_rule->routing.nh_ip = rule.routing.nh_ip;
875                 }
876         }
877
878         /* Free message buffer */
879         rte_ctrlmbuf_free((struct rte_mbuf *) msg);
880 }
881
882 cmdline_parse_token_string_t cmd_route_add_route_string =
883         TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string,
884         "route");
885
886 cmdline_parse_token_string_t cmd_route_add_add_string =
887         TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string,
888         "add");
889
890 cmdline_parse_token_ipaddr_t cmd_route_add_ip =
891         TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, ip);
892
893 cmdline_parse_token_num_t cmd_route_add_depth =
894         TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT8);
895
896 cmdline_parse_token_num_t cmd_route_add_port =
897         TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT8);
898
899 cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip =
900         TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, nh_ip);
901
902 cmdline_parse_inst_t cmd_route_add = {
903         .f = cmd_route_add_parsed,
904         .data = NULL,
905         .help_str = "Route add",
906         .tokens = {
907                 (void *)&cmd_route_add_route_string,
908                 (void *)&cmd_route_add_add_string,
909                 (void *)&cmd_route_add_ip,
910                 (void *)&cmd_route_add_depth,
911                 (void *)&cmd_route_add_port,
912                 (void *)&cmd_route_add_nh_ip,
913                 NULL,
914         },
915 };
916
917 /* *** Routing - Del *** */
918 struct cmd_route_del_result {
919         cmdline_fixed_string_t route_string;
920         cmdline_fixed_string_t del_string;
921         cmdline_ipaddr_t ip;
922         uint8_t depth;
923 };
924
925 static void
926 cmd_route_del_parsed(
927         void *parsed_result,
928         __attribute__((unused)) struct cmdline *cl,
929         __attribute__((unused)) void *data)
930 {
931         struct cmd_route_del_result *params = parsed_result;
932         struct app_rule rule, *old_rule;
933         struct app_msg_req *req;
934         struct app_msg_resp *resp;
935         void *msg;
936         int status;
937
938         uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
939
940         if (core_id == RTE_MAX_LCORE) {
941                 printf("Routing not performed by any CPU core\n");
942                 return;
943         }
944
945         struct rte_ring *ring_req = app_get_ring_req(core_id);
946         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
947
948         /* Check params */
949         if ((params->depth == 0) || (params->depth > 32)) {
950                 printf("Illegal value for depth parameter (%u)\n",
951                         params->depth);
952                 return;
953         }
954
955         /* Create rule */
956         memset(&rule, 0, sizeof(rule));
957         rule.routing.key.ip = rte_bswap32((uint32_t)
958                 params->ip.addr.ipv4.s_addr);
959         rule.routing.key.depth = params->depth;
960
961         /* Check rule existence */
962         IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
963         if (old_rule == NULL)
964                 return;
965
966         printf("Deleting route: ");
967         print_routing_rule(old_rule->routing);
968
969         /* Allocate message buffer */
970         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
971         if (msg == NULL)
972                 rte_panic("Unable to allocate new message\n");
973
974         /* Fill request message */
975         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
976         req->type = APP_MSG_REQ_RT_DEL;
977         req->routing_del.ip = rule.routing.key.ip;
978         req->routing_del.depth = rule.routing.key.depth;
979
980         /* Send request */
981         do {
982                 status = rte_ring_sp_enqueue(ring_req, msg);
983         } while (status == -ENOBUFS);
984
985         /* Wait for response */
986         do {
987                 status = rte_ring_sc_dequeue(ring_resp, &msg);
988         } while (status != 0);
989         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
990
991         /* Check response */
992         if (resp->result != 0)
993                 printf("Request ROUTE_DEL failed %u)\n", resp->result);
994         else {
995                 TAILQ_REMOVE(&routing_table, old_rule, entries);
996                 rte_free(old_rule);
997                 n_routing_rules--;
998         }
999
1000         /* Free message buffer */
1001         rte_ctrlmbuf_free((struct rte_mbuf *)msg);
1002 }
1003
1004 cmdline_parse_token_string_t cmd_route_del_route_string =
1005         TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string,
1006         "route");
1007
1008 cmdline_parse_token_string_t cmd_route_del_del_string =
1009         TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string,
1010         "del");
1011
1012 cmdline_parse_token_ipaddr_t cmd_route_del_ip =
1013         TOKEN_IPADDR_INITIALIZER(struct cmd_route_del_result, ip);
1014
1015 cmdline_parse_token_num_t cmd_route_del_depth =
1016         TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT8);
1017
1018 cmdline_parse_inst_t cmd_route_del = {
1019         .f = cmd_route_del_parsed,
1020         .data = NULL,
1021         .help_str = "Route delete",
1022         .tokens = {
1023                 (void *)&cmd_route_del_route_string,
1024                 (void *)&cmd_route_del_del_string,
1025                 (void *)&cmd_route_del_ip,
1026                 (void *)&cmd_route_del_depth,
1027                 NULL,
1028         },
1029 };
1030
1031 /* *** Routing - Print *** */
1032 struct cmd_routing_print_result {
1033         cmdline_fixed_string_t routing_string;
1034         cmdline_fixed_string_t print_string;
1035 };
1036
1037 static void
1038 cmd_routing_print_parsed(
1039         __attribute__((unused)) void *parsed_result,
1040         __attribute__((unused)) struct cmdline *cl,
1041         __attribute__((unused)) void *data)
1042 {
1043         struct app_rule *it;
1044
1045         TAILQ_FOREACH(it, &routing_table, entries) {
1046                 print_routing_rule(it->routing);
1047         }
1048 }
1049
1050 cmdline_parse_token_string_t cmd_routing_print_routing_string =
1051         TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result,
1052         routing_string, "route");
1053
1054 cmdline_parse_token_string_t cmd_routing_print_print_string =
1055         TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result, print_string,
1056         "ls");
1057
1058 cmdline_parse_inst_t cmd_routing_print = {
1059         .f = cmd_routing_print_parsed,
1060         .data = NULL,
1061         .help_str = "Route list",
1062         .tokens = {
1063                 (void *)&cmd_routing_print_routing_string,
1064                 (void *)&cmd_routing_print_print_string,
1065                 NULL,
1066         },
1067 };
1068
1069 #ifdef RTE_LIBRTE_ACL
1070
1071 /* *** Firewall - Add *** */
1072 struct cmd_firewall_add_result {
1073         cmdline_fixed_string_t firewall_string;
1074         cmdline_fixed_string_t add_string;
1075         int32_t priority;
1076         cmdline_ipaddr_t src_ip;
1077         uint32_t src_ip_mask;
1078         cmdline_ipaddr_t dst_ip;
1079         uint32_t dst_ip_mask;
1080         uint16_t src_port_from;
1081         uint16_t src_port_to;
1082         uint16_t dst_port_from;
1083         uint16_t dst_port_to;
1084         uint8_t proto;
1085         uint8_t proto_mask;
1086         uint8_t port;
1087 };
1088
1089 static void
1090 cmd_firewall_add_parsed(
1091         void *parsed_result,
1092         __attribute__((unused)) struct cmdline *cl,
1093         __attribute__((unused)) void *data)
1094 {
1095         struct cmd_firewall_add_result *params = parsed_result;
1096         struct app_rule rule, *old_rule, *new_rule = NULL;
1097         struct rte_mbuf *msg;
1098         struct app_msg_req *req;
1099         struct app_msg_resp *resp;
1100         int status;
1101
1102         uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
1103
1104         if (core_id == RTE_MAX_LCORE) {
1105                 printf("Firewall not performed by any CPU core\n");
1106                 return;
1107         }
1108
1109         struct rte_ring *ring_req = app_get_ring_req(core_id);
1110         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
1111
1112         /* Check params */
1113         if (params->port >= app.n_ports) {
1114                 printf("Illegal value for port parameter (%u)\n", params->port);
1115                 return;
1116         }
1117
1118         /* Create rule */
1119         memset(&rule, 0, sizeof(rule));
1120         rule.firewall.priority = params->priority;
1121         rule.firewall.key.src_ip =
1122                 rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
1123         rule.firewall.key.src_ip_mask = params->src_ip_mask;
1124         rule.firewall.key.dst_ip =
1125                 rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
1126         rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
1127         rule.firewall.key.src_port_from = params->src_port_from;
1128         rule.firewall.key.src_port_to = params->src_port_to;
1129         rule.firewall.key.dst_port_from = params->dst_port_from;
1130         rule.firewall.key.dst_port_to = params->dst_port_to;
1131         rule.firewall.key.proto = params->proto;
1132         rule.firewall.key.proto_mask = params->proto_mask;
1133         rule.firewall.port = params->port;
1134
1135         /* Check rule existence */
1136         IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
1137         if ((old_rule == NULL) &&
1138                 (n_firewall_rules == app.max_firewall_rules)) {
1139                 printf("Firewall table is full.\n");
1140                 return;
1141         }
1142
1143         printf("Adding firewall rule: ");
1144         print_firewall_rule(rule.firewall);
1145
1146         /* Allocate message buffer */
1147         msg = rte_ctrlmbuf_alloc(app.msg_pool);
1148         if (msg == NULL)
1149                 rte_panic("Unable to allocate new message\n");
1150
1151         /* if we need a new rule structure, allocate it before we go further */
1152         if (old_rule == NULL) {
1153                 new_rule = rte_zmalloc_socket("CLI", sizeof(struct app_rule),
1154                                 RTE_CACHE_LINE_SIZE, rte_socket_id());
1155                 if (new_rule == NULL) {
1156                         printf("Cannot allocate memory for new rule\n");
1157                         rte_ctrlmbuf_free(msg);
1158                         return;
1159                 }
1160         }
1161
1162
1163         /* Fill request message */
1164         req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
1165         req->type = APP_MSG_REQ_FW_ADD;
1166         req->firewall_add.add_params.priority = rule.firewall.priority;
1167         req->firewall_add.add_params.field_value[1].value.u32 =
1168                 rule.firewall.key.src_ip;
1169         req->firewall_add.add_params.field_value[1].mask_range.u32 =
1170                 rule.firewall.key.src_ip_mask;
1171         req->firewall_add.add_params.field_value[2].value.u32 =
1172                 rule.firewall.key.dst_ip;
1173         req->firewall_add.add_params.field_value[2].mask_range.u32 =
1174                 rule.firewall.key.dst_ip_mask;
1175         req->firewall_add.add_params.field_value[3].value.u16 =
1176                 rule.firewall.key.src_port_from;
1177         req->firewall_add.add_params.field_value[3].mask_range.u16 =
1178                 rule.firewall.key.src_port_to;
1179         req->firewall_add.add_params.field_value[4].value.u16 =
1180                 rule.firewall.key.dst_port_from;
1181         req->firewall_add.add_params.field_value[4].mask_range.u16 =
1182                 rule.firewall.key.dst_port_to;
1183         req->firewall_add.add_params.field_value[0].value.u8 =
1184                 rule.firewall.key.proto;
1185         req->firewall_add.add_params.field_value[0].mask_range.u8 =
1186                 rule.firewall.key.proto_mask;
1187         req->firewall_add.port = rule.firewall.port;
1188
1189         /* Send request */
1190         do {
1191                 status = rte_ring_sp_enqueue(ring_req, (void *) msg);
1192         } while (status == -ENOBUFS);
1193
1194         /* Wait for response */
1195         do {
1196                 status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
1197         } while (status != 0);
1198         resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
1199
1200         /* Check response */
1201         if (resp->result != 0)
1202                 printf("Request FIREWALL_ADD failed (%u)\n", resp->result);
1203         else {
1204                 if (old_rule == NULL) {
1205                         memcpy(new_rule, &rule, sizeof(rule));
1206                         TAILQ_INSERT_TAIL(&firewall_table, new_rule, entries);
1207                         n_firewall_rules++;
1208                 } else {
1209                         old_rule->firewall.priority = rule.firewall.priority;
1210                         old_rule->firewall.port = rule.firewall.port;
1211                 }
1212         }
1213
1214         /* Free message buffer */
1215         rte_ctrlmbuf_free(msg);
1216 }
1217
1218 cmdline_parse_token_string_t cmd_firewall_add_firewall_string =
1219         TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result,
1220         firewall_string, "firewall");
1221
1222 cmdline_parse_token_string_t cmd_firewall_add_add_string =
1223         TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result, add_string,
1224         "add");
1225
1226 cmdline_parse_token_num_t cmd_firewall_add_priority =
1227         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, priority, INT32);
1228
1229 cmdline_parse_token_ipaddr_t cmd_firewall_add_src_ip =
1230         TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, src_ip);
1231 cmdline_parse_token_num_t cmd_firewall_add_src_ip_mask =
1232         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_ip_mask,
1233         UINT32);
1234
1235 cmdline_parse_token_ipaddr_t cmd_firewall_add_dst_ip =
1236         TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, dst_ip);
1237 cmdline_parse_token_num_t cmd_firewall_add_dst_ip_mask =
1238         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_ip_mask,
1239         UINT32);
1240
1241 cmdline_parse_token_num_t cmd_firewall_add_src_port_from =
1242         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_from,
1243         UINT16);
1244 cmdline_parse_token_num_t cmd_firewall_add_src_port_to =
1245         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_to,
1246         UINT16);
1247
1248 cmdline_parse_token_num_t cmd_firewall_add_dst_port_from =
1249         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_from,
1250         UINT16);
1251 cmdline_parse_token_num_t cmd_firewall_add_dst_port_to =
1252         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_to,
1253         UINT16);
1254
1255 cmdline_parse_token_num_t cmd_firewall_add_proto =
1256         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto, UINT8);
1257 cmdline_parse_token_num_t cmd_firewall_add_proto_mask =
1258         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto_mask,
1259         UINT8);
1260 cmdline_parse_token_num_t cmd_firewall_add_port =
1261         TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, port, UINT8);
1262
1263 cmdline_parse_inst_t cmd_firewall_add = {
1264         .f = cmd_firewall_add_parsed,
1265         .data = NULL,
1266         .help_str = "Firewall rule add",
1267         .tokens = {
1268                 (void *)&cmd_firewall_add_firewall_string,
1269                 (void *)&cmd_firewall_add_add_string,
1270                 (void *)&cmd_firewall_add_priority,
1271                 (void *)&cmd_firewall_add_src_ip,
1272                 (void *)&cmd_firewall_add_src_ip_mask,
1273                 (void *)&cmd_firewall_add_dst_ip,
1274                 (void *)&cmd_firewall_add_dst_ip_mask,
1275                 (void *)&cmd_firewall_add_src_port_from,
1276                 (void *)&cmd_firewall_add_src_port_to,
1277                 (void *)&cmd_firewall_add_dst_port_from,
1278                 (void *)&cmd_firewall_add_dst_port_to,
1279                 (void *)&cmd_firewall_add_proto,
1280                 (void *)&cmd_firewall_add_proto_mask,
1281                 (void *)&cmd_firewall_add_port,
1282                 NULL,
1283         },
1284 };
1285
1286 /* *** firewall - Del *** */
1287 struct cmd_firewall_del_result {
1288         cmdline_fixed_string_t firewall_string;
1289         cmdline_fixed_string_t del_string;
1290         cmdline_ipaddr_t src_ip;
1291         uint32_t src_ip_mask;
1292         cmdline_ipaddr_t dst_ip;
1293         uint32_t dst_ip_mask;
1294         uint16_t src_port_from;
1295         uint16_t src_port_to;
1296         uint16_t dst_port_from;
1297         uint16_t dst_port_to;
1298         uint8_t proto;
1299         uint8_t proto_mask;
1300 };
1301
1302 static void
1303 cmd_firewall_del_parsed(
1304         void *parsed_result,
1305         __attribute__((unused)) struct cmdline *cl,
1306         __attribute__((unused)) void *data)
1307 {
1308         struct cmd_firewall_del_result *params = parsed_result;
1309         struct app_rule rule, *old_rule;
1310         struct rte_mbuf *msg;
1311         struct app_msg_req *req;
1312         struct app_msg_resp *resp;
1313         int status;
1314
1315         uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
1316
1317         if (core_id == RTE_MAX_LCORE) {
1318                 printf("Firewall not performed by any CPU core\n");
1319                 return;
1320         }
1321
1322         struct rte_ring *ring_req = app_get_ring_req(core_id);
1323         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
1324
1325         /* Check params */
1326
1327         /* Create rule */
1328         memset(&rule, 0, sizeof(rule));
1329         rule.firewall.key.src_ip =
1330                 rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
1331         rule.firewall.key.src_ip_mask = params->src_ip_mask;
1332         rule.firewall.key.dst_ip =
1333                 rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
1334         rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
1335         rule.firewall.key.src_port_from = params->src_port_from;
1336         rule.firewall.key.src_port_to = params->src_port_to;
1337         rule.firewall.key.dst_port_from = params->dst_port_from;
1338         rule.firewall.key.dst_port_to = params->dst_port_to;
1339         rule.firewall.key.proto = params->proto;
1340         rule.firewall.key.proto_mask = params->proto_mask;
1341
1342         /* Check rule existence */
1343         IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
1344         if (old_rule == NULL)
1345                 return;
1346
1347         printf("Deleting firewall rule: ");
1348         print_firewall_rule(old_rule->firewall);
1349
1350         /* Allocate message buffer */
1351         msg = rte_ctrlmbuf_alloc(app.msg_pool);
1352         if (msg == NULL)
1353                 rte_panic("Unable to allocate new message\n");
1354
1355         /* Fill request message */
1356         req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
1357         memset(&req->firewall_del, 0, sizeof(req->firewall_del));
1358         req->type = APP_MSG_REQ_FW_DEL;
1359         req->firewall_del.delete_params.field_value[1].value.u32 =
1360                 rule.firewall.key.src_ip;
1361         req->firewall_del.delete_params.field_value[1].mask_range.u32 =
1362                 rule.firewall.key.src_ip_mask;
1363         req->firewall_del.delete_params.field_value[2].value.u32 =
1364                 rule.firewall.key.dst_ip;
1365         req->firewall_del.delete_params.field_value[2].mask_range.u32 =
1366                 rule.firewall.key.dst_ip_mask;
1367         req->firewall_del.delete_params.field_value[3].value.u16 =
1368                 rule.firewall.key.src_port_from;
1369         req->firewall_del.delete_params.field_value[3].mask_range.u16 =
1370                 rule.firewall.key.src_port_to;
1371         req->firewall_del.delete_params.field_value[4].value.u16 =
1372                 rule.firewall.key.dst_port_from;
1373         req->firewall_del.delete_params.field_value[4].mask_range.u16 =
1374                 rule.firewall.key.dst_port_to;
1375         req->firewall_del.delete_params.field_value[0].value.u8 =
1376                 rule.firewall.key.proto;
1377         req->firewall_del.delete_params.field_value[0].mask_range.u8 =
1378                 rule.firewall.key.proto_mask;
1379
1380         /* Send request */
1381         do {
1382                 status = rte_ring_sp_enqueue(ring_req, (void *) msg);
1383         } while (status == -ENOBUFS);
1384
1385         /* Wait for response */
1386         do {
1387                 status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
1388         } while (status != 0);
1389         resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
1390
1391         /* Check response */
1392         if (resp->result != 0)
1393                 printf("Request FIREWALL_DEL failed %u)\n", resp->result);
1394         else {
1395                 TAILQ_REMOVE(&firewall_table, old_rule, entries);
1396                 rte_free(old_rule);
1397                 n_firewall_rules--;
1398         }
1399
1400         /* Free message buffer */
1401         rte_ctrlmbuf_free(msg);
1402 }
1403
1404 cmdline_parse_token_string_t cmd_firewall_del_firewall_string =
1405         TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result,
1406         firewall_string, "firewall");
1407
1408 cmdline_parse_token_string_t cmd_firewall_del_del_string =
1409         TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result, del_string,
1410         "del");
1411
1412 cmdline_parse_token_ipaddr_t cmd_firewall_del_src_ip =
1413         TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, src_ip);
1414 cmdline_parse_token_num_t cmd_firewall_del_src_ip_mask =
1415         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_ip_mask,
1416         UINT32);
1417
1418 cmdline_parse_token_ipaddr_t cmd_firewall_del_dst_ip =
1419         TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, dst_ip);
1420 cmdline_parse_token_num_t cmd_firewall_del_dst_ip_mask =
1421         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_ip_mask,
1422         UINT32);
1423
1424 cmdline_parse_token_num_t cmd_firewall_del_src_port_from =
1425         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_from,
1426         UINT16);
1427 cmdline_parse_token_num_t cmd_firewall_del_src_port_to =
1428         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_to,
1429         UINT16);
1430
1431 cmdline_parse_token_num_t cmd_firewall_del_dst_port_from =
1432         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_from,
1433         UINT16);
1434 cmdline_parse_token_num_t cmd_firewall_del_dst_port_to =
1435         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_to,
1436         UINT16);
1437
1438 cmdline_parse_token_num_t cmd_firewall_del_proto =
1439         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto, UINT8);
1440 cmdline_parse_token_num_t cmd_firewall_del_proto_mask =
1441         TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto_mask,
1442         UINT8);
1443
1444 cmdline_parse_inst_t cmd_firewall_del = {
1445         .f = cmd_firewall_del_parsed,
1446         .data = NULL,
1447         .help_str = "Firewall rule delete",
1448         .tokens = {
1449                 (void *)&cmd_firewall_del_firewall_string,
1450                 (void *)&cmd_firewall_del_del_string,
1451                 (void *)&cmd_firewall_del_src_ip,
1452                 (void *)&cmd_firewall_del_src_ip_mask,
1453                 (void *)&cmd_firewall_del_dst_ip,
1454                 (void *)&cmd_firewall_del_dst_ip_mask,
1455                 (void *)&cmd_firewall_del_src_port_from,
1456                 (void *)&cmd_firewall_del_src_port_to,
1457                 (void *)&cmd_firewall_del_dst_port_from,
1458                 (void *)&cmd_firewall_del_dst_port_to,
1459                 (void *)&cmd_firewall_del_proto,
1460                 (void *)&cmd_firewall_del_proto_mask,
1461                 NULL,
1462         },
1463 };
1464
1465 /* *** Firewall - Print *** */
1466 struct cmd_firewall_print_result {
1467         cmdline_fixed_string_t firewall_string;
1468         cmdline_fixed_string_t print_string;
1469 };
1470
1471 static void
1472 cmd_firewall_print_parsed(
1473         __attribute__((unused)) void *parsed_result,
1474         __attribute__((unused)) struct cmdline *cl,
1475         __attribute__((unused)) void *data)
1476 {
1477         struct app_rule *it;
1478
1479         TAILQ_FOREACH(it, &firewall_table, entries) {
1480                 print_firewall_rule(it->firewall);
1481         }
1482 }
1483
1484 cmdline_parse_token_string_t cmd_firewall_print_firewall_string =
1485         TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result,
1486         firewall_string, "firewall");
1487
1488 cmdline_parse_token_string_t cmd_firewall_print_print_string =
1489         TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result, print_string,
1490         "ls");
1491
1492 cmdline_parse_inst_t cmd_firewall_print = {
1493         .f = cmd_firewall_print_parsed,
1494         .data = NULL,
1495         .help_str = "Firewall rules list",
1496         .tokens = {
1497                 (void *)&cmd_firewall_print_firewall_string,
1498                 (void *)&cmd_firewall_print_print_string,
1499                 NULL,
1500         },
1501 };
1502
1503 #endif
1504
1505 /* *** Flow Classification - Add All *** */
1506 struct cmd_flow_add_all_result {
1507         cmdline_fixed_string_t flow_string;
1508         cmdline_fixed_string_t add_string;
1509         cmdline_fixed_string_t all_string;
1510 };
1511
1512 static void
1513 cmd_flow_add_all_parsed(
1514         __attribute__((unused)) void *parsed_result,
1515         __attribute__((unused)) struct cmdline *cl,
1516         __attribute__((unused)) void *data)
1517 {
1518         struct app_msg_req *req;
1519         struct app_msg_resp *resp;
1520         void *msg;
1521         int status;
1522
1523         struct rte_ring *ring_req =
1524                 app_get_ring_req(app_get_first_core_id(APP_CORE_FC));
1525         struct rte_ring *ring_resp =
1526                 app_get_ring_resp(app_get_first_core_id(APP_CORE_FC));
1527
1528         /* Allocate message buffer */
1529         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
1530         if (msg == NULL)
1531                 rte_panic("Unable to allocate new message\n");
1532
1533         /* Fill request message */
1534         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1535         memset(req, 0, sizeof(struct app_msg_req));
1536
1537         req->type = APP_MSG_REQ_FC_ADD_ALL;
1538
1539         /* Send request */
1540         do {
1541                 status = rte_ring_sp_enqueue(ring_req, msg);
1542         } while (status == -ENOBUFS);
1543
1544         /* Wait for response */
1545         do {
1546                 status = rte_ring_sc_dequeue(ring_resp, &msg);
1547         } while (status != 0);
1548         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1549
1550         /* Check response */
1551         if (resp->result != 0)
1552                 printf("Request FLOW_ADD_ALL failed (%u)\n", resp->result);
1553
1554         /* Free message buffer */
1555         rte_ctrlmbuf_free((struct rte_mbuf *)msg);
1556 }
1557
1558 cmdline_parse_token_string_t cmd_flow_add_all_flow_string =
1559         TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, flow_string,
1560         "flow");
1561
1562 cmdline_parse_token_string_t cmd_flow_add_all_add_string =
1563         TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, add_string,
1564         "add");
1565
1566 cmdline_parse_token_string_t cmd_flow_add_all_all_string =
1567         TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, all_string,
1568         "all");
1569
1570 cmdline_parse_inst_t cmd_flow_add_all = {
1571         .f = cmd_flow_add_all_parsed,
1572         .data = NULL,
1573         .help_str = "Flow table initialization based on hard-coded rule",
1574         .tokens = {
1575                 (void *)&cmd_flow_add_all_flow_string,
1576                 (void *)&cmd_flow_add_all_add_string,
1577                 (void *)&cmd_flow_add_all_all_string,
1578                 NULL,
1579         },
1580 };
1581
1582 /* *** Flow Classification - Add *** */
1583 struct cmd_flow_add_result {
1584         cmdline_fixed_string_t flow_string;
1585         cmdline_fixed_string_t add_string;
1586         cmdline_ipaddr_t src_ip;
1587         cmdline_ipaddr_t dst_ip;
1588         uint16_t src_port;
1589         uint16_t dst_port;
1590         uint8_t proto;
1591         uint8_t port;
1592 };
1593
1594 static void
1595 cmd_flow_add_parsed(
1596         void *parsed_result,
1597         __attribute__((unused)) struct cmdline *cl,
1598         __attribute__((unused)) void *data)
1599 {
1600         struct cmd_flow_add_result *params = parsed_result;
1601         struct app_rule rule, *old_rule;
1602         struct app_msg_req *req;
1603         struct app_msg_resp *resp;
1604         void *msg;
1605         int status;
1606
1607         uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
1608
1609         if (core_id == RTE_MAX_LCORE) {
1610                 printf("Flow classification not performed by any CPU core\n");
1611                 return;
1612         }
1613
1614         struct rte_ring *ring_req = app_get_ring_req(core_id);
1615         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
1616
1617         /* Check params */
1618         if (params->port >= app.n_ports) {
1619                 printf("Illegal value for port parameter (%u)\n", params->port);
1620                 return;
1621         }
1622
1623         /* Create rule */
1624         memset(&rule, 0, sizeof(rule));
1625         rule.flow.key.src_ip =
1626                 rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
1627         rule.flow.key.dst_ip =
1628                 rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
1629         rule.flow.key.src_port = params->src_port;
1630         rule.flow.key.dst_port = params->dst_port;
1631         rule.flow.key.proto = params->proto;
1632         rule.flow.port = params->port;
1633
1634         /* Check rule existence */
1635         IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
1636         if ((old_rule == NULL) && (n_flow_rules == app.max_flow_rules)) {
1637                 printf("Flow table is full.\n");
1638                 return;
1639         }
1640
1641         printf("Adding flow: ");
1642         print_flow_rule(rule.flow);
1643
1644         /* Allocate message buffer */
1645         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
1646         if (msg == NULL)
1647                 rte_panic("Unable to allocate new message\n");
1648
1649         /* Fill request message */
1650         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1651         memset(req, 0, sizeof(struct app_msg_req));
1652
1653         req->type = APP_MSG_REQ_FC_ADD;
1654         req->flow_classif_add.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
1655         req->flow_classif_add.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
1656         req->flow_classif_add.key.port_src =
1657                 rte_bswap16(rule.flow.key.src_port);
1658         req->flow_classif_add.key.port_dst =
1659                 rte_bswap16(rule.flow.key.dst_port);
1660         req->flow_classif_add.key.proto = rule.flow.key.proto;
1661         req->flow_classif_add.port = rule.flow.port;
1662
1663         /* Send request */
1664         do {
1665                 status = rte_ring_sp_enqueue(ring_req, msg);
1666         } while (status == -ENOBUFS);
1667
1668         /* Wait for response */
1669         do {
1670                 status = rte_ring_sc_dequeue(ring_resp, &msg);
1671         } while (status != 0);
1672         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1673
1674         /* Check response */
1675         if (resp->result != 0)
1676                 printf("Request FLOW_ADD failed (%u)\n", resp->result);
1677         else {
1678                 if (old_rule == NULL) {
1679                         struct app_rule *new_rule = (struct app_rule *)
1680                                 rte_zmalloc_socket("CLI",
1681                                 sizeof(struct app_rule),
1682                                 RTE_CACHE_LINE_SIZE,
1683                                 rte_socket_id());
1684
1685                         if (new_rule == NULL)
1686                                 rte_panic("Unable to allocate new rule\n");
1687
1688                         memcpy(new_rule, &rule, sizeof(rule));
1689                         TAILQ_INSERT_TAIL(&flow_table, new_rule, entries);
1690                         n_flow_rules++;
1691                 } else
1692                         old_rule->flow.port = rule.flow.port;
1693         }
1694
1695         /* Free message buffer */
1696         rte_ctrlmbuf_free((struct rte_mbuf *)msg);
1697 }
1698
1699 cmdline_parse_token_string_t cmd_flow_add_flow_string =
1700         TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, flow_string,
1701         "flow");
1702
1703 cmdline_parse_token_string_t cmd_flow_add_add_string =
1704         TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, add_string, "add");
1705
1706 cmdline_parse_token_ipaddr_t cmd_flow_add_src_ip =
1707         TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, src_ip);
1708
1709 cmdline_parse_token_ipaddr_t cmd_flow_add_dst_ip =
1710         TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, dst_ip);
1711
1712 cmdline_parse_token_num_t cmd_flow_add_src_port =
1713         TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, src_port, UINT16);
1714
1715 cmdline_parse_token_num_t cmd_flow_add_dst_port =
1716         TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, dst_port, UINT16);
1717
1718 cmdline_parse_token_num_t cmd_flow_add_proto =
1719         TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, proto, UINT8);
1720
1721 cmdline_parse_token_num_t cmd_flow_add_port =
1722         TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, port, UINT8);
1723
1724 cmdline_parse_inst_t cmd_flow_add = {
1725         .f = cmd_flow_add_parsed,
1726         .data = NULL,
1727         .help_str = "Flow add",
1728         .tokens = {
1729                 (void *)&cmd_flow_add_flow_string,
1730                 (void *)&cmd_flow_add_add_string,
1731                 (void *)&cmd_flow_add_src_ip,
1732                 (void *)&cmd_flow_add_dst_ip,
1733                 (void *)&cmd_flow_add_src_port,
1734                 (void *)&cmd_flow_add_dst_port,
1735                 (void *)&cmd_flow_add_proto,
1736                 (void *)&cmd_flow_add_port,
1737                 NULL,
1738         },
1739 };
1740
1741 /* *** Flow Classification - Del *** */
1742 struct cmd_flow_del_result {
1743         cmdline_fixed_string_t flow_string;
1744         cmdline_fixed_string_t del_string;
1745         cmdline_ipaddr_t src_ip;
1746         cmdline_ipaddr_t dst_ip;
1747         uint16_t src_port;
1748         uint16_t dst_port;
1749         uint8_t proto;
1750 };
1751
1752 static void
1753 cmd_flow_del_parsed(
1754         void *parsed_result,
1755         __attribute__((unused)) struct cmdline *cl,
1756         __attribute__((unused)) void *data)
1757 {
1758         struct cmd_flow_del_result *params = parsed_result;
1759         struct app_rule rule, *old_rule;
1760         struct app_msg_req *req;
1761         struct app_msg_resp *resp;
1762         void *msg;
1763         int status;
1764
1765         uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
1766
1767         if (core_id == RTE_MAX_LCORE) {
1768                 printf("Flow classification not performed by any CPU core.\n");
1769                 return;
1770         }
1771
1772         struct rte_ring *ring_req = app_get_ring_req(core_id);
1773         struct rte_ring *ring_resp = app_get_ring_resp(core_id);
1774
1775         /* Create rule */
1776         memset(&rule, 0, sizeof(rule));
1777         rule.flow.key.src_ip =
1778                 rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
1779         rule.flow.key.dst_ip =
1780                 rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
1781         rule.flow.key.src_port = params->src_port;
1782         rule.flow.key.dst_port = params->dst_port;
1783         rule.flow.key.proto = params->proto;
1784
1785         /* Check rule existence */
1786         IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
1787         if (old_rule == NULL)
1788                 return;
1789
1790         printf("Deleting flow: ");
1791         print_flow_rule(old_rule->flow);
1792
1793         /* Allocate message buffer */
1794         msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
1795         if (msg == NULL)
1796                 rte_panic("Unable to allocate new message\n");
1797
1798         /* Fill request message */
1799         req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1800         memset(req, 0, sizeof(struct app_msg_req));
1801
1802         req->type = APP_MSG_REQ_FC_DEL;
1803         req->flow_classif_del.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
1804         req->flow_classif_del.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
1805         req->flow_classif_del.key.port_src =
1806                 rte_bswap32(rule.flow.key.src_port);
1807         req->flow_classif_del.key.port_dst =
1808                 rte_bswap32(rule.flow.key.dst_port);
1809         req->flow_classif_del.key.proto = rule.flow.key.proto;
1810
1811         /* Send request */
1812         do {
1813                 status = rte_ring_sp_enqueue(ring_req, msg);
1814         } while (status == -ENOBUFS);
1815
1816         /* Wait for response */
1817         do {
1818                 status = rte_ring_sc_dequeue(ring_resp, &msg);
1819         } while (status != 0);
1820         resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
1821
1822         /* Check response */
1823         if (resp->result != 0)
1824                 printf("Request FLOW_DEL failed (%u)\n", resp->result);
1825         else {
1826                 TAILQ_REMOVE(&flow_table, old_rule, entries);
1827                 rte_free(old_rule);
1828                 n_flow_rules--;
1829         }
1830
1831         /* Free message buffer */
1832         rte_ctrlmbuf_free((struct rte_mbuf *)msg);
1833 }
1834
1835 cmdline_parse_token_string_t cmd_flow_del_flow_string =
1836         TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, flow_string,
1837         "flow");
1838
1839 cmdline_parse_token_string_t cmd_flow_del_del_string =
1840         TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, del_string, "del");
1841
1842 cmdline_parse_token_ipaddr_t cmd_flow_del_src_ip =
1843         TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, src_ip);
1844
1845 cmdline_parse_token_ipaddr_t cmd_flow_del_dst_ip =
1846         TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, dst_ip);
1847
1848 cmdline_parse_token_num_t cmd_flow_del_src_port =
1849         TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, src_port, UINT16);
1850
1851 cmdline_parse_token_num_t cmd_flow_del_dst_port =
1852         TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, dst_port, UINT16);
1853
1854 cmdline_parse_token_num_t cmd_flow_del_proto =
1855         TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, proto, UINT8);
1856
1857 cmdline_parse_inst_t cmd_flow_del = {
1858         .f = cmd_flow_del_parsed,
1859         .data = NULL,
1860         .help_str = "Flow delete",
1861         .tokens = {
1862                 (void *)&cmd_flow_del_flow_string,
1863                 (void *)&cmd_flow_del_del_string,
1864                 (void *)&cmd_flow_del_src_ip,
1865                 (void *)&cmd_flow_del_dst_ip,
1866                 (void *)&cmd_flow_del_src_port,
1867                 (void *)&cmd_flow_del_dst_port,
1868                 (void *)&cmd_flow_del_proto,
1869                 NULL,
1870         },
1871 };
1872
1873 /* *** Flow Classification - Print *** */
1874 struct cmd_flow_print_result {
1875         cmdline_fixed_string_t flow_string;
1876         cmdline_fixed_string_t print_string;
1877 };
1878
1879 static void
1880 cmd_flow_print_parsed(
1881         __attribute__((unused)) void *parsed_result,
1882         __attribute__((unused)) struct cmdline *cl,
1883         __attribute__((unused)) void *data)
1884 {
1885         struct app_rule *it;
1886
1887         TAILQ_FOREACH(it, &flow_table, entries) {
1888                 print_flow_rule(it->flow);
1889         }
1890 }
1891
1892 cmdline_parse_token_string_t cmd_flow_print_flow_string =
1893         TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, flow_string,
1894         "flow");
1895
1896 cmdline_parse_token_string_t cmd_flow_print_print_string =
1897         TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, print_string,
1898         "ls");
1899
1900 cmdline_parse_inst_t cmd_flow_print = {
1901         .f = cmd_flow_print_parsed,
1902         .data = NULL,
1903         .help_str = "Flow list",
1904         .tokens = {
1905                 (void *)&cmd_flow_print_flow_string,
1906                 (void *)&cmd_flow_print_print_string,
1907                 NULL,
1908         },
1909 };
1910
1911 /* *** QUIT *** */
1912 struct cmd_quit_result {
1913         cmdline_fixed_string_t quit;
1914 };
1915
1916 static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
1917                 struct cmdline *cl,
1918                 __attribute__((unused)) void *data)
1919 {
1920         cmdline_quit(cl);
1921 }
1922
1923 cmdline_parse_token_string_t cmd_quit_quit =
1924                 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
1925
1926 cmdline_parse_inst_t cmd_quit = {
1927         .f = cmd_quit_parsed,
1928         .data = NULL,
1929         .help_str = "Exit application",
1930         .tokens = {
1931                 (void *)&cmd_quit_quit,
1932                 NULL,
1933         },
1934 };
1935
1936 /* List of commands */
1937 cmdline_parse_ctx_t main_ctx[] = {
1938         (cmdline_parse_inst_t *)&cmd_flow_add,
1939         (cmdline_parse_inst_t *)&cmd_flow_del,
1940         (cmdline_parse_inst_t *)&cmd_flow_add_all,
1941         (cmdline_parse_inst_t *)&cmd_flow_print,
1942 #ifdef RTE_LIBRTE_ACL
1943         (cmdline_parse_inst_t *)&cmd_firewall_add,
1944         (cmdline_parse_inst_t *)&cmd_firewall_del,
1945         (cmdline_parse_inst_t *)&cmd_firewall_print,
1946 #endif
1947         (cmdline_parse_inst_t *)&cmd_route_add,
1948         (cmdline_parse_inst_t *)&cmd_route_del,
1949         (cmdline_parse_inst_t *)&cmd_routing_print,
1950         (cmdline_parse_inst_t *)&cmd_arp_add,
1951         (cmdline_parse_inst_t *)&cmd_arp_del,
1952         (cmdline_parse_inst_t *)&cmd_arp_print,
1953         (cmdline_parse_inst_t *)&cmd_run_file,
1954         (cmdline_parse_inst_t *)&cmd_link_enable,
1955         (cmdline_parse_inst_t *)&cmd_link_disable,
1956         (cmdline_parse_inst_t *)&cmd_quit,
1957         NULL,
1958 };
1959
1960 /* Main loop */
1961 void
1962 app_main_loop_cmdline(void)
1963 {
1964         struct cmdline *cl;
1965         uint32_t core_id = rte_lcore_id();
1966
1967         RTE_LOG(INFO, USER1, "Core %u is running the command line interface\n",
1968                 core_id);
1969
1970         n_arp_rules = 0;
1971         n_routing_rules = 0;
1972         n_firewall_rules = 0;
1973         n_flow_rules = 0;
1974
1975         app_init_rule_tables();
1976
1977         cl = cmdline_stdin_new(main_ctx, "pipeline> ");
1978         if (cl == NULL)
1979                 return;
1980         cmdline_interact(cl);
1981         cmdline_stdin_exit(cl);
1982 }