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