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