1981cc75edb12f6b401731bacec6feea8c2ea483
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_firewall_be.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
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                         .f_action_bulk = NULL,
454                         .arg_ah = NULL,
455                 };
456
457                 int status = rte_pipeline_port_out_create(p->p,
458                         &port_params,
459                         &p->port_out_id[i]);
460
461                 if (status) {
462                         rte_pipeline_free(p->p);
463                         rte_free(p);
464                         return NULL;
465                 }
466         }
467
468         /* Tables */
469         p->n_tables = 1;
470         {
471                 struct rte_table_acl_params table_acl_params = {
472                         .name = params->name,
473                         .n_rules = p_fw->n_rules,
474                         .n_rule_fields = p_fw->n_rule_fields,
475                 };
476
477                 struct rte_pipeline_table_params table_params = {
478                                 .ops = &rte_table_acl_ops,
479                                 .arg_create = &table_acl_params,
480                                 .f_action_hit = NULL,
481                                 .f_action_miss = NULL,
482                                 .arg_ah = NULL,
483                                 .action_data_size =
484                                         sizeof(struct firewall_table_entry) -
485                                         sizeof(struct rte_pipeline_table_entry),
486                         };
487
488                 int status;
489
490                 memcpy(table_acl_params.field_format,
491                         p_fw->field_format,
492                         p_fw->field_format_size);
493
494                 status = rte_pipeline_table_create(p->p,
495                         &table_params,
496                         &p->table_id[0]);
497
498                 if (status) {
499                         rte_pipeline_free(p->p);
500                         rte_free(p);
501                         return NULL;
502                 }
503         }
504
505         /* Connecting input ports to tables */
506         for (i = 0; i < p->n_ports_in; i++) {
507                 int status = rte_pipeline_port_in_connect_to_table(p->p,
508                         p->port_in_id[i],
509                         p->table_id[0]);
510
511                 if (status) {
512                         rte_pipeline_free(p->p);
513                         rte_free(p);
514                         return NULL;
515                 }
516         }
517
518         /* Enable input ports */
519         for (i = 0; i < p->n_ports_in; i++) {
520                 int status = rte_pipeline_port_in_enable(p->p,
521                         p->port_in_id[i]);
522
523                 if (status) {
524                         rte_pipeline_free(p->p);
525                         rte_free(p);
526                         return NULL;
527                 }
528         }
529
530         /* Check pipeline consistency */
531         if (rte_pipeline_check(p->p) < 0) {
532                 rte_pipeline_free(p->p);
533                 rte_free(p);
534                 return NULL;
535         }
536
537         /* Message queues */
538         p->n_msgq = params->n_msgq;
539         for (i = 0; i < p->n_msgq; i++)
540                 p->msgq_in[i] = params->msgq_in[i];
541         for (i = 0; i < p->n_msgq; i++)
542                 p->msgq_out[i] = params->msgq_out[i];
543
544         /* Message handlers */
545         memcpy(p->handlers, handlers, sizeof(p->handlers));
546         memcpy(p_fw->custom_handlers,
547                 custom_handlers,
548                 sizeof(p_fw->custom_handlers));
549
550         return p;
551 }
552
553 static int
554 pipeline_firewall_free(void *pipeline)
555 {
556         struct pipeline *p = (struct pipeline *) pipeline;
557
558         /* Check input arguments */
559         if (p == NULL)
560                 return -1;
561
562         /* Free resources */
563         rte_pipeline_free(p->p);
564         rte_free(p);
565         return 0;
566 }
567
568 static int
569 pipeline_firewall_track(void *pipeline,
570         __rte_unused uint32_t port_in,
571         uint32_t *port_out)
572 {
573         struct pipeline *p = (struct pipeline *) pipeline;
574
575         /* Check input arguments */
576         if ((p == NULL) ||
577                 (port_in >= p->n_ports_in) ||
578                 (port_out == NULL))
579                 return -1;
580
581         if (p->n_ports_in == 1) {
582                 *port_out = 0;
583                 return 0;
584         }
585
586         return -1;
587 }
588
589 static int
590 pipeline_firewall_timer(void *pipeline)
591 {
592         struct pipeline *p = (struct pipeline *) pipeline;
593
594         pipeline_msg_req_handle(p);
595         rte_pipeline_flush(p->p);
596
597         return 0;
598 }
599
600 void *
601 pipeline_firewall_msg_req_custom_handler(struct pipeline *p,
602         void *msg)
603 {
604         struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p;
605         struct pipeline_custom_msg_req *req = msg;
606         pipeline_msg_req_handler f_handle;
607
608         f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS) ?
609                 p_fw->custom_handlers[req->subtype] :
610                 pipeline_msg_req_invalid_handler;
611
612         if (f_handle == NULL)
613                 f_handle = pipeline_msg_req_invalid_handler;
614
615         return f_handle(p, req);
616 }
617
618 void *
619 pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg)
620 {
621         struct pipeline_firewall_add_msg_req *req = msg;
622         struct pipeline_firewall_add_msg_rsp *rsp = msg;
623
624         struct rte_table_acl_rule_add_params params;
625         struct firewall_table_entry entry = {
626                 .head = {
627                         .action = RTE_PIPELINE_ACTION_PORT,
628                         {.port_id = p->port_out_id[req->port_id]},
629                 },
630         };
631
632         memset(&params, 0, sizeof(params));
633
634         switch (req->key.type) {
635         case PIPELINE_FIREWALL_IPV4_5TUPLE:
636                 params.priority = req->priority;
637                 params.field_value[0].value.u8 =
638                         req->key.key.ipv4_5tuple.proto;
639                 params.field_value[0].mask_range.u8 =
640                         req->key.key.ipv4_5tuple.proto_mask;
641                 params.field_value[1].value.u32 =
642                         req->key.key.ipv4_5tuple.src_ip;
643                 params.field_value[1].mask_range.u32 =
644                         req->key.key.ipv4_5tuple.src_ip_mask;
645                 params.field_value[2].value.u32 =
646                         req->key.key.ipv4_5tuple.dst_ip;
647                 params.field_value[2].mask_range.u32 =
648                         req->key.key.ipv4_5tuple.dst_ip_mask;
649                 params.field_value[3].value.u16 =
650                         req->key.key.ipv4_5tuple.src_port_from;
651                 params.field_value[3].mask_range.u16 =
652                         req->key.key.ipv4_5tuple.src_port_to;
653                 params.field_value[4].value.u16 =
654                         req->key.key.ipv4_5tuple.dst_port_from;
655                 params.field_value[4].mask_range.u16 =
656                         req->key.key.ipv4_5tuple.dst_port_to;
657                 break;
658
659         default:
660                 rsp->status = -1; /* Error */
661                 return rsp;
662         }
663
664         rsp->status = rte_pipeline_table_entry_add(p->p,
665                 p->table_id[0],
666                 &params,
667                 (struct rte_pipeline_table_entry *) &entry,
668                 &rsp->key_found,
669                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
670
671         return rsp;
672 }
673
674 void *
675 pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg)
676 {
677         struct pipeline_firewall_del_msg_req *req = msg;
678         struct pipeline_firewall_del_msg_rsp *rsp = msg;
679
680         struct rte_table_acl_rule_delete_params params;
681
682         memset(&params, 0, sizeof(params));
683
684         switch (req->key.type) {
685         case PIPELINE_FIREWALL_IPV4_5TUPLE:
686                 params.field_value[0].value.u8 =
687                         req->key.key.ipv4_5tuple.proto;
688                 params.field_value[0].mask_range.u8 =
689                         req->key.key.ipv4_5tuple.proto_mask;
690                 params.field_value[1].value.u32 =
691                         req->key.key.ipv4_5tuple.src_ip;
692                 params.field_value[1].mask_range.u32 =
693                         req->key.key.ipv4_5tuple.src_ip_mask;
694                 params.field_value[2].value.u32 =
695                         req->key.key.ipv4_5tuple.dst_ip;
696                 params.field_value[2].mask_range.u32 =
697                         req->key.key.ipv4_5tuple.dst_ip_mask;
698                 params.field_value[3].value.u16 =
699                         req->key.key.ipv4_5tuple.src_port_from;
700                 params.field_value[3].mask_range.u16 =
701                         req->key.key.ipv4_5tuple.src_port_to;
702                 params.field_value[4].value.u16 =
703                         req->key.key.ipv4_5tuple.dst_port_from;
704                 params.field_value[4].mask_range.u16 =
705                         req->key.key.ipv4_5tuple.dst_port_to;
706                 break;
707
708         default:
709                 rsp->status = -1; /* Error */
710                 return rsp;
711         }
712
713         rsp->status = rte_pipeline_table_entry_delete(p->p,
714                 p->table_id[0],
715                 &params,
716                 &rsp->key_found,
717                 NULL);
718
719         return rsp;
720 }
721
722 static void *
723 pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
724 {
725         struct pipeline_firewall_add_bulk_msg_req *req = msg;
726         struct pipeline_firewall_add_bulk_msg_rsp *rsp = msg;
727
728         struct rte_table_acl_rule_add_params *params[req->n_keys];
729         struct firewall_table_entry *entries[req->n_keys];
730
731         uint32_t i, n_keys;
732
733         n_keys = req->n_keys;
734
735         for (i = 0; i < n_keys; i++) {
736                 entries[i] = rte_malloc(NULL,
737                                 sizeof(struct firewall_table_entry),
738                                 RTE_CACHE_LINE_SIZE);
739                 if (entries[i] == NULL) {
740                         rsp->status = -1;
741                         return rsp;
742                 }
743
744                 params[i] = rte_malloc(NULL,
745                                 sizeof(struct rte_table_acl_rule_add_params),
746                                 RTE_CACHE_LINE_SIZE);
747                 if (params[i] == NULL) {
748                         rsp->status = -1;
749                         return rsp;
750                 }
751
752                 entries[i]->head.action = RTE_PIPELINE_ACTION_PORT;
753                 entries[i]->head.port_id = p->port_out_id[req->port_ids[i]];
754
755                 switch (req->keys[i].type) {
756                 case PIPELINE_FIREWALL_IPV4_5TUPLE:
757                         params[i]->priority = req->priorities[i];
758                         params[i]->field_value[0].value.u8 =
759                                 req->keys[i].key.ipv4_5tuple.proto;
760                         params[i]->field_value[0].mask_range.u8 =
761                                 req->keys[i].key.ipv4_5tuple.proto_mask;
762                         params[i]->field_value[1].value.u32 =
763                                 req->keys[i].key.ipv4_5tuple.src_ip;
764                         params[i]->field_value[1].mask_range.u32 =
765                                 req->keys[i].key.ipv4_5tuple.src_ip_mask;
766                         params[i]->field_value[2].value.u32 =
767                                 req->keys[i].key.ipv4_5tuple.dst_ip;
768                         params[i]->field_value[2].mask_range.u32 =
769                                 req->keys[i].key.ipv4_5tuple.dst_ip_mask;
770                         params[i]->field_value[3].value.u16 =
771                                 req->keys[i].key.ipv4_5tuple.src_port_from;
772                         params[i]->field_value[3].mask_range.u16 =
773                                 req->keys[i].key.ipv4_5tuple.src_port_to;
774                         params[i]->field_value[4].value.u16 =
775                                 req->keys[i].key.ipv4_5tuple.dst_port_from;
776                         params[i]->field_value[4].mask_range.u16 =
777                                 req->keys[i].key.ipv4_5tuple.dst_port_to;
778                         break;
779
780                 default:
781                         rsp->status = -1; /* Error */
782
783                         for (i = 0; i < n_keys; i++) {
784                                 rte_free(entries[i]);
785                                 rte_free(params[i]);
786                         }
787
788                         return rsp;
789                 }
790         }
791
792         rsp->status = rte_pipeline_table_entry_add_bulk(p->p, p->table_id[0],
793                         (void *)params, (struct rte_pipeline_table_entry **)entries,
794                         n_keys, req->keys_found,
795                         (struct rte_pipeline_table_entry **)req->entries_ptr);
796
797         for (i = 0; i < n_keys; i++) {
798                 rte_free(entries[i]);
799                 rte_free(params[i]);
800         }
801
802         return rsp;
803 }
804
805 static void *
806 pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg)
807 {
808         struct pipeline_firewall_del_bulk_msg_req *req = msg;
809         struct pipeline_firewall_del_bulk_msg_rsp *rsp = msg;
810
811         struct rte_table_acl_rule_delete_params *params[req->n_keys];
812
813         uint32_t i, n_keys;
814
815         n_keys = req->n_keys;
816
817         for (i = 0; i < n_keys; i++) {
818                 params[i] = rte_malloc(NULL,
819                                 sizeof(struct rte_table_acl_rule_delete_params),
820                                 RTE_CACHE_LINE_SIZE);
821                 if (params[i] == NULL) {
822                         rsp->status = -1;
823                         return rsp;
824                 }
825
826                 switch (req->keys[i].type) {
827                 case PIPELINE_FIREWALL_IPV4_5TUPLE:
828                         params[i]->field_value[0].value.u8 =
829                                 req->keys[i].key.ipv4_5tuple.proto;
830                         params[i]->field_value[0].mask_range.u8 =
831                                 req->keys[i].key.ipv4_5tuple.proto_mask;
832                         params[i]->field_value[1].value.u32 =
833                                 req->keys[i].key.ipv4_5tuple.src_ip;
834                         params[i]->field_value[1].mask_range.u32 =
835                                 req->keys[i].key.ipv4_5tuple.src_ip_mask;
836                         params[i]->field_value[2].value.u32 =
837                                 req->keys[i].key.ipv4_5tuple.dst_ip;
838                         params[i]->field_value[2].mask_range.u32 =
839                                 req->keys[i].key.ipv4_5tuple.dst_ip_mask;
840                         params[i]->field_value[3].value.u16 =
841                                 req->keys[i].key.ipv4_5tuple.src_port_from;
842                         params[i]->field_value[3].mask_range.u16 =
843                                 req->keys[i].key.ipv4_5tuple.src_port_to;
844                         params[i]->field_value[4].value.u16 =
845                                 req->keys[i].key.ipv4_5tuple.dst_port_from;
846                         params[i]->field_value[4].mask_range.u16 =
847                                 req->keys[i].key.ipv4_5tuple.dst_port_to;
848                         break;
849
850                 default:
851                         rsp->status = -1; /* Error */
852
853                         for (i = 0; i < n_keys; i++)
854                                 rte_free(params[i]);
855
856                         return rsp;
857                 }
858         }
859
860         rsp->status = rte_pipeline_table_entry_delete_bulk(p->p, p->table_id[0],
861                         (void **)&params, n_keys, req->keys_found, NULL);
862
863         for (i = 0; i < n_keys; i++)
864                 rte_free(params[i]);
865
866         return rsp;
867 }
868
869 void *
870 pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg)
871 {
872         struct pipeline_firewall_add_default_msg_req *req = msg;
873         struct pipeline_firewall_add_default_msg_rsp *rsp = msg;
874
875         struct firewall_table_entry default_entry = {
876                 .head = {
877                         .action = RTE_PIPELINE_ACTION_PORT,
878                         {.port_id = p->port_out_id[req->port_id]},
879                 },
880         };
881
882         rsp->status = rte_pipeline_table_default_entry_add(p->p,
883                 p->table_id[0],
884                 (struct rte_pipeline_table_entry *) &default_entry,
885                 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
886
887         return rsp;
888 }
889
890 void *
891 pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg)
892 {
893         struct pipeline_firewall_del_default_msg_rsp *rsp = msg;
894
895         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
896                 p->table_id[0],
897                 NULL);
898
899         return rsp;
900 }
901
902 struct pipeline_be_ops pipeline_firewall_be_ops = {
903         .f_init = pipeline_firewall_init,
904         .f_free = pipeline_firewall_free,
905         .f_run = NULL,
906         .f_timer = pipeline_firewall_timer,
907         .f_track = pipeline_firewall_track,
908 };