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