Imported Upstream version 16.07-rc1
[deb_dpdk.git] / examples / ip_pipeline / pipeline / pipeline_firewall.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 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 #include <errno.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <sys/queue.h>
39 #include <netinet/in.h>
40
41 #include <rte_common.h>
42 #include <rte_hexdump.h>
43 #include <rte_malloc.h>
44 #include <cmdline_rdline.h>
45 #include <cmdline_parse.h>
46 #include <cmdline_parse_num.h>
47 #include <cmdline_parse_string.h>
48
49 #include "app.h"
50 #include "pipeline_common_fe.h"
51 #include "pipeline_firewall.h"
52 #include "parser.h"
53
54 struct app_pipeline_firewall_rule {
55         struct pipeline_firewall_key key;
56         int32_t priority;
57         uint32_t port_id;
58         void *entry_ptr;
59
60         TAILQ_ENTRY(app_pipeline_firewall_rule) node;
61 };
62
63 struct app_pipeline_firewall {
64         /* parameters */
65         uint32_t n_ports_in;
66         uint32_t n_ports_out;
67
68         /* rules */
69         TAILQ_HEAD(, app_pipeline_firewall_rule) rules;
70         uint32_t n_rules;
71         uint32_t default_rule_present;
72         uint32_t default_rule_port_id;
73         void *default_rule_entry_ptr;
74 };
75
76 static void
77 print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule)
78 {
79         printf("Prio = %" PRId32 " (SA = %" PRIu32 ".%" PRIu32
80                 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", "
81                 "DA = %" PRIu32 ".%" PRIu32
82                 ".%"PRIu32 ".%" PRIu32 "/%" PRIu32 ", "
83                 "SP = %" PRIu32 "-%" PRIu32 ", "
84                 "DP = %" PRIu32 "-%" PRIu32 ", "
85                 "Proto = %" PRIu32 " / 0x%" PRIx32 ") => "
86                 "Port = %" PRIu32 " (entry ptr = %p)\n",
87
88                 rule->priority,
89
90                 (rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF,
91                 (rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF,
92                 (rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF,
93                 rule->key.key.ipv4_5tuple.src_ip & 0xFF,
94                 rule->key.key.ipv4_5tuple.src_ip_mask,
95
96                 (rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF,
97                 (rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF,
98                 (rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF,
99                 rule->key.key.ipv4_5tuple.dst_ip & 0xFF,
100                 rule->key.key.ipv4_5tuple.dst_ip_mask,
101
102                 rule->key.key.ipv4_5tuple.src_port_from,
103                 rule->key.key.ipv4_5tuple.src_port_to,
104
105                 rule->key.key.ipv4_5tuple.dst_port_from,
106                 rule->key.key.ipv4_5tuple.dst_port_to,
107
108                 rule->key.key.ipv4_5tuple.proto,
109                 rule->key.key.ipv4_5tuple.proto_mask,
110
111                 rule->port_id,
112                 rule->entry_ptr);
113 }
114
115 static struct app_pipeline_firewall_rule *
116 app_pipeline_firewall_rule_find(struct app_pipeline_firewall *p,
117         struct pipeline_firewall_key *key)
118 {
119         struct app_pipeline_firewall_rule *r;
120
121         TAILQ_FOREACH(r, &p->rules, node)
122                 if (memcmp(key,
123                         &r->key,
124                         sizeof(struct pipeline_firewall_key)) == 0)
125                         return r;
126
127         return NULL;
128 }
129
130 static int
131 app_pipeline_firewall_ls(
132         struct app_params *app,
133         uint32_t pipeline_id)
134 {
135         struct app_pipeline_firewall *p;
136         struct app_pipeline_firewall_rule *rule;
137         uint32_t n_rules;
138         int priority;
139
140         /* Check input arguments */
141         if (app == NULL)
142                 return -1;
143
144         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
145         if (p == NULL)
146                 return -1;
147
148         n_rules = p->n_rules;
149         for (priority = 0; n_rules; priority++)
150                 TAILQ_FOREACH(rule, &p->rules, node)
151                         if (rule->priority == priority) {
152                                 print_firewall_ipv4_rule(rule);
153                                 n_rules--;
154                         }
155
156         if (p->default_rule_present)
157                 printf("Default rule: port %" PRIu32 " (entry ptr = %p)\n",
158                         p->default_rule_port_id,
159                         p->default_rule_entry_ptr);
160         else
161                 printf("Default rule: DROP\n");
162
163         printf("\n");
164
165         return 0;
166 }
167
168 static void*
169 app_pipeline_firewall_init(struct pipeline_params *params,
170         __rte_unused void *arg)
171 {
172         struct app_pipeline_firewall *p;
173         uint32_t size;
174
175         /* Check input arguments */
176         if ((params == NULL) ||
177                 (params->n_ports_in == 0) ||
178                 (params->n_ports_out == 0))
179                 return NULL;
180
181         /* Memory allocation */
182         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_firewall));
183         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
184         if (p == NULL)
185                 return NULL;
186
187         /* Initialization */
188         p->n_ports_in = params->n_ports_in;
189         p->n_ports_out = params->n_ports_out;
190
191         TAILQ_INIT(&p->rules);
192         p->n_rules = 0;
193         p->default_rule_present = 0;
194         p->default_rule_port_id = 0;
195         p->default_rule_entry_ptr = NULL;
196
197         return (void *) p;
198 }
199
200 static int
201 app_pipeline_firewall_free(void *pipeline)
202 {
203         struct app_pipeline_firewall *p = pipeline;
204
205         /* Check input arguments */
206         if (p == NULL)
207                 return -1;
208
209         /* Free resources */
210         while (!TAILQ_EMPTY(&p->rules)) {
211                 struct app_pipeline_firewall_rule *rule;
212
213                 rule = TAILQ_FIRST(&p->rules);
214                 TAILQ_REMOVE(&p->rules, rule, node);
215                 rte_free(rule);
216         }
217
218         rte_free(p);
219         return 0;
220 }
221
222 static int
223 app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key)
224 {
225         switch (key->type) {
226         case PIPELINE_FIREWALL_IPV4_5TUPLE:
227         {
228                 uint32_t src_ip_depth = key->key.ipv4_5tuple.src_ip_mask;
229                 uint32_t dst_ip_depth = key->key.ipv4_5tuple.dst_ip_mask;
230                 uint16_t src_port_from = key->key.ipv4_5tuple.src_port_from;
231                 uint16_t src_port_to = key->key.ipv4_5tuple.src_port_to;
232                 uint16_t dst_port_from = key->key.ipv4_5tuple.dst_port_from;
233                 uint16_t dst_port_to = key->key.ipv4_5tuple.dst_port_to;
234
235                 uint32_t src_ip_netmask = 0;
236                 uint32_t dst_ip_netmask = 0;
237
238                 if ((src_ip_depth > 32) ||
239                         (dst_ip_depth > 32) ||
240                         (src_port_from > src_port_to) ||
241                         (dst_port_from > dst_port_to))
242                         return -1;
243
244                 if (src_ip_depth)
245                         src_ip_netmask = (~0U) << (32 - src_ip_depth);
246
247                 if (dst_ip_depth)
248                         dst_ip_netmask = ((~0U) << (32 - dst_ip_depth));
249
250                 key->key.ipv4_5tuple.src_ip &= src_ip_netmask;
251                 key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask;
252
253                 return 0;
254         }
255
256         default:
257                 return -1;
258         }
259 }
260
261 int
262 app_pipeline_firewall_load_file(char *filename,
263         struct pipeline_firewall_key *keys,
264         uint32_t *priorities,
265         uint32_t *port_ids,
266         uint32_t *n_keys,
267         uint32_t *line)
268 {
269         FILE *f = NULL;
270         char file_buf[1024];
271         uint32_t i, l;
272
273         /* Check input arguments */
274         if ((filename == NULL) ||
275                 (keys == NULL) ||
276                 (priorities == NULL) ||
277                 (port_ids == NULL) ||
278                 (n_keys == NULL) ||
279                 (*n_keys == 0) ||
280                 (line == NULL)) {
281                 if (line)
282                         *line = 0;
283                 return -1;
284                 }
285
286         /* Open input file */
287         f = fopen(filename, "r");
288         if (f == NULL) {
289                 *line = 0;
290                 return -1;
291         }
292
293         /* Read file */
294         for (i = 0, l = 1; i < *n_keys; l++) {
295                 char *tokens[32];
296                 uint32_t n_tokens = RTE_DIM(tokens);
297
298                 uint32_t priority = 0;
299                 struct in_addr sipaddr;
300                 uint32_t sipdepth = 0;
301                 struct in_addr dipaddr;
302                 uint32_t dipdepth = 0;
303                 uint16_t sport0 = 0;
304                 uint16_t sport1 = 0;
305                 uint16_t dport0 = 0;
306                 uint16_t dport1 = 0;
307                 uint8_t proto = 0;
308                 uint8_t protomask = 0;
309                 uint32_t port_id = 0;
310
311                 int status;
312
313                 if (fgets(file_buf, sizeof(file_buf), f) == NULL)
314                         break;
315
316                 status = parse_tokenize_string(file_buf, tokens, &n_tokens);
317                 if (status)
318                         goto error1;
319
320                 if ((n_tokens == 0) || (tokens[0][0] == '#'))
321                         continue;
322
323                 if ((n_tokens != 15) ||
324                         strcmp(tokens[0], "priority") ||
325                         parser_read_uint32(&priority, tokens[1]) ||
326                         strcmp(tokens[2], "ipv4") ||
327                         parse_ipv4_addr(tokens[3], &sipaddr) ||
328                         parser_read_uint32(&sipdepth, tokens[4]) ||
329                         parse_ipv4_addr(tokens[5], &dipaddr) ||
330                         parser_read_uint32(&dipdepth, tokens[6]) ||
331                         parser_read_uint16(&sport0, tokens[7]) ||
332                         parser_read_uint16(&sport1, tokens[8]) ||
333                         parser_read_uint16(&dport0, tokens[9]) ||
334                         parser_read_uint16(&dport1, tokens[10]) ||
335                         parser_read_uint8(&proto, tokens[11]) ||
336                         parser_read_uint8_hex(&protomask, tokens[12]) ||
337                         strcmp(tokens[13], "port") ||
338                         parser_read_uint32(&port_id, tokens[14]))
339                         goto error1;
340
341                 keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
342                 keys[i].key.ipv4_5tuple.src_ip =
343                         rte_be_to_cpu_32(sipaddr.s_addr);
344                 keys[i].key.ipv4_5tuple.src_ip_mask = sipdepth;
345                 keys[i].key.ipv4_5tuple.dst_ip =
346                         rte_be_to_cpu_32(dipaddr.s_addr);
347                 keys[i].key.ipv4_5tuple.dst_ip_mask = dipdepth;
348                 keys[i].key.ipv4_5tuple.src_port_from = sport0;
349                 keys[i].key.ipv4_5tuple.src_port_to = sport1;
350                 keys[i].key.ipv4_5tuple.dst_port_from = dport0;
351                 keys[i].key.ipv4_5tuple.dst_port_to = dport1;
352                 keys[i].key.ipv4_5tuple.proto = proto;
353                 keys[i].key.ipv4_5tuple.proto_mask = protomask;
354
355                 port_ids[i] = port_id;
356                 priorities[i] = priority;
357
358                 if (app_pipeline_firewall_key_check_and_normalize(&keys[i]))
359                         goto error1;
360
361                 i++;
362         }
363
364         /* Close file */
365         *n_keys = i;
366         fclose(f);
367         return 0;
368
369 error1:
370         *line = l;
371         fclose(f);
372         return -1;
373 }
374
375 int
376 app_pipeline_firewall_add_rule(struct app_params *app,
377         uint32_t pipeline_id,
378         struct pipeline_firewall_key *key,
379         uint32_t priority,
380         uint32_t port_id)
381 {
382         struct app_pipeline_firewall *p;
383         struct app_pipeline_firewall_rule *rule;
384         struct pipeline_firewall_add_msg_req *req;
385         struct pipeline_firewall_add_msg_rsp *rsp;
386         int new_rule;
387
388         /* Check input arguments */
389         if ((app == NULL) ||
390                 (key == NULL) ||
391                 (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE))
392                 return -1;
393
394         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
395         if (p == NULL)
396                 return -1;
397
398         if (port_id >= p->n_ports_out)
399                 return -1;
400
401         if (app_pipeline_firewall_key_check_and_normalize(key) != 0)
402                 return -1;
403
404         /* Find existing rule or allocate new rule */
405         rule = app_pipeline_firewall_rule_find(p, key);
406         new_rule = (rule == NULL);
407         if (rule == NULL) {
408                 rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE);
409
410                 if (rule == NULL)
411                         return -1;
412         }
413
414         /* Allocate and write request */
415         req = app_msg_alloc(app);
416         if (req == NULL) {
417                 if (new_rule)
418                         rte_free(rule);
419                 return -1;
420         }
421
422         req->type = PIPELINE_MSG_REQ_CUSTOM;
423         req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD;
424         memcpy(&req->key, key, sizeof(*key));
425         req->priority = priority;
426         req->port_id = port_id;
427
428         /* Send request and wait for response */
429         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
430         if (rsp == NULL) {
431                 if (new_rule)
432                         rte_free(rule);
433                 return -1;
434         }
435
436         /* Read response and write rule */
437         if (rsp->status ||
438                 (rsp->entry_ptr == NULL) ||
439                 ((new_rule == 0) && (rsp->key_found == 0)) ||
440                 ((new_rule == 1) && (rsp->key_found == 1))) {
441                 app_msg_free(app, rsp);
442                 if (new_rule)
443                         rte_free(rule);
444                 return -1;
445         }
446
447         memcpy(&rule->key, key, sizeof(*key));
448         rule->priority = priority;
449         rule->port_id = port_id;
450         rule->entry_ptr = rsp->entry_ptr;
451
452         /* Commit rule */
453         if (new_rule) {
454                 TAILQ_INSERT_TAIL(&p->rules, rule, node);
455                 p->n_rules++;
456         }
457
458         print_firewall_ipv4_rule(rule);
459
460         /* Free response */
461         app_msg_free(app, rsp);
462
463         return 0;
464 }
465
466 int
467 app_pipeline_firewall_delete_rule(struct app_params *app,
468         uint32_t pipeline_id,
469         struct pipeline_firewall_key *key)
470 {
471         struct app_pipeline_firewall *p;
472         struct app_pipeline_firewall_rule *rule;
473         struct pipeline_firewall_del_msg_req *req;
474         struct pipeline_firewall_del_msg_rsp *rsp;
475
476         /* Check input arguments */
477         if ((app == NULL) ||
478                 (key == NULL) ||
479                 (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE))
480                 return -1;
481
482         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
483         if (p == NULL)
484                 return -1;
485
486         if (app_pipeline_firewall_key_check_and_normalize(key) != 0)
487                 return -1;
488
489         /* Find rule */
490         rule = app_pipeline_firewall_rule_find(p, key);
491         if (rule == NULL)
492                 return 0;
493
494         /* Allocate and write request */
495         req = app_msg_alloc(app);
496         if (req == NULL)
497                 return -1;
498
499         req->type = PIPELINE_MSG_REQ_CUSTOM;
500         req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL;
501         memcpy(&req->key, key, sizeof(*key));
502
503         /* Send request and wait for response */
504         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
505         if (rsp == NULL)
506                 return -1;
507
508         /* Read response */
509         if (rsp->status || !rsp->key_found) {
510                 app_msg_free(app, rsp);
511                 return -1;
512         }
513
514         /* Remove rule */
515         TAILQ_REMOVE(&p->rules, rule, node);
516         p->n_rules--;
517         rte_free(rule);
518
519         /* Free response */
520         app_msg_free(app, rsp);
521
522         return 0;
523 }
524
525 int
526 app_pipeline_firewall_add_bulk(struct app_params *app,
527                 uint32_t pipeline_id,
528                 struct pipeline_firewall_key *keys,
529                 uint32_t n_keys,
530                 uint32_t *priorities,
531                 uint32_t *port_ids)
532 {
533         struct app_pipeline_firewall *p;
534         struct pipeline_firewall_add_bulk_msg_req *req;
535         struct pipeline_firewall_add_bulk_msg_rsp *rsp;
536
537         struct app_pipeline_firewall_rule **rules;
538         int *new_rules;
539
540         int *keys_found;
541         void **entries_ptr;
542
543         uint32_t i;
544         int status = 0;
545
546         /* Check input arguments */
547         if (app == NULL)
548                 return -1;
549
550         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
551         if (p == NULL)
552                 return -1;
553
554         rules = rte_malloc(NULL,
555                 n_keys * sizeof(struct app_pipeline_firewall_rule *),
556                 RTE_CACHE_LINE_SIZE);
557         if (rules == NULL)
558                 return -1;
559
560         new_rules = rte_malloc(NULL,
561                 n_keys * sizeof(int),
562                 RTE_CACHE_LINE_SIZE);
563         if (new_rules == NULL) {
564                 rte_free(rules);
565                 return -1;
566         }
567
568         /* check data integrity and add to rule list */
569         for (i = 0; i < n_keys; i++) {
570                 if (port_ids[i]  >= p->n_ports_out) {
571                         rte_free(rules);
572                         rte_free(new_rules);
573                         return -1;
574                 }
575
576                 if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) {
577                         rte_free(rules);
578                         rte_free(new_rules);
579                         return -1;
580                 }
581
582                 rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]);
583                 new_rules[i] = (rules[i] == NULL);
584                 if (rules[i] == NULL) {
585                         rules[i] = rte_malloc(NULL,
586                                 sizeof(*rules[i]),
587                                 RTE_CACHE_LINE_SIZE);
588
589                         if (rules[i] == NULL) {
590                                 uint32_t j;
591
592                                 for (j = 0; j <= i; j++)
593                                         if (new_rules[j])
594                                                 rte_free(rules[j]);
595
596                                 rte_free(rules);
597                                 rte_free(new_rules);
598                                 return -1;
599                         }
600                 }
601         }
602
603         keys_found = rte_malloc(NULL,
604                 n_keys * sizeof(int),
605                 RTE_CACHE_LINE_SIZE);
606         if (keys_found == NULL) {
607                 uint32_t j;
608
609                 for (j = 0; j < n_keys; j++)
610                         if (new_rules[j])
611                                 rte_free(rules[j]);
612
613                 rte_free(rules);
614                 rte_free(new_rules);
615                 return -1;
616         }
617
618         entries_ptr = rte_malloc(NULL,
619                 n_keys * sizeof(struct rte_pipeline_table_entry *),
620                 RTE_CACHE_LINE_SIZE);
621         if (entries_ptr == NULL) {
622                 uint32_t j;
623
624                 for (j = 0; j < n_keys; j++)
625                         if (new_rules[j])
626                                 rte_free(rules[j]);
627
628                 rte_free(rules);
629                 rte_free(new_rules);
630                 rte_free(keys_found);
631                 return -1;
632         }
633         for (i = 0; i < n_keys; i++) {
634                 entries_ptr[i] = rte_malloc(NULL,
635                         sizeof(struct rte_pipeline_table_entry),
636                         RTE_CACHE_LINE_SIZE);
637
638                 if (entries_ptr[i] == NULL) {
639                         uint32_t j;
640
641                         for (j = 0; j < n_keys; j++)
642                                 if (new_rules[j])
643                                         rte_free(rules[j]);
644
645                         for (j = 0; j <= i; j++)
646                                 rte_free(entries_ptr[j]);
647
648                         rte_free(rules);
649                         rte_free(new_rules);
650                         rte_free(keys_found);
651                         rte_free(entries_ptr);
652                         return -1;
653                 }
654         }
655
656         /* Allocate and write request */
657         req = app_msg_alloc(app);
658         if (req == NULL) {
659                 uint32_t j;
660
661                 for (j = 0; j < n_keys; j++)
662                         if (new_rules[j])
663                                 rte_free(rules[j]);
664
665                 for (j = 0; j < n_keys; j++)
666                         rte_free(entries_ptr[j]);
667
668                 rte_free(rules);
669                 rte_free(new_rules);
670                 rte_free(keys_found);
671                 rte_free(entries_ptr);
672                 return -1;
673         }
674
675         req->type = PIPELINE_MSG_REQ_CUSTOM;
676         req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_BULK;
677
678         req->keys = keys;
679         req->n_keys = n_keys;
680         req->port_ids = port_ids;
681         req->priorities = priorities;
682         req->keys_found = keys_found;
683         req->entries_ptr = entries_ptr;
684
685         /* Send request and wait for response */
686         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
687         if (rsp == NULL) {
688                 uint32_t j;
689
690                 for (j = 0; j < n_keys; j++)
691                         if (new_rules[j])
692                                 rte_free(rules[j]);
693
694                 for (j = 0; j < n_keys; j++)
695                         rte_free(entries_ptr[j]);
696
697                 rte_free(rules);
698                 rte_free(new_rules);
699                 rte_free(keys_found);
700                 rte_free(entries_ptr);
701                 return -1;
702         }
703
704         if (rsp->status) {
705                 for (i = 0; i < n_keys; i++)
706                         if (new_rules[i])
707                                 rte_free(rules[i]);
708
709                 for (i = 0; i < n_keys; i++)
710                         rte_free(entries_ptr[i]);
711
712                 status = -1;
713                 goto cleanup;
714         }
715
716         for (i = 0; i < n_keys; i++) {
717                 if (entries_ptr[i] == NULL ||
718                         ((new_rules[i] == 0) && (keys_found[i] == 0)) ||
719                         ((new_rules[i] == 1) && (keys_found[i] == 1))) {
720                         for (i = 0; i < n_keys; i++)
721                                 if (new_rules[i])
722                                         rte_free(rules[i]);
723
724                         for (i = 0; i < n_keys; i++)
725                                 rte_free(entries_ptr[i]);
726
727                         status = -1;
728                         goto cleanup;
729                 }
730         }
731
732         for (i = 0; i < n_keys; i++) {
733                 memcpy(&rules[i]->key, &keys[i], sizeof(keys[i]));
734                 rules[i]->priority = priorities[i];
735                 rules[i]->port_id = port_ids[i];
736                 rules[i]->entry_ptr = entries_ptr[i];
737
738                 /* Commit rule */
739                 if (new_rules[i]) {
740                         TAILQ_INSERT_TAIL(&p->rules, rules[i], node);
741                         p->n_rules++;
742                 }
743
744                 print_firewall_ipv4_rule(rules[i]);
745         }
746
747 cleanup:
748         app_msg_free(app, rsp);
749         rte_free(rules);
750         rte_free(new_rules);
751         rte_free(keys_found);
752         rte_free(entries_ptr);
753
754         return status;
755 }
756
757 int
758 app_pipeline_firewall_delete_bulk(struct app_params *app,
759         uint32_t pipeline_id,
760         struct pipeline_firewall_key *keys,
761         uint32_t n_keys)
762 {
763         struct app_pipeline_firewall *p;
764         struct pipeline_firewall_del_bulk_msg_req *req;
765         struct pipeline_firewall_del_bulk_msg_rsp *rsp;
766
767         struct app_pipeline_firewall_rule **rules;
768         int *keys_found;
769
770         uint32_t i;
771         int status = 0;
772
773         /* Check input arguments */
774         if (app == NULL)
775                 return -1;
776
777         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
778         if (p == NULL)
779                 return -1;
780
781         rules = rte_malloc(NULL,
782                 n_keys * sizeof(struct app_pipeline_firewall_rule *),
783                 RTE_CACHE_LINE_SIZE);
784         if (rules == NULL)
785                 return -1;
786
787         for (i = 0; i < n_keys; i++) {
788                 if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) {
789                         return -1;
790                 }
791
792                 rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]);
793         }
794
795         keys_found = rte_malloc(NULL,
796                 n_keys * sizeof(int),
797                 RTE_CACHE_LINE_SIZE);
798         if (keys_found == NULL) {
799                 rte_free(rules);
800                 return -1;
801         }
802
803         /* Allocate and write request */
804         req = app_msg_alloc(app);
805         if (req == NULL) {
806                 rte_free(rules);
807                 rte_free(keys_found);
808                 return -1;
809         }
810
811         req->type = PIPELINE_MSG_REQ_CUSTOM;
812         req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_BULK;
813
814         req->keys = keys;
815         req->n_keys = n_keys;
816         req->keys_found = keys_found;
817
818         /* Send request and wait for response */
819         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
820         if (rsp == NULL) {
821                 rte_free(rules);
822                 rte_free(keys_found);
823                 return -1;
824         }
825
826         if (rsp->status) {
827                 status = -1;
828                 goto cleanup;
829         }
830
831         for (i = 0; i < n_keys; i++) {
832                 if (keys_found[i] == 0) {
833                         status = -1;
834                         goto cleanup;
835                 }
836         }
837
838         for (i = 0; i < n_keys; i++) {
839                 TAILQ_REMOVE(&p->rules, rules[i], node);
840                 p->n_rules--;
841                 rte_free(rules[i]);
842         }
843
844 cleanup:
845         app_msg_free(app, rsp);
846         rte_free(rules);
847         rte_free(keys_found);
848
849         return status;
850 }
851
852 int
853 app_pipeline_firewall_add_default_rule(struct app_params *app,
854         uint32_t pipeline_id,
855         uint32_t port_id)
856 {
857         struct app_pipeline_firewall *p;
858         struct pipeline_firewall_add_default_msg_req *req;
859         struct pipeline_firewall_add_default_msg_rsp *rsp;
860
861         /* Check input arguments */
862         if (app == NULL)
863                 return -1;
864
865         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
866         if (p == NULL)
867                 return -1;
868
869         if (port_id >= p->n_ports_out)
870                 return -1;
871
872         /* Allocate and write request */
873         req = app_msg_alloc(app);
874         if (req == NULL)
875                 return -1;
876
877         req->type = PIPELINE_MSG_REQ_CUSTOM;
878         req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT;
879         req->port_id = port_id;
880
881         /* Send request and wait for response */
882         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
883         if (rsp == NULL)
884                 return -1;
885
886         /* Read response and write rule */
887         if (rsp->status || (rsp->entry_ptr == NULL)) {
888                 app_msg_free(app, rsp);
889                 return -1;
890         }
891
892         p->default_rule_port_id = port_id;
893         p->default_rule_entry_ptr = rsp->entry_ptr;
894
895         /* Commit rule */
896         p->default_rule_present = 1;
897
898         /* Free response */
899         app_msg_free(app, rsp);
900
901         return 0;
902 }
903
904 int
905 app_pipeline_firewall_delete_default_rule(struct app_params *app,
906         uint32_t pipeline_id)
907 {
908         struct app_pipeline_firewall *p;
909         struct pipeline_firewall_del_default_msg_req *req;
910         struct pipeline_firewall_del_default_msg_rsp *rsp;
911
912         /* Check input arguments */
913         if (app == NULL)
914                 return -1;
915
916         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_firewall);
917         if (p == NULL)
918                 return -1;
919
920         /* Allocate and write request */
921         req = app_msg_alloc(app);
922         if (req == NULL)
923                 return -1;
924
925         req->type = PIPELINE_MSG_REQ_CUSTOM;
926         req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT;
927
928         /* Send request and wait for response */
929         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
930         if (rsp == NULL)
931                 return -1;
932
933         /* Read response and write rule */
934         if (rsp->status) {
935                 app_msg_free(app, rsp);
936                 return -1;
937         }
938
939         /* Commit rule */
940         p->default_rule_present = 0;
941
942         /* Free response */
943         app_msg_free(app, rsp);
944
945         return 0;
946 }
947
948 /*
949  * firewall
950  *
951  * firewall add:
952  *    p <pipelineid> firewall add priority <priority>
953  *       ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth>
954  *       <sport0> <sport1> <dport0> <dport1> <proto> <protomask>
955  *       port <portid>
956  *       Note: <protomask> is a hex value
957  *
958  *    p <pipelineid> firewall add bulk <file>
959  *
960  * firewall add default:
961  *    p <pipelineid> firewall add default <port ID>
962  *
963  * firewall del:
964  *    p <pipelineid> firewall del
965  *       ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth>
966  *       <sport0> <sport1> <dport0> <dport1> <proto> <protomask>
967  *
968  *    p <pipelineid> firewall del bulk <file>
969  *
970  * firewall del default:
971  *    p <pipelineid> firewall del default
972  *
973  * firewall ls:
974  *    p <pipelineid> firewall ls
975  */
976
977 struct cmd_firewall_result {
978         cmdline_fixed_string_t p_string;
979         uint32_t pipeline_id;
980         cmdline_fixed_string_t firewall_string;
981         cmdline_multi_string_t multi_string;
982 };
983
984 static void cmd_firewall_parsed(void *parsed_result,
985         __attribute__((unused))  struct cmdline *cl,
986         void *data)
987 {
988         struct cmd_firewall_result *params = parsed_result;
989         struct app_params *app = data;
990         int status;
991
992         char *tokens[17];
993         uint32_t n_tokens = RTE_DIM(tokens);
994
995         status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
996         if (status) {
997                 printf(CMD_MSG_TOO_MANY_ARGS, "firewall");
998                 return;
999         }
1000
1001         /* firewall add */
1002         if ((n_tokens >= 2) &&
1003                 (strcmp(tokens[0], "add") == 0) &&
1004                 (strcmp(tokens[1], "priority") == 0)) {
1005                 struct pipeline_firewall_key key;
1006                 uint32_t priority;
1007                 struct in_addr sipaddr;
1008                 uint32_t sipdepth;
1009                 struct in_addr dipaddr;
1010                 uint32_t dipdepth;
1011                 uint16_t sport0;
1012                 uint16_t sport1;
1013                 uint16_t dport0;
1014                 uint16_t dport1;
1015                 uint8_t proto;
1016                 uint8_t protomask;
1017                 uint32_t port_id;
1018
1019                 memset(&key, 0, sizeof(key));
1020
1021                 if (n_tokens != 16) {
1022                         printf(CMD_MSG_MISMATCH_ARGS, "firewall add");
1023                         return;
1024                 }
1025
1026                 if (parser_read_uint32(&priority, tokens[2])) {
1027                         printf(CMD_MSG_INVALID_ARG, "priority");
1028                         return;
1029                 }
1030
1031                 if (strcmp(tokens[3], "ipv4")) {
1032                         printf(CMD_MSG_ARG_NOT_FOUND, "ipv4");
1033                         return;
1034                 }
1035
1036                 if (parse_ipv4_addr(tokens[4], &sipaddr)) {
1037                         printf(CMD_MSG_INVALID_ARG, "sipaddr");
1038                         return;
1039                 }
1040
1041                 if (parser_read_uint32(&sipdepth, tokens[5])) {
1042                         printf(CMD_MSG_INVALID_ARG, "sipdepth");
1043                         return;
1044                 }
1045
1046                 if (parse_ipv4_addr(tokens[6], &dipaddr)) {
1047                         printf(CMD_MSG_INVALID_ARG, "dipaddr");
1048                         return;
1049                 }
1050
1051                 if (parser_read_uint32(&dipdepth, tokens[7])) {
1052                         printf(CMD_MSG_INVALID_ARG, "dipdepth");
1053                         return;
1054                 }
1055
1056                 if (parser_read_uint16(&sport0, tokens[8])) {
1057                         printf(CMD_MSG_INVALID_ARG, "sport0");
1058                         return;
1059                 }
1060
1061                 if (parser_read_uint16(&sport1, tokens[9])) {
1062                         printf(CMD_MSG_INVALID_ARG, "sport1");
1063                         return;
1064                 }
1065
1066                 if (parser_read_uint16(&dport0, tokens[10])) {
1067                         printf(CMD_MSG_INVALID_ARG, "dport0");
1068                         return;
1069                 }
1070
1071                 if (parser_read_uint16(&dport1, tokens[11])) {
1072                         printf(CMD_MSG_INVALID_ARG, "dport1");
1073                         return;
1074                 }
1075
1076                 if (parser_read_uint8(&proto, tokens[12])) {
1077                         printf(CMD_MSG_INVALID_ARG, "proto");
1078                         return;
1079                 }
1080
1081                 if (parser_read_uint8_hex(&protomask, tokens[13])) {
1082                         printf(CMD_MSG_INVALID_ARG, "protomask");
1083                         return;
1084                 }
1085
1086                 if (strcmp(tokens[14], "port")) {
1087                         printf(CMD_MSG_ARG_NOT_FOUND, "port");
1088                         return;
1089                 }
1090
1091                 if (parser_read_uint32(&port_id, tokens[15])) {
1092                         printf(CMD_MSG_INVALID_ARG, "portid");
1093                         return;
1094                 }
1095
1096                 key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
1097                 key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr);
1098                 key.key.ipv4_5tuple.src_ip_mask = sipdepth;
1099                 key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr);
1100                 key.key.ipv4_5tuple.dst_ip_mask = dipdepth;
1101                 key.key.ipv4_5tuple.src_port_from = sport0;
1102                 key.key.ipv4_5tuple.src_port_to = sport1;
1103                 key.key.ipv4_5tuple.dst_port_from = dport0;
1104                 key.key.ipv4_5tuple.dst_port_to = dport1;
1105                 key.key.ipv4_5tuple.proto = proto;
1106                 key.key.ipv4_5tuple.proto_mask = protomask;
1107
1108                 status = app_pipeline_firewall_add_rule(app,
1109                         params->pipeline_id,
1110                         &key,
1111                         priority,
1112                         port_id);
1113                 if (status)
1114                         printf(CMD_MSG_FAIL, "firewall add");
1115
1116                 return;
1117         } /* firewall add */
1118
1119         /* firewall add bulk */
1120         if ((n_tokens >= 2) &&
1121                 (strcmp(tokens[0], "add") == 0) &&
1122                 (strcmp(tokens[1], "bulk") == 0)) {
1123                 struct pipeline_firewall_key *keys;
1124                 uint32_t *priorities, *port_ids, n_keys, line;
1125                 char *filename;
1126
1127                 if (n_tokens != 3) {
1128                         printf(CMD_MSG_MISMATCH_ARGS, "firewall add bulk");
1129                         return;
1130                 }
1131
1132                 filename = tokens[2];
1133
1134                 n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE;
1135                 keys = malloc(n_keys * sizeof(struct pipeline_firewall_key));
1136                 if (keys == NULL) {
1137                         printf(CMD_MSG_OUT_OF_MEMORY);
1138                         return;
1139                 }
1140                 memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key));
1141
1142                 priorities = malloc(n_keys * sizeof(uint32_t));
1143                 if (priorities == NULL) {
1144                         printf(CMD_MSG_OUT_OF_MEMORY);
1145                         free(keys);
1146                         return;
1147                 }
1148
1149                 port_ids = malloc(n_keys * sizeof(uint32_t));
1150                 if (port_ids == NULL) {
1151                         printf(CMD_MSG_OUT_OF_MEMORY);
1152                         free(priorities);
1153                         free(keys);
1154                         return;
1155                 }
1156
1157                 status = app_pipeline_firewall_load_file(filename,
1158                         keys,
1159                         priorities,
1160                         port_ids,
1161                         &n_keys,
1162                         &line);
1163                 if (status != 0) {
1164                         printf(CMD_MSG_FILE_ERR, filename, line);
1165                         free(port_ids);
1166                         free(priorities);
1167                         free(keys);
1168                         return;
1169                 }
1170
1171                 status = app_pipeline_firewall_add_bulk(app,
1172                         params->pipeline_id,
1173                         keys,
1174                         n_keys,
1175                         priorities,
1176                         port_ids);
1177                 if (status)
1178                         printf(CMD_MSG_FAIL, "firewall add bulk");
1179
1180                 free(keys);
1181                 free(priorities);
1182                 free(port_ids);
1183                 return;
1184         } /* firewall add bulk */
1185
1186         /* firewall add default */
1187         if ((n_tokens >= 2) &&
1188                 (strcmp(tokens[0], "add") == 0) &&
1189                 (strcmp(tokens[1], "default") == 0)) {
1190                 uint32_t port_id;
1191
1192                 if (n_tokens != 3) {
1193                         printf(CMD_MSG_MISMATCH_ARGS, "firewall add default");
1194                         return;
1195                 }
1196
1197                 if (parser_read_uint32(&port_id, tokens[2])) {
1198                         printf(CMD_MSG_INVALID_ARG, "portid");
1199                         return;
1200                 }
1201
1202                 status = app_pipeline_firewall_add_default_rule(app,
1203                         params->pipeline_id,
1204                         port_id);
1205                 if (status)
1206                         printf(CMD_MSG_FAIL, "firewall add default");
1207
1208                 return;
1209         } /* firewall add default */
1210
1211         /* firewall del */
1212         if ((n_tokens >= 2) &&
1213                 (strcmp(tokens[0], "del") == 0) &&
1214                 (strcmp(tokens[1], "ipv4") == 0)) {
1215                 struct pipeline_firewall_key key;
1216                 struct in_addr sipaddr;
1217                 uint32_t sipdepth;
1218                 struct in_addr dipaddr;
1219                 uint32_t dipdepth;
1220                 uint16_t sport0;
1221                 uint16_t sport1;
1222                 uint16_t dport0;
1223                 uint16_t dport1;
1224                 uint8_t proto;
1225                 uint8_t protomask;
1226
1227                 memset(&key, 0, sizeof(key));
1228
1229                 if (n_tokens != 12) {
1230                         printf(CMD_MSG_MISMATCH_ARGS, "firewall del");
1231                         return;
1232                 }
1233
1234                 if (parse_ipv4_addr(tokens[2], &sipaddr)) {
1235                         printf(CMD_MSG_INVALID_ARG, "sipaddr");
1236                         return;
1237                 }
1238
1239                 if (parser_read_uint32(&sipdepth, tokens[3])) {
1240                         printf(CMD_MSG_INVALID_ARG, "sipdepth");
1241                         return;
1242                 }
1243
1244                 if (parse_ipv4_addr(tokens[4], &dipaddr)) {
1245                         printf(CMD_MSG_INVALID_ARG, "dipaddr");
1246                         return;
1247                 }
1248
1249                 if (parser_read_uint32(&dipdepth, tokens[5])) {
1250                         printf(CMD_MSG_INVALID_ARG, "dipdepth");
1251                         return;
1252                 }
1253
1254                 if (parser_read_uint16(&sport0, tokens[6])) {
1255                         printf(CMD_MSG_INVALID_ARG, "sport0");
1256                         return;
1257                 }
1258
1259                 if (parser_read_uint16(&sport1, tokens[7])) {
1260                         printf(CMD_MSG_INVALID_ARG, "sport1");
1261                         return;
1262                 }
1263
1264                 if (parser_read_uint16(&dport0, tokens[8])) {
1265                         printf(CMD_MSG_INVALID_ARG, "dport0");
1266                         return;
1267                 }
1268
1269                 if (parser_read_uint16(&dport1, tokens[9])) {
1270                         printf(CMD_MSG_INVALID_ARG, "dport1");
1271                         return;
1272                 }
1273
1274                 if (parser_read_uint8(&proto, tokens[10])) {
1275                         printf(CMD_MSG_INVALID_ARG, "proto");
1276                         return;
1277                 }
1278
1279                 if (parser_read_uint8_hex(&protomask, tokens[11])) {
1280                         printf(CMD_MSG_INVALID_ARG, "protomask");
1281                         return;
1282                 }
1283
1284                 key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
1285                 key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr);
1286                 key.key.ipv4_5tuple.src_ip_mask = sipdepth;
1287                 key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr);
1288                 key.key.ipv4_5tuple.dst_ip_mask = dipdepth;
1289                 key.key.ipv4_5tuple.src_port_from = sport0;
1290                 key.key.ipv4_5tuple.src_port_to = sport1;
1291                 key.key.ipv4_5tuple.dst_port_from = dport0;
1292                 key.key.ipv4_5tuple.dst_port_to = dport1;
1293                 key.key.ipv4_5tuple.proto = proto;
1294                 key.key.ipv4_5tuple.proto_mask = protomask;
1295
1296                 status = app_pipeline_firewall_delete_rule(app,
1297                         params->pipeline_id,
1298                         &key);
1299                 if (status)
1300                         printf(CMD_MSG_FAIL, "firewall del");
1301
1302                 return;
1303         } /* firewall del */
1304
1305         /* firewall del bulk */
1306         if ((n_tokens >= 2) &&
1307                 (strcmp(tokens[0], "del") == 0) &&
1308                 (strcmp(tokens[1], "bulk") == 0)) {
1309                 struct pipeline_firewall_key *keys;
1310                 uint32_t *priorities, *port_ids, n_keys, line;
1311                 char *filename;
1312
1313                 if (n_tokens != 3) {
1314                         printf(CMD_MSG_MISMATCH_ARGS, "firewall del bulk");
1315                         return;
1316                 }
1317
1318                 filename = tokens[2];
1319
1320                 n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE;
1321                 keys = malloc(n_keys * sizeof(struct pipeline_firewall_key));
1322                 if (keys == NULL) {
1323                         printf(CMD_MSG_OUT_OF_MEMORY);
1324                         return;
1325                 }
1326                 memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key));
1327
1328                 priorities = malloc(n_keys * sizeof(uint32_t));
1329                 if (priorities == NULL) {
1330                         printf(CMD_MSG_OUT_OF_MEMORY);
1331                         free(keys);
1332                         return;
1333                 }
1334
1335                 port_ids = malloc(n_keys * sizeof(uint32_t));
1336                 if (port_ids == NULL) {
1337                         printf(CMD_MSG_OUT_OF_MEMORY);
1338                         free(priorities);
1339                         free(keys);
1340                         return;
1341                 }
1342
1343                 status = app_pipeline_firewall_load_file(filename,
1344                         keys,
1345                         priorities,
1346                         port_ids,
1347                         &n_keys,
1348                         &line);
1349                 if (status != 0) {
1350                         printf(CMD_MSG_FILE_ERR, filename, line);
1351                         free(port_ids);
1352                         free(priorities);
1353                         free(keys);
1354                         return;
1355                 }
1356
1357                 status = app_pipeline_firewall_delete_bulk(app,
1358                         params->pipeline_id,
1359                         keys,
1360                         n_keys);
1361                 if (status)
1362                         printf(CMD_MSG_FAIL, "firewall del bulk");
1363
1364                 free(port_ids);
1365                 free(priorities);
1366                 free(keys);
1367                 return;
1368         } /* firewall del bulk */
1369
1370         /* firewall del default */
1371         if ((n_tokens >= 2) &&
1372                 (strcmp(tokens[0], "del") == 0) &&
1373                 (strcmp(tokens[1], "default") == 0)) {
1374                 if (n_tokens != 2) {
1375                         printf(CMD_MSG_MISMATCH_ARGS, "firewall del default");
1376                         return;
1377                 }
1378
1379                 status = app_pipeline_firewall_delete_default_rule(app,
1380                         params->pipeline_id);
1381                 if (status)
1382                         printf(CMD_MSG_FAIL, "firewall del default");
1383
1384                 return;
1385
1386         } /* firewall del default */
1387
1388         /* firewall ls */
1389         if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1390                 if (n_tokens != 1) {
1391                         printf(CMD_MSG_MISMATCH_ARGS, "firewall ls");
1392                         return;
1393                 }
1394
1395                 status = app_pipeline_firewall_ls(app, params->pipeline_id);
1396                 if (status)
1397                         printf(CMD_MSG_FAIL, "firewall ls");
1398
1399                 return;
1400         } /* firewall ls */
1401
1402         printf(CMD_MSG_MISMATCH_ARGS, "firewall");
1403 }
1404
1405 static cmdline_parse_token_string_t cmd_firewall_p_string =
1406         TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, p_string, "p");
1407
1408 static cmdline_parse_token_num_t cmd_firewall_pipeline_id =
1409         TOKEN_NUM_INITIALIZER(struct cmd_firewall_result, pipeline_id, UINT32);
1410
1411 static cmdline_parse_token_string_t cmd_firewall_firewall_string =
1412         TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, firewall_string,
1413         "firewall");
1414
1415 static cmdline_parse_token_string_t cmd_firewall_multi_string =
1416         TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, multi_string,
1417         TOKEN_STRING_MULTI);
1418
1419 static cmdline_parse_inst_t cmd_firewall = {
1420         .f = cmd_firewall_parsed,
1421         .data = NULL,
1422         .help_str =     "firewall add / add bulk / add default / del / del bulk"
1423                 " / del default / ls",
1424         .tokens = {
1425                 (void *) &cmd_firewall_p_string,
1426                 (void *) &cmd_firewall_pipeline_id,
1427                 (void *) &cmd_firewall_firewall_string,
1428                 (void *) &cmd_firewall_multi_string,
1429                 NULL,
1430         },
1431 };
1432
1433 static cmdline_parse_ctx_t pipeline_cmds[] = {
1434         (cmdline_parse_inst_t *) &cmd_firewall,
1435         NULL,
1436 };
1437
1438 static struct pipeline_fe_ops pipeline_firewall_fe_ops = {
1439         .f_init = app_pipeline_firewall_init,
1440         .f_post_init = NULL,
1441         .f_free = app_pipeline_firewall_free,
1442         .f_track = app_pipeline_track_default,
1443         .cmds = pipeline_cmds,
1444 };
1445
1446 struct pipeline_type pipeline_firewall = {
1447         .name = "FIREWALL",
1448         .be_ops = &pipeline_firewall_be_ops,
1449         .fe_ops = &pipeline_firewall_fe_ops,
1450 };