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