Imported Upstream version 16.07-rc1
[deb_dpdk.git] / examples / ip_pipeline / pipeline / pipeline_firewall_be.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 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 <string.h>
35
36 #include <rte_common.h>
37 #include <rte_malloc.h>
38 #include <rte_ether.h>
39 #include <rte_ip.h>
40 #include <rte_tcp.h>
41 #include <rte_byteorder.h>
42 #include <rte_table_acl.h>
43
44 #include "pipeline_firewall_be.h"
45 #include "parser.h"
46
47 struct pipeline_firewall {
48         struct pipeline p;
49         pipeline_msg_req_handler custom_handlers[PIPELINE_FIREWALL_MSG_REQS];
50
51         uint32_t n_rules;
52         uint32_t n_rule_fields;
53         struct rte_acl_field_def *field_format;
54         uint32_t field_format_size;
55 } __rte_cache_aligned;
56
57 static void *
58 pipeline_firewall_msg_req_custom_handler(struct pipeline *p, void *msg);
59
60 static pipeline_msg_req_handler handlers[] = {
61         [PIPELINE_MSG_REQ_PING] =
62                 pipeline_msg_req_ping_handler,
63         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
64                 pipeline_msg_req_stats_port_in_handler,
65         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
66                 pipeline_msg_req_stats_port_out_handler,
67         [PIPELINE_MSG_REQ_STATS_TABLE] =
68                 pipeline_msg_req_stats_table_handler,
69         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
70                 pipeline_msg_req_port_in_enable_handler,
71         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
72                 pipeline_msg_req_port_in_disable_handler,
73         [PIPELINE_MSG_REQ_CUSTOM] =
74                 pipeline_firewall_msg_req_custom_handler,
75 };
76
77 static void *
78 pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg);
79
80 static void *
81 pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg);
82
83 static void *
84 pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg);
85
86 static void *
87 pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg);
88
89 static void *
90 pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg);
91
92 static void *
93 pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg);
94
95 static pipeline_msg_req_handler custom_handlers[] = {
96         [PIPELINE_FIREWALL_MSG_REQ_ADD] =
97                 pipeline_firewall_msg_req_add_handler,
98         [PIPELINE_FIREWALL_MSG_REQ_DEL] =
99                 pipeline_firewall_msg_req_del_handler,
100         [PIPELINE_FIREWALL_MSG_REQ_ADD_BULK] =
101                 pipeline_firewall_msg_req_add_bulk_handler,
102         [PIPELINE_FIREWALL_MSG_REQ_DEL_BULK] =
103                 pipeline_firewall_msg_req_del_bulk_handler,
104         [PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] =
105                 pipeline_firewall_msg_req_add_default_handler,
106         [PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] =
107                 pipeline_firewall_msg_req_del_default_handler,
108 };
109
110 /*
111  * Firewall table
112  */
113 struct firewall_table_entry {
114         struct rte_pipeline_table_entry head;
115 };
116
117 static struct rte_acl_field_def field_format_ipv4[] = {
118         /* Protocol */
119         [0] = {
120                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
121                 .size = sizeof(uint8_t),
122                 .field_index = 0,
123                 .input_index = 0,
124                 .offset = sizeof(struct ether_hdr) +
125                         offsetof(struct ipv4_hdr, next_proto_id),
126         },
127
128         /* Source IP address (IPv4) */
129         [1] = {
130                 .type = RTE_ACL_FIELD_TYPE_MASK,
131                 .size = sizeof(uint32_t),
132                 .field_index = 1,
133                 .input_index = 1,
134                 .offset = sizeof(struct ether_hdr) +
135                         offsetof(struct ipv4_hdr, src_addr),
136         },
137
138         /* Destination IP address (IPv4) */
139         [2] = {
140                 .type = RTE_ACL_FIELD_TYPE_MASK,
141                 .size = sizeof(uint32_t),
142                 .field_index = 2,
143                 .input_index = 2,
144                 .offset = sizeof(struct ether_hdr) +
145                         offsetof(struct ipv4_hdr, dst_addr),
146         },
147
148         /* Source Port */
149         [3] = {
150                 .type = RTE_ACL_FIELD_TYPE_RANGE,
151                 .size = sizeof(uint16_t),
152                 .field_index = 3,
153                 .input_index = 3,
154                 .offset = sizeof(struct ether_hdr) +
155                         sizeof(struct ipv4_hdr) +
156                         offsetof(struct tcp_hdr, src_port),
157         },
158
159         /* Destination Port */
160         [4] = {
161                 .type = RTE_ACL_FIELD_TYPE_RANGE,
162                 .size = sizeof(uint16_t),
163                 .field_index = 4,
164                 .input_index = 4,
165                 .offset = sizeof(struct ether_hdr) +
166                         sizeof(struct ipv4_hdr) +
167                         offsetof(struct tcp_hdr, dst_port),
168         },
169 };
170
171 #define SIZEOF_VLAN_HDR                          4
172
173 static struct rte_acl_field_def field_format_vlan_ipv4[] = {
174         /* Protocol */
175         [0] = {
176                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
177                 .size = sizeof(uint8_t),
178                 .field_index = 0,
179                 .input_index = 0,
180                 .offset = sizeof(struct ether_hdr) +
181                         SIZEOF_VLAN_HDR +
182                         offsetof(struct ipv4_hdr, next_proto_id),
183         },
184
185         /* Source IP address (IPv4) */
186         [1] = {
187                 .type = RTE_ACL_FIELD_TYPE_MASK,
188                 .size = sizeof(uint32_t),
189                 .field_index = 1,
190                 .input_index = 1,
191                 .offset = sizeof(struct ether_hdr) +
192                         SIZEOF_VLAN_HDR +
193                         offsetof(struct ipv4_hdr, src_addr),
194         },
195
196         /* Destination IP address (IPv4) */
197         [2] = {
198                 .type = RTE_ACL_FIELD_TYPE_MASK,
199                 .size = sizeof(uint32_t),
200                 .field_index = 2,
201                 .input_index = 2,
202                 .offset = sizeof(struct ether_hdr) +
203                         SIZEOF_VLAN_HDR +
204                         offsetof(struct ipv4_hdr, dst_addr),
205         },
206
207         /* Source Port */
208         [3] = {
209                 .type = RTE_ACL_FIELD_TYPE_RANGE,
210                 .size = sizeof(uint16_t),
211                 .field_index = 3,
212                 .input_index = 3,
213                 .offset = sizeof(struct ether_hdr) +
214                         SIZEOF_VLAN_HDR +
215                         sizeof(struct ipv4_hdr) +
216                         offsetof(struct tcp_hdr, src_port),
217         },
218
219         /* Destination Port */
220         [4] = {
221                 .type = RTE_ACL_FIELD_TYPE_RANGE,
222                 .size = sizeof(uint16_t),
223                 .field_index = 4,
224                 .input_index = 4,
225                 .offset = sizeof(struct ether_hdr) +
226                         SIZEOF_VLAN_HDR +
227                         sizeof(struct ipv4_hdr) +
228                         offsetof(struct tcp_hdr, dst_port),
229         },
230 };
231
232 #define SIZEOF_QINQ_HEADER                       8
233
234 static struct rte_acl_field_def field_format_qinq_ipv4[] = {
235         /* Protocol */
236         [0] = {
237                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
238                 .size = sizeof(uint8_t),
239                 .field_index = 0,
240                 .input_index = 0,
241                 .offset = sizeof(struct ether_hdr) +
242                         SIZEOF_QINQ_HEADER +
243                         offsetof(struct ipv4_hdr, next_proto_id),
244         },
245
246         /* Source IP address (IPv4) */
247         [1] = {
248                 .type = RTE_ACL_FIELD_TYPE_MASK,
249                 .size = sizeof(uint32_t),
250                 .field_index = 1,
251                 .input_index = 1,
252                 .offset = sizeof(struct ether_hdr) +
253                         SIZEOF_QINQ_HEADER +
254                         offsetof(struct ipv4_hdr, src_addr),
255         },
256
257         /* Destination IP address (IPv4) */
258         [2] = {
259                 .type = RTE_ACL_FIELD_TYPE_MASK,
260                 .size = sizeof(uint32_t),
261                 .field_index = 2,
262                 .input_index = 2,
263                 .offset = sizeof(struct ether_hdr) +
264                         SIZEOF_QINQ_HEADER +
265                         offsetof(struct ipv4_hdr, dst_addr),
266         },
267
268         /* Source Port */
269         [3] = {
270                 .type = RTE_ACL_FIELD_TYPE_RANGE,
271                 .size = sizeof(uint16_t),
272                 .field_index = 3,
273                 .input_index = 3,
274                 .offset = sizeof(struct ether_hdr) +
275                         SIZEOF_QINQ_HEADER +
276                         sizeof(struct ipv4_hdr) +
277                         offsetof(struct tcp_hdr, src_port),
278         },
279
280         /* Destination Port */
281         [4] = {
282                 .type = RTE_ACL_FIELD_TYPE_RANGE,
283                 .size = sizeof(uint16_t),
284                 .field_index = 4,
285                 .input_index = 4,
286                 .offset = sizeof(struct ether_hdr) +
287                         SIZEOF_QINQ_HEADER +
288                         sizeof(struct ipv4_hdr) +
289                         offsetof(struct tcp_hdr, dst_port),
290         },
291 };
292
293 static int
294 pipeline_firewall_parse_args(struct pipeline_firewall *p,
295         struct pipeline_params *params)
296 {
297         uint32_t n_rules_present = 0;
298         uint32_t pkt_type_present = 0;
299         uint32_t i;
300
301         /* defaults */
302         p->n_rules = 4 * 1024;
303         p->n_rule_fields = RTE_DIM(field_format_ipv4);
304         p->field_format = field_format_ipv4;
305         p->field_format_size = sizeof(field_format_ipv4);
306
307         for (i = 0; i < params->n_args; i++) {
308                 char *arg_name = params->args_name[i];
309                 char *arg_value = params->args_value[i];
310
311                 if (strcmp(arg_name, "n_rules") == 0) {
312                         int status;
313
314                         PIPELINE_PARSE_ERR_DUPLICATE(
315                                 n_rules_present == 0, params->name,
316                                 arg_name);
317                         n_rules_present = 1;
318
319                         status = parser_read_uint32(&p->n_rules,
320                                 arg_value);
321                         PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
322                                 params->name, arg_name, arg_value);
323                         PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
324                                 params->name, arg_name, arg_value);
325                         continue;
326                 }
327
328                 if (strcmp(arg_name, "pkt_type") == 0) {
329                         PIPELINE_PARSE_ERR_DUPLICATE(
330                                 pkt_type_present == 0, params->name,
331                                 arg_name);
332                         pkt_type_present = 1;
333
334                         /* ipv4 */
335                         if (strcmp(arg_value, "ipv4") == 0) {
336                                 p->n_rule_fields = RTE_DIM(field_format_ipv4);
337                                 p->field_format = field_format_ipv4;
338                                 p->field_format_size =
339                                         sizeof(field_format_ipv4);
340                                 continue;
341                         }
342
343                         /* vlan_ipv4 */
344                         if (strcmp(arg_value, "vlan_ipv4") == 0) {
345                                 p->n_rule_fields =
346                                         RTE_DIM(field_format_vlan_ipv4);
347                                 p->field_format = field_format_vlan_ipv4;
348                                 p->field_format_size =
349                                         sizeof(field_format_vlan_ipv4);
350                                 continue;
351                         }
352
353                         /* qinq_ipv4 */
354                         if (strcmp(arg_value, "qinq_ipv4") == 0) {
355                                 p->n_rule_fields =
356                                         RTE_DIM(field_format_qinq_ipv4);
357                                 p->field_format = field_format_qinq_ipv4;
358                                 p->field_format_size =
359                                         sizeof(field_format_qinq_ipv4);
360                                 continue;
361                         }
362
363                         /* other */
364                         PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
365                                 arg_name, arg_value);
366                 }
367
368                 /* other */
369                 PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);
370         }
371
372         return 0;
373 }
374
375 static void *
376 pipeline_firewall_init(struct pipeline_params *params,
377         __rte_unused void *arg)
378 {
379         struct pipeline *p;
380         struct pipeline_firewall *p_fw;
381         uint32_t size, i;
382
383         /* Check input arguments */
384         if ((params == NULL) ||
385                 (params->n_ports_in == 0) ||
386                 (params->n_ports_out == 0))
387                 return NULL;
388
389         /* Memory allocation */
390         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_firewall));
391         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
392         p_fw = (struct pipeline_firewall *) p;
393         if (p == NULL)
394                 return NULL;
395
396         strcpy(p->name, params->name);
397         p->log_level = params->log_level;
398
399         PLOG(p, HIGH, "Firewall");
400
401         /* Parse arguments */
402         if (pipeline_firewall_parse_args(p_fw, params))
403                 return NULL;
404
405         /* Pipeline */
406         {
407                 struct rte_pipeline_params pipeline_params = {
408                         .name = params->name,
409                         .socket_id = params->socket_id,
410                         .offset_port_id = 0,
411                 };
412
413                 p->p = rte_pipeline_create(&pipeline_params);
414                 if (p->p == NULL) {
415                         rte_free(p);
416                         return NULL;
417                 }
418         }
419
420         /* Input ports */
421         p->n_ports_in = params->n_ports_in;
422         for (i = 0; i < p->n_ports_in; i++) {
423                 struct rte_pipeline_port_in_params port_params = {
424                         .ops = pipeline_port_in_params_get_ops(
425                                 &params->port_in[i]),
426                         .arg_create = pipeline_port_in_params_convert(
427                                 &params->port_in[i]),
428                         .f_action = NULL,
429                         .arg_ah = NULL,
430                         .burst_size = params->port_in[i].burst_size,
431                 };
432
433                 int status = rte_pipeline_port_in_create(p->p,
434                         &port_params,
435                         &p->port_in_id[i]);
436
437                 if (status) {
438                         rte_pipeline_free(p->p);
439                         rte_free(p);
440                         return NULL;
441                 }
442         }
443
444         /* Output ports */
445         p->n_ports_out = params->n_ports_out;
446         for (i = 0; i < p->n_ports_out; i++) {
447                 struct rte_pipeline_port_out_params port_params = {
448                         .ops = pipeline_port_out_params_get_ops(
449                                 &params->port_out[i]),
450                         .arg_create = pipeline_port_out_params_convert(
451                                 &params->port_out[i]),
452                         .f_action = NULL,
453                         .arg_ah = NULL,
454                 };
455
456                 int status = rte_pipeline_port_out_create(p->p,
457                         &port_params,
458                         &p->port_out_id[i]);
459
460                 if (status) {
461                         rte_pipeline_free(p->p);
462                         rte_free(p);
463                         return NULL;
464                 }
465         }
466
467         /* Tables */
468         p->n_tables = 1;
469         {
470                 struct rte_table_acl_params table_acl_params = {
471                         .name = params->name,
472                         .n_rules = p_fw->n_rules,
473                         .n_rule_fields = p_fw->n_rule_fields,
474                 };
475
476                 struct rte_pipeline_table_params table_params = {
477                                 .ops = &rte_table_acl_ops,
478                                 .arg_create = &table_acl_params,
479                                 .f_action_hit = NULL,
480                                 .f_action_miss = NULL,
481                                 .arg_ah = NULL,
482                                 .action_data_size =
483                                         sizeof(struct firewall_table_entry) -
484                                         sizeof(struct rte_pipeline_table_entry),
485                         };
486
487                 int status;
488
489                 memcpy(table_acl_params.field_format,
490                         p_fw->field_format,
491                         p_fw->field_format_size);
492
493                 status = rte_pipeline_table_create(p->p,
494                         &table_params,
495                         &p->table_id[0]);
496
497                 if (status) {
498                         rte_pipeline_free(p->p);
499                         rte_free(p);
500                         return NULL;
501                 }
502         }
503
504         /* Connecting input ports to tables */
505         for (i = 0; i < p->n_ports_in; i++) {
506                 int status = rte_pipeline_port_in_connect_to_table(p->p,
507                         p->port_in_id[i],
508                         p->table_id[0]);
509
510                 if (status) {
511                         rte_pipeline_free(p->p);
512                         rte_free(p);
513                         return NULL;
514                 }
515         }
516
517         /* Enable input ports */
518         for (i = 0; i < p->n_ports_in; i++) {
519                 int status = rte_pipeline_port_in_enable(p->p,
520                         p->port_in_id[i]);
521
522                 if (status) {
523                         rte_pipeline_free(p->p);
524                         rte_free(p);
525                         return NULL;
526                 }
527         }
528
529         /* Check pipeline consistency */
530         if (rte_pipeline_check(p->p) < 0) {
531                 rte_pipeline_free(p->p);
532                 rte_free(p);
533                 return NULL;
534         }
535
536         /* Message queues */
537         p->n_msgq = params->n_msgq;
538         for (i = 0; i < p->n_msgq; i++)
539                 p->msgq_in[i] = params->msgq_in[i];
540         for (i = 0; i < p->n_msgq; i++)
541                 p->msgq_out[i] = params->msgq_out[i];
542
543         /* Message handlers */
544         memcpy(p->handlers, handlers, sizeof(p->handlers));
545         memcpy(p_fw->custom_handlers,
546                 custom_handlers,
547                 sizeof(p_fw->custom_handlers));
548
549         return p;
550 }
551
552 static int
553 pipeline_firewall_free(void *pipeline)
554 {
555         struct pipeline *p = (struct pipeline *) pipeline;
556
557         /* Check input arguments */
558         if (p == NULL)
559                 return -1;
560
561         /* Free resources */
562         rte_pipeline_free(p->p);
563         rte_free(p);
564         return 0;
565 }
566
567 static int
568 pipeline_firewall_timer(void *pipeline)
569 {
570         struct pipeline *p = (struct pipeline *) pipeline;
571
572         pipeline_msg_req_handle(p);
573         rte_pipeline_flush(p->p);
574
575         return 0;
576 }
577
578 void *
579 pipeline_firewall_msg_req_custom_handler(struct pipeline *p,
580         void *msg)
581 {
582         struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p;
583         struct pipeline_custom_msg_req *req = msg;
584         pipeline_msg_req_handler f_handle;
585
586         f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS) ?
587                 p_fw->custom_handlers[req->subtype] :
588                 pipeline_msg_req_invalid_handler;
589
590         if (f_handle == NULL)
591                 f_handle = pipeline_msg_req_invalid_handler;
592
593         return f_handle(p, req);
594 }
595
596 void *
597 pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg)
598 {
599         struct pipeline_firewall_add_msg_req *req = msg;
600         struct pipeline_firewall_add_msg_rsp *rsp = msg;
601
602         struct rte_table_acl_rule_add_params params;
603         struct firewall_table_entry entry = {
604                 .head = {
605                         .action = RTE_PIPELINE_ACTION_PORT,
606                         {.port_id = p->port_out_id[req->port_id]},
607                 },
608         };
609
610         memset(&params, 0, sizeof(params));
611
612         switch (req->key.type) {
613         case PIPELINE_FIREWALL_IPV4_5TUPLE:
614                 params.priority = req->priority;
615                 params.field_value[0].value.u8 =
616                         req->key.key.ipv4_5tuple.proto;
617                 params.field_value[0].mask_range.u8 =
618                         req->key.key.ipv4_5tuple.proto_mask;
619                 params.field_value[1].value.u32 =
620                         req->key.key.ipv4_5tuple.src_ip;
621                 params.field_value[1].mask_range.u32 =
622                         req->key.key.ipv4_5tuple.src_ip_mask;
623                 params.field_value[2].value.u32 =
624                         req->key.key.ipv4_5tuple.dst_ip;
625                 params.field_value[2].mask_range.u32 =
626                         req->key.key.ipv4_5tuple.dst_ip_mask;
627                 params.field_value[3].value.u16 =
628                         req->key.key.ipv4_5tuple.src_port_from;
629                 params.field_value[3].mask_range.u16 =
630                         req->key.key.ipv4_5tuple.src_port_to;
631                 params.field_value[4].value.u16 =
632                         req->key.key.ipv4_5tuple.dst_port_from;
633                 params.field_value[4].mask_range.u16 =
634                         req->key.key.ipv4_5tuple.dst_port_to;
635                 break;
636
637         default:
638                 rsp->status = -1; /* Error */
639                 return rsp;
640         }
641
642         rsp->status = rte_pipeline_table_entry_add(p->p,
643                 p->table_id[0],
644                 &params,
645                 (struct rte_pipeline_table_entry *) &entry,
646                 &rsp->key_found,
647                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
648
649         return rsp;
650 }
651
652 void *
653 pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg)
654 {
655         struct pipeline_firewall_del_msg_req *req = msg;
656         struct pipeline_firewall_del_msg_rsp *rsp = msg;
657
658         struct rte_table_acl_rule_delete_params params;
659
660         memset(&params, 0, sizeof(params));
661
662         switch (req->key.type) {
663         case PIPELINE_FIREWALL_IPV4_5TUPLE:
664                 params.field_value[0].value.u8 =
665                         req->key.key.ipv4_5tuple.proto;
666                 params.field_value[0].mask_range.u8 =
667                         req->key.key.ipv4_5tuple.proto_mask;
668                 params.field_value[1].value.u32 =
669                         req->key.key.ipv4_5tuple.src_ip;
670                 params.field_value[1].mask_range.u32 =
671                         req->key.key.ipv4_5tuple.src_ip_mask;
672                 params.field_value[2].value.u32 =
673                         req->key.key.ipv4_5tuple.dst_ip;
674                 params.field_value[2].mask_range.u32 =
675                         req->key.key.ipv4_5tuple.dst_ip_mask;
676                 params.field_value[3].value.u16 =
677                         req->key.key.ipv4_5tuple.src_port_from;
678                 params.field_value[3].mask_range.u16 =
679                         req->key.key.ipv4_5tuple.src_port_to;
680                 params.field_value[4].value.u16 =
681                         req->key.key.ipv4_5tuple.dst_port_from;
682                 params.field_value[4].mask_range.u16 =
683                         req->key.key.ipv4_5tuple.dst_port_to;
684                 break;
685
686         default:
687                 rsp->status = -1; /* Error */
688                 return rsp;
689         }
690
691         rsp->status = rte_pipeline_table_entry_delete(p->p,
692                 p->table_id[0],
693                 &params,
694                 &rsp->key_found,
695                 NULL);
696
697         return rsp;
698 }
699
700 static void *
701 pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
702 {
703         struct pipeline_firewall_add_bulk_msg_req *req = msg;
704         struct pipeline_firewall_add_bulk_msg_rsp *rsp = msg;
705
706         struct rte_table_acl_rule_add_params *params[req->n_keys];
707         struct firewall_table_entry *entries[req->n_keys];
708
709         uint32_t i, n_keys;
710
711         n_keys = req->n_keys;
712
713         for (i = 0; i < n_keys; i++) {
714                 entries[i] = rte_zmalloc(NULL,
715                                 sizeof(struct firewall_table_entry),
716                                 RTE_CACHE_LINE_SIZE);
717                 if (entries[i] == NULL) {
718                         rsp->status = -1;
719                         return rsp;
720                 }
721
722                 params[i] = rte_zmalloc(NULL,
723                                 sizeof(struct rte_table_acl_rule_add_params),
724                                 RTE_CACHE_LINE_SIZE);
725                 if (params[i] == NULL) {
726                         rsp->status = -1;
727                         return rsp;
728                 }
729
730                 entries[i]->head.action = RTE_PIPELINE_ACTION_PORT;
731                 entries[i]->head.port_id = p->port_out_id[req->port_ids[i]];
732
733                 switch (req->keys[i].type) {
734                 case PIPELINE_FIREWALL_IPV4_5TUPLE:
735                         params[i]->priority = req->priorities[i];
736                         params[i]->field_value[0].value.u8 =
737                                 req->keys[i].key.ipv4_5tuple.proto;
738                         params[i]->field_value[0].mask_range.u8 =
739                                 req->keys[i].key.ipv4_5tuple.proto_mask;
740                         params[i]->field_value[1].value.u32 =
741                                 req->keys[i].key.ipv4_5tuple.src_ip;
742                         params[i]->field_value[1].mask_range.u32 =
743                                 req->keys[i].key.ipv4_5tuple.src_ip_mask;
744                         params[i]->field_value[2].value.u32 =
745                                 req->keys[i].key.ipv4_5tuple.dst_ip;
746                         params[i]->field_value[2].mask_range.u32 =
747                                 req->keys[i].key.ipv4_5tuple.dst_ip_mask;
748                         params[i]->field_value[3].value.u16 =
749                                 req->keys[i].key.ipv4_5tuple.src_port_from;
750                         params[i]->field_value[3].mask_range.u16 =
751                                 req->keys[i].key.ipv4_5tuple.src_port_to;
752                         params[i]->field_value[4].value.u16 =
753                                 req->keys[i].key.ipv4_5tuple.dst_port_from;
754                         params[i]->field_value[4].mask_range.u16 =
755                                 req->keys[i].key.ipv4_5tuple.dst_port_to;
756                         break;
757
758                 default:
759                         rsp->status = -1; /* Error */
760
761                         for (i = 0; i < n_keys; i++) {
762                                 rte_free(entries[i]);
763                                 rte_free(params[i]);
764                         }
765
766                         return rsp;
767                 }
768         }
769
770         rsp->status = rte_pipeline_table_entry_add_bulk(p->p, p->table_id[0],
771                         (void *)params, (struct rte_pipeline_table_entry **)entries,
772                         n_keys, req->keys_found,
773                         (struct rte_pipeline_table_entry **)req->entries_ptr);
774
775         for (i = 0; i < n_keys; i++) {
776                 rte_free(entries[i]);
777                 rte_free(params[i]);
778         }
779
780         return rsp;
781 }
782
783 static void *
784 pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg)
785 {
786         struct pipeline_firewall_del_bulk_msg_req *req = msg;
787         struct pipeline_firewall_del_bulk_msg_rsp *rsp = msg;
788
789         struct rte_table_acl_rule_delete_params *params[req->n_keys];
790
791         uint32_t i, n_keys;
792
793         n_keys = req->n_keys;
794
795         for (i = 0; i < n_keys; i++) {
796                 params[i] = rte_zmalloc(NULL,
797                                 sizeof(struct rte_table_acl_rule_delete_params),
798                                 RTE_CACHE_LINE_SIZE);
799                 if (params[i] == NULL) {
800                         rsp->status = -1;
801                         return rsp;
802                 }
803
804                 switch (req->keys[i].type) {
805                 case PIPELINE_FIREWALL_IPV4_5TUPLE:
806                         params[i]->field_value[0].value.u8 =
807                                 req->keys[i].key.ipv4_5tuple.proto;
808                         params[i]->field_value[0].mask_range.u8 =
809                                 req->keys[i].key.ipv4_5tuple.proto_mask;
810                         params[i]->field_value[1].value.u32 =
811                                 req->keys[i].key.ipv4_5tuple.src_ip;
812                         params[i]->field_value[1].mask_range.u32 =
813                                 req->keys[i].key.ipv4_5tuple.src_ip_mask;
814                         params[i]->field_value[2].value.u32 =
815                                 req->keys[i].key.ipv4_5tuple.dst_ip;
816                         params[i]->field_value[2].mask_range.u32 =
817                                 req->keys[i].key.ipv4_5tuple.dst_ip_mask;
818                         params[i]->field_value[3].value.u16 =
819                                 req->keys[i].key.ipv4_5tuple.src_port_from;
820                         params[i]->field_value[3].mask_range.u16 =
821                                 req->keys[i].key.ipv4_5tuple.src_port_to;
822                         params[i]->field_value[4].value.u16 =
823                                 req->keys[i].key.ipv4_5tuple.dst_port_from;
824                         params[i]->field_value[4].mask_range.u16 =
825                                 req->keys[i].key.ipv4_5tuple.dst_port_to;
826                         break;
827
828                 default:
829                         rsp->status = -1; /* Error */
830
831                         for (i = 0; i < n_keys; i++)
832                                 rte_free(params[i]);
833
834                         return rsp;
835                 }
836         }
837
838         rsp->status = rte_pipeline_table_entry_delete_bulk(p->p, p->table_id[0],
839                         (void **)&params, n_keys, req->keys_found, NULL);
840
841         for (i = 0; i < n_keys; i++)
842                 rte_free(params[i]);
843
844         return rsp;
845 }
846
847 void *
848 pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg)
849 {
850         struct pipeline_firewall_add_default_msg_req *req = msg;
851         struct pipeline_firewall_add_default_msg_rsp *rsp = msg;
852
853         struct firewall_table_entry default_entry = {
854                 .head = {
855                         .action = RTE_PIPELINE_ACTION_PORT,
856                         {.port_id = p->port_out_id[req->port_id]},
857                 },
858         };
859
860         rsp->status = rte_pipeline_table_default_entry_add(p->p,
861                 p->table_id[0],
862                 (struct rte_pipeline_table_entry *) &default_entry,
863                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
864
865         return rsp;
866 }
867
868 void *
869 pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg)
870 {
871         struct pipeline_firewall_del_default_msg_rsp *rsp = msg;
872
873         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
874                 p->table_id[0],
875                 NULL);
876
877         return rsp;
878 }
879
880 struct pipeline_be_ops pipeline_firewall_be_ops = {
881         .f_init = pipeline_firewall_init,
882         .f_free = pipeline_firewall_free,
883         .f_run = NULL,
884         .f_timer = pipeline_firewall_timer,
885 };