Support packets in flight
[samplevnf.git] / common / VIL / acl / lib_acl.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "lib_acl.h"
17 #include "vnf_common.h"
18 #include <rte_port.h>
19 #define ACL_LIB_DEBUG 0
20 static struct rte_acl_field_def field_format_ipv4[] = {
21         /* Protocol */
22         [0] = {
23                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
24                                  .size = sizeof(uint8_t),
25                                  .field_index = 0,
26                                  .input_index = 0,
27                                  .offset = sizeof(struct ether_hdr) +
28                                  offsetof(struct ipv4_hdr, next_proto_id),
29                                  },
30
31         /* Source IP address (IPv4) */
32         [1] = {
33                                  .type = RTE_ACL_FIELD_TYPE_MASK,
34                                  .size = sizeof(uint32_t),
35                                  .field_index = 1,
36                                  .input_index = 1,
37                                  .offset = sizeof(struct ether_hdr) +
38                                  offsetof(struct ipv4_hdr, src_addr),
39                                  },
40
41         /* Destination IP address (IPv4) */
42         [2] = {
43                                  .type = RTE_ACL_FIELD_TYPE_MASK,
44                                  .size = sizeof(uint32_t),
45                                  .field_index = 2,
46                                  .input_index = 2,
47                                  .offset = sizeof(struct ether_hdr) +
48                                  offsetof(struct ipv4_hdr, dst_addr),
49                                  },
50
51         /* Source Port */
52         [3] = {
53                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
54                                  .size = sizeof(uint16_t),
55                                  .field_index = 3,
56                                  .input_index = 3,
57                                  .offset = sizeof(struct ether_hdr) +
58                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
59                                  },
60
61         /* Destination Port */
62         [4] = {
63                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
64                                  .size = sizeof(uint16_t),
65                                  .field_index = 4,
66                                  .input_index = 3,
67                                  .offset = sizeof(struct ether_hdr) +
68                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
69                                  },
70 };
71
72 #define SIZEOF_VLAN_HDR                          4
73
74 static struct rte_acl_field_def field_format_vlan_ipv4[] = {
75         /* Protocol */
76         [0] = {
77                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
78                                  .size = sizeof(uint8_t),
79                                  .field_index = 0,
80                                  .input_index = 0,
81                                  .offset = sizeof(struct ether_hdr) +
82                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, next_proto_id),
83                                  },
84
85         /* Source IP address (IPv4) */
86         [1] = {
87                                  .type = RTE_ACL_FIELD_TYPE_MASK,
88                                  .size = sizeof(uint32_t),
89                                  .field_index = 1,
90                                  .input_index = 1,
91                                  .offset = sizeof(struct ether_hdr) +
92                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, src_addr),
93                                  },
94
95         /* Destination IP address (IPv4) */
96         [2] = {
97                                  .type = RTE_ACL_FIELD_TYPE_MASK,
98                                  .size = sizeof(uint32_t),
99                                  .field_index = 2,
100                                  .input_index = 2,
101                                  .offset = sizeof(struct ether_hdr) +
102                                  SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, dst_addr),
103                                  },
104
105         /* Source Port */
106         [3] = {
107                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
108                                  .size = sizeof(uint16_t),
109                                  .field_index = 3,
110                                  .input_index = 3,
111                                  .offset = sizeof(struct ether_hdr) +
112                                  SIZEOF_VLAN_HDR +
113                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
114                                  },
115
116         /* Destination Port */
117         [4] = {
118                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
119                                  .size = sizeof(uint16_t),
120                                  .field_index = 4,
121                                  .input_index = 4,
122                                  .offset = sizeof(struct ether_hdr) +
123                                  SIZEOF_VLAN_HDR +
124                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
125                                  },
126 };
127
128 #define SIZEOF_QINQ_HEADER                       8
129
130 static struct rte_acl_field_def field_format_qinq_ipv4[] = {
131         /* Protocol */
132         [0] = {
133                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
134                                  .size = sizeof(uint8_t),
135                                  .field_index = 0,
136                                  .input_index = 0,
137                                  .offset = sizeof(struct ether_hdr) +
138                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, next_proto_id),
139                                  },
140
141         /* Source IP address (IPv4) */
142         [1] = {
143                                  .type = RTE_ACL_FIELD_TYPE_MASK,
144                                  .size = sizeof(uint32_t),
145                                  .field_index = 1,
146                                  .input_index = 1,
147                                  .offset = sizeof(struct ether_hdr) +
148                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, src_addr),
149                                  },
150
151         /* Destination IP address (IPv4) */
152         [2] = {
153                                  .type = RTE_ACL_FIELD_TYPE_MASK,
154                                  .size = sizeof(uint32_t),
155                                  .field_index = 2,
156                                  .input_index = 2,
157                                  .offset = sizeof(struct ether_hdr) +
158                                  SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, dst_addr),
159                                  },
160
161         /* Source Port */
162         [3] = {
163                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
164                                  .size = sizeof(uint16_t),
165                                  .field_index = 3,
166                                  .input_index = 3,
167                                  .offset = sizeof(struct ether_hdr) +
168                                  SIZEOF_QINQ_HEADER +
169                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
170                                  },
171
172         /* Destination Port */
173         [4] = {
174                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
175                                  .size = sizeof(uint16_t),
176                                  .field_index = 4,
177                                  .input_index = 4,
178                                  .offset = sizeof(struct ether_hdr) +
179                                  SIZEOF_QINQ_HEADER +
180                                  sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
181                                  },
182 };
183
184 static struct rte_acl_field_def field_format_ipv6[] = {
185         /* Protocol */
186         [0] = {
187                                  .type = RTE_ACL_FIELD_TYPE_BITMASK,
188                                  .size = sizeof(uint8_t),
189                                  .field_index = 0,
190                                  .input_index = 0,
191                                  .offset = sizeof(struct ether_hdr) +
192                                  offsetof(struct ipv6_hdr, proto),
193                                  },
194
195         /* Source IP address (IPv6) */
196         [1] = {
197                                  .type = RTE_ACL_FIELD_TYPE_MASK,
198                                  .size = sizeof(uint32_t),
199                                  .field_index = 1,
200                                  .input_index = 1,
201                                  .offset = sizeof(struct ether_hdr) +
202                                  offsetof(struct ipv6_hdr, src_addr),
203                                  },
204
205         [2] = {
206                                  .type = RTE_ACL_FIELD_TYPE_MASK,
207                                  .size = sizeof(uint32_t),
208                                  .field_index = 2,
209                                  .input_index = 2,
210                                  .offset = sizeof(struct ether_hdr) +
211                                  offsetof(struct ipv6_hdr, src_addr) + sizeof(uint32_t),
212                                  },
213
214         [3] = {
215                                  .type = RTE_ACL_FIELD_TYPE_MASK,
216                                  .size = sizeof(uint32_t),
217                                  .field_index = 3,
218                                  .input_index = 3,
219                                  .offset = sizeof(struct ether_hdr) +
220                                  offsetof(struct ipv6_hdr, src_addr) + 2 * sizeof(uint32_t),
221                                  },
222
223         [4] = {
224                                  .type = RTE_ACL_FIELD_TYPE_MASK,
225                                  .size = sizeof(uint32_t),
226                                  .field_index = 4,
227                                  .input_index = 4,
228                                  .offset = sizeof(struct ether_hdr) +
229                                  offsetof(struct ipv6_hdr, src_addr) + 3 * sizeof(uint32_t),
230                                  },
231
232         /* Destination IP address (IPv6) */
233         [5] = {
234                                  .type = RTE_ACL_FIELD_TYPE_MASK,
235                                  .size = sizeof(uint32_t),
236                                  .field_index = 5,
237                                  .input_index = 5,
238                                  .offset = sizeof(struct ether_hdr) +
239                                  offsetof(struct ipv6_hdr, dst_addr),
240                                  },
241
242         [6] = {
243                                  .type = RTE_ACL_FIELD_TYPE_MASK,
244                                  .size = sizeof(uint32_t),
245                                  .field_index = 6,
246                                  .input_index = 6,
247                                  .offset = sizeof(struct ether_hdr) +
248                                  offsetof(struct ipv6_hdr, dst_addr) + sizeof(uint32_t),
249                                  },
250
251         [7] = {
252                                  .type = RTE_ACL_FIELD_TYPE_MASK,
253                                  .size = sizeof(uint32_t),
254                                  .field_index = 7,
255                                  .input_index = 7,
256                                  .offset = sizeof(struct ether_hdr) +
257                                  offsetof(struct ipv6_hdr, dst_addr) + 2 * sizeof(uint32_t),
258                                  },
259
260         [8] = {
261                                  .type = RTE_ACL_FIELD_TYPE_MASK,
262                                  .size = sizeof(uint32_t),
263                                  .field_index = 8,
264                                  .input_index = 8,
265                                  .offset = sizeof(struct ether_hdr) +
266                                  offsetof(struct ipv6_hdr, dst_addr) + 3 * sizeof(uint32_t),
267                                  },
268
269         /* Source Port */
270         [9] = {
271                                  .type = RTE_ACL_FIELD_TYPE_RANGE,
272                                  .size = sizeof(uint16_t),
273                                  .field_index = 9,
274                                  .input_index = 9,
275                                  .offset = sizeof(struct ether_hdr) +
276                                  sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, src_port),
277                                  },
278
279         /* Destination Port */
280         [10] = {
281                 .type = RTE_ACL_FIELD_TYPE_RANGE,
282                 .size = sizeof(uint16_t),
283                 .field_index = 10,
284                 .input_index = 9,
285                 .offset = sizeof(struct ether_hdr) +
286                 sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, dst_port),
287                 },
288 };
289
290 void *lib_acl_create_active_standby_table_ipv4(uint8_t table_num,
291                 uint32_t *libacl_n_rules)
292 {
293         printf("Create LIBACL active IPV4 Tables rte_socket_id(): %i\n",
294                         rte_socket_id());
295
296         /* Create IPV4 LIBACL Rule Tables */
297         struct rte_table_acl_params common_ipv4_table_libacl_params = {
298                 .name = "LIBACLIPV4A",
299                 .n_rules = *libacl_n_rules,
300                 .n_rule_fields = RTE_DIM(field_format_ipv4),
301         };
302
303         memcpy(common_ipv4_table_libacl_params.field_format,
304                         field_format_ipv4, sizeof(field_format_ipv4));
305
306         uint32_t ipv4_entry_size = sizeof(struct lib_acl_table_entry);
307         /* Create second IPV4 Table */
308         if (table_num == 2)
309                 common_ipv4_table_libacl_params.name = "LIBACLIPV4B";
310         return  rte_table_acl_ops.f_create(&common_ipv4_table_libacl_params,
311                         rte_socket_id(),
312                         ipv4_entry_size);
313
314
315 }
316
317 void *lib_acl_create_active_standby_table_ipv6(uint8_t table_num,
318                 uint32_t *libacl_n_rules)
319 {
320         printf("Create LIBACL active IPV6 Tables rte_socket_id(): %i\n",
321                         rte_socket_id());
322         /* Create IPV6 LIBACL Rule Tables */
323         struct rte_table_acl_params common_ipv6_table_libacl_params = {
324                 .name = "LIBACLIPV6A",
325                 .n_rules = *libacl_n_rules,
326                 .n_rule_fields = RTE_DIM(field_format_ipv6),
327         };
328
329         memcpy(common_ipv6_table_libacl_params.field_format,
330                         field_format_ipv6, sizeof(field_format_ipv6));
331
332         uint32_t ipv6_entry_size = sizeof(struct lib_acl_table_entry);
333         /* Create second IPV6 table */
334         if (table_num == 2)
335                 common_ipv6_table_libacl_params.name = "LIBACLIPV6B";
336         return  rte_table_acl_ops.f_create(&common_ipv6_table_libacl_params,
337                         rte_socket_id(),
338                         ipv6_entry_size);
339
340
341 }
342 int lib_acl_parse_config(struct lib_acl *plib_acl,
343                 char *arg_name, char *arg_value,
344                 uint32_t *libacl_n_rules)
345 {
346         uint32_t n_rules_present = 0;
347         uint32_t pkt_type_present = 0;
348         /* defaults */
349         plib_acl->n_rules = DEFULT_NUM_RULE;
350         *libacl_n_rules = DEFULT_NUM_RULE;
351         plib_acl->n_rule_fields = RTE_DIM(field_format_ipv4);
352         plib_acl->field_format = field_format_ipv4;
353         plib_acl->field_format_size = sizeof(field_format_ipv4);
354         if (strcmp(arg_name, "n_rules") == 0) {
355                 if (n_rules_present) {
356                         printf("n_rules_present");
357                         return -1;
358                 }
359                 n_rules_present = 1;
360
361                 plib_acl->n_rules = atoi(arg_value);
362                 *libacl_n_rules = atoi(arg_value);
363                 return 0;
364         }
365         if (strcmp(arg_name, "pkt_type") == 0) {
366                 if (pkt_type_present) {
367                         printf("pkt_type");
368                         return -1;
369                 }
370                 pkt_type_present = 1;
371
372                 /* ipv4 */
373                 if (strcmp(arg_value, "ipv4") == 0) {
374                         plib_acl->n_rule_fields =
375                                 RTE_DIM(field_format_ipv4);
376                         plib_acl->field_format = field_format_ipv4;
377                         plib_acl->field_format_size =
378                                 sizeof(field_format_ipv4);
379                         return 0;
380                 }
381
382                 /* vlan_ipv4 */
383                 if (strcmp(arg_value, "vlan_ipv4") == 0) {
384                         plib_acl->n_rule_fields =
385                                 RTE_DIM(field_format_vlan_ipv4);
386                         plib_acl->field_format =
387                                 field_format_vlan_ipv4;
388                         plib_acl->field_format_size =
389                                 sizeof(field_format_vlan_ipv4);
390                         return 0;
391                 }
392
393                 /* qinq_ipv4 */
394                 if (strcmp(arg_value, "qinq_ipv4") == 0) {
395                         plib_acl->n_rule_fields =
396                                 RTE_DIM(field_format_qinq_ipv4);
397                         plib_acl->field_format =
398                                 field_format_qinq_ipv4;
399                         plib_acl->field_format_size =
400                                 sizeof(field_format_qinq_ipv4);
401                         return 0;
402                 }
403
404                 /* ipv6 */
405                 if (strcmp(arg_value, "ipv6") == 0) {
406                         plib_acl->n_rule_fields =
407                                 RTE_DIM(field_format_ipv6);
408                         plib_acl->field_format = field_format_ipv6;
409                         plib_acl->field_format_size =
410                                 sizeof(field_format_ipv6);
411                         return 0;
412                 }
413                 /* other */
414                 printf("other");
415                 return -1;
416         }
417         /* Parameter not processed in this parse function */
418         return 1;
419 }
420
421
422 /**
423  * Main packet processing function.
424  * 64 packet bit mask are used to identify which packets to forward.
425  * Performs the following:
426  *  - Burst lookup packets in the IPv4 ACL Rule Table.
427  *  - Lookup Action Table, perform actions.
428  *  - Burst lookup Connection Tracking, if enabled.
429  *  - Lookup MAC address.
430  *  - Set bit mask.
431  *  - Packets with bit mask set are forwarded
432  *
433  * @param p
434  *  A pointer to the pipeline.
435  * @param pkts
436  *  A pointer to a burst of packets.
437  * @param n_pkts
438  *  Number of packets to process.
439  * @param arg
440  *  A pointer to pipeline specific data.
441  *
442  * @return
443  *  0 on success, negative on error.
444  */
445         uint64_t
446 lib_acl_ipv4_pkt_work_key(struct lib_acl *plib_acl,
447         struct rte_mbuf **pkts, uint64_t pkts_mask,
448         uint64_t *pkts_drop_without_rule,
449         void *plib_acl_rule_table_ipv4_active,
450         struct pipeline_action_key *action_array_active,
451         struct action_counter_block (*p_action_counter_table)[action_array_max],
452         uint64_t *conntrack_mask,
453         uint64_t *connexist_mask)
454 {
455
456         uint64_t lookup_hit_mask_ipv4 = 0;
457         uint64_t lookup_miss_mask_ipv4 = 0;
458         int status;
459
460         if (ACL_LIB_DEBUG)
461                 printf("ACL IPV4 Lookup Mask Before = 0x%"PRIx64"\n",
462                                 pkts_mask);
463         status = rte_table_acl_ops.f_lookup(
464                         plib_acl_rule_table_ipv4_active,
465                         pkts, pkts_mask, &lookup_hit_mask_ipv4,
466                         (void **) plib_acl->plib_acl_entries_ipv4);
467         if (status < 0)
468                 printf("Lookup Failed\n");
469         if (ACL_LIB_DEBUG)
470                 printf("ACL IPV4 Lookup Mask After = 0x%"PRIx64"\n",
471                                 lookup_hit_mask_ipv4);
472         if (ACL_LIB_DEBUG)
473                 printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
474                                 lookup_hit_mask_ipv4);
475
476         lookup_miss_mask_ipv4 = pkts_mask & (~lookup_hit_mask_ipv4);
477         pkts_mask = lookup_hit_mask_ipv4;
478         *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv4);
479         if (ACL_LIB_DEBUG)
480                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
481                                 *pkts_drop_without_rule,
482                                 __builtin_popcountll(lookup_miss_mask_ipv4));
483         /* bitmap of packets left to process for ARP */
484         uint64_t pkts_to_process = lookup_hit_mask_ipv4;
485
486         for (; pkts_to_process;) {
487                 uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
488                 /* bitmask representing only this packet */
489                 uint64_t pkt_mask = 1LLU << pos;
490                 /* remove this packet from remaining list */
491                 pkts_to_process &= ~pkt_mask;
492                 struct rte_mbuf *pkt = pkts[pos];
493
494
495
496                 struct lib_acl_table_entry *entry =
497                         (struct lib_acl_table_entry *)
498                         plib_acl->plib_acl_entries_ipv4[pos];
499                 uint16_t phy_port = entry->head.port_id;
500                 uint32_t action_id = entry->action_id;
501
502                 if (ACL_LIB_DEBUG)
503                         printf("action_id = %u\n", action_id);
504
505                 uint32_t dscp_offset = IP_START + IP_HDR_DSCP_OFST;
506
507                 if (action_array_active[action_id].action_bitmap &
508                                 lib_acl_action_count) {
509                         p_action_counter_table
510                                 [plib_acl->action_counter_index]
511                                 [action_id].packetCount++;
512                         p_action_counter_table
513                                 [plib_acl->action_counter_index]
514                                 [action_id].byteCount +=
515                                 rte_pktmbuf_pkt_len(pkt);
516                         if (ACL_LIB_DEBUG)
517                                 printf("Action Count   Packet Count: %"
518                                                 PRIu64 "  Byte Count: %"
519                                                 PRIu64 "\n"
520                                                 , p_action_counter_table
521                                                 [plib_acl->action_counter_index]
522                                                 [action_id].packetCount,
523                                                 p_action_counter_table
524                                                 [plib_acl->action_counter_index]
525                                                 [action_id].byteCount);
526                 }
527
528                 if (action_array_active[action_id].action_bitmap &
529                                 lib_acl_action_packet_drop) {
530
531                         /* Drop packet by changing the mask */
532                         if (ACL_LIB_DEBUG)
533                                 printf("ACL before drop pkt_mask %"
534                                                 PRIx64", pkt_num %d\n",
535                                                 pkts_mask, pos);
536                         pkts_mask &= ~(1LLU << pos);
537                         (*pkts_drop_without_rule)++;
538                         if (ACL_LIB_DEBUG)
539                                 printf("ACL after drop pkt_mask %" PRIx64
540                                         ", pkt_num %d, action_packet_drop %"
541                                         PRIu64 "\n", pkts_mask, pos,
542                                         *pkts_drop_without_rule);
543                 }
544
545                 if (action_array_active[action_id].action_bitmap &
546                                 lib_acl_action_fwd) {
547                         phy_port = action_array_active[action_id].
548                                 fwd_port;
549                         entry->head.port_id = phy_port;
550                         if (ACL_LIB_DEBUG)
551                                 printf("Action FWD  Port ID: %"
552                                                 PRIu16"\n", phy_port);
553                 }
554
555                 if (action_array_active[action_id].action_bitmap &
556                                 lib_acl_action_nat) {
557                         phy_port = action_array_active[action_id].
558                                 nat_port;
559                         entry->head.port_id = phy_port;
560                         if (ACL_LIB_DEBUG)
561                                 printf("Action NAT  Port ID: %"
562                                                 PRIu16"\n", phy_port);
563                 }
564
565                 if (action_array_active[action_id].action_bitmap &
566                                 lib_acl_action_dscp) {
567
568                         /* Set DSCP priority */
569                         uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
570                                         dscp_offset);
571                         *dscp = action_array_active[action_id].
572                                 dscp_priority << 2;
573                         if (ACL_LIB_DEBUG)
574                                 printf("Action DSCP   DSCP Priority: %"
575                                                 PRIu16 "\n", *dscp);
576                 }
577
578                 if (action_array_active[action_id].action_bitmap &
579                                 lib_acl_action_packet_accept) {
580                         if (ACL_LIB_DEBUG)
581                                 printf("Action Accept\n");
582
583                         if (action_array_active[action_id].action_bitmap
584                                         & lib_acl_action_conntrack) {
585
586                                 /* Set conntrack bit for this pkt */
587                                 *conntrack_mask |= pkt_mask;
588                                 if (ACL_LIB_DEBUG)
589                                         printf("ACL CT enabled: 0x%"
590                                                         PRIx64"  pkt_mask: 0x%"
591                                                         PRIx64"\n",
592                                                         *conntrack_mask,
593                                                         pkt_mask);
594                         }
595
596                         if (action_array_active[action_id].action_bitmap
597                                         & lib_acl_action_connexist) {
598
599                                 /* Set conntrack bit for this pkt */
600                                 *conntrack_mask |= pkt_mask;
601
602                                 /* Set connexist bit for this pkt for
603                                  * public -> private */
604                                 /* Private -> public packet will open
605                                  * the connection */
606                                 if (action_array_active[action_id].
607                                                 private_public ==
608                                                 lib_acl_public_private)
609                                         *connexist_mask |= pkt_mask;
610
611                                 if (ACL_LIB_DEBUG)
612                                         printf("ACL Connexist ENB CT:0x%"
613                                                         PRIx64"  connexist: 0x%"
614                                                         PRIx64"  pkt_mask: 0x%"
615                                                         PRIx64"\n",
616                                                         *conntrack_mask,
617                                                         *connexist_mask,
618                                                         pkt_mask);
619                         }
620                 }
621
622         }
623         return pkts_mask;
624 }
625 /**
626  * Main packet processing function.
627  * 64 packet bit mask are used to identify which packets to forward.
628  * Performs the following:
629  *  - Burst lookup packets in the IPv6 ACL Rule Table.
630  *  - Lookup Action Table, perform actions.
631  *  - Burst lookup Connection Tracking, if enabled.
632  *  - Lookup MAC address.
633  *  - Set bit mask.
634  *  - Packets with bit mask set are forwarded
635  *
636  * @param p
637  *  A pointer to the pipeline.
638  * @param pkts
639  *  A pointer to a burst of packets.
640  * @param n_pkts
641  *  Number of packets to process.
642  * @param arg
643  *  A pointer to pipeline specific data.
644  *
645  * @return
646  *  0 on success, negative on error.
647  */
648         uint64_t
649 lib_acl_ipv6_pkt_work_key(struct lib_acl *plib_acl,
650         struct rte_mbuf **pkts, uint64_t pkts_mask,
651         uint64_t *pkts_drop_without_rule,
652         void *plib_acl_rule_table_ipv6_active,
653         struct pipeline_action_key *action_array_active,
654         struct action_counter_block (*p_action_counter_table)[action_array_max],
655         uint64_t *conntrack_mask,
656         uint64_t *connexist_mask)
657 {
658
659         uint64_t lookup_hit_mask_ipv6 = 0;
660         uint64_t lookup_miss_mask_ipv6 = 0;
661         int status;
662
663
664         if (ACL_LIB_DEBUG)
665                 printf("ACL IPV6 Lookup Mask Before = 0x%"PRIx64"\n",
666                                 pkts_mask);
667         status = rte_table_acl_ops.f_lookup(
668                         plib_acl_rule_table_ipv6_active,
669                         pkts, pkts_mask, &lookup_hit_mask_ipv6,
670                         (void **) plib_acl->plib_acl_entries_ipv6);
671         if (status < 0)
672                 printf("Lookup Failed\n");
673         if (ACL_LIB_DEBUG)
674                 printf("ACL IPV6 Lookup Mask After = 0x%"PRIx64"\n",
675                                 lookup_hit_mask_ipv6);
676
677         if (ACL_LIB_DEBUG)
678                 printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
679                                 lookup_hit_mask_ipv6);
680
681         lookup_miss_mask_ipv6 = pkts_mask & (~lookup_hit_mask_ipv6);
682         pkts_mask = lookup_hit_mask_ipv6;
683         *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv6);
684         if (ACL_LIB_DEBUG)
685                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
686                                 *pkts_drop_without_rule,
687                                 __builtin_popcountll(lookup_miss_mask_ipv6));
688         /* bitmap of packets left to process for ARP */
689         uint64_t pkts_to_process = lookup_hit_mask_ipv6;
690
691         for (; pkts_to_process;) {
692                 uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
693                 /* bitmask representing only this packet */
694                 uint64_t pkt_mask = 1LLU << pos;
695                 /* remove this packet from remaining list */
696                 pkts_to_process &= ~pkt_mask;
697                 struct rte_mbuf *pkt = pkts[pos];
698
699
700                 struct lib_acl_table_entry *entry =
701                         (struct lib_acl_table_entry *)
702                         plib_acl->plib_acl_entries_ipv6[pos];
703                 uint16_t phy_port = entry->head.port_id;
704                 uint32_t action_id = entry->action_id;
705
706                 if (ACL_LIB_DEBUG)
707                         printf("action_id = %u\n", action_id);
708
709                 if (action_array_active[action_id].action_bitmap &
710                                 lib_acl_action_count) {
711                         p_action_counter_table
712                                 [plib_acl->action_counter_index]
713                                 [action_id].packetCount++;
714                         p_action_counter_table
715                                 [plib_acl->action_counter_index]
716                                 [action_id].byteCount +=
717                                 rte_pktmbuf_pkt_len(pkt);
718                         if (ACL_LIB_DEBUG)
719                                 printf("Action Count   Packet Count: %"
720                                                 PRIu64 "  Byte Count: %"
721                                                 PRIu64 "\n",
722                                                 p_action_counter_table
723                                                 [plib_acl->action_counter_index]
724                                                 [action_id].packetCount,
725                                                 p_action_counter_table
726                                                 [plib_acl->action_counter_index]
727                                                 [action_id].byteCount);
728                 }
729
730                 if (action_array_active[action_id].action_bitmap &
731                                 lib_acl_action_packet_drop) {
732                         /* Drop packet by changing the mask */
733                         if (ACL_LIB_DEBUG)
734                                 printf("ACL before drop pkt_mask %"
735                                                 PRIx64", pkt_num %d\n",
736                                                 pkts_mask, pos);
737                         pkts_mask &= ~(1LLU << pos);
738                         (*pkts_drop_without_rule)++;
739                         if (ACL_LIB_DEBUG)
740                                 printf("ACL after drop pkt_mask %" PRIx64
741                                         ", pkt_num %d, action_packet_drop %"
742                                         PRIu64 "\n", pkts_mask, pos,
743                                         *pkts_drop_without_rule);
744
745                 }
746
747                 if (action_array_active[action_id].action_bitmap &
748                                 lib_acl_action_fwd) {
749                         phy_port = action_array_active[action_id].
750                                 fwd_port;
751                         entry->head.port_id = phy_port;
752                         if (ACL_LIB_DEBUG)
753                                 printf("Action FWD  Port ID: %"
754                                                 PRIu16"\n", phy_port);
755                 }
756
757                 if (action_array_active[action_id].action_bitmap &
758                                 lib_acl_action_nat) {
759                         phy_port = action_array_active[action_id].
760                                 nat_port;
761                         entry->head.port_id = phy_port;
762                         if (ACL_LIB_DEBUG)
763                                 printf("Action NAT  Port ID: %"
764                                                 PRIu16"\n", phy_port);
765                 }
766
767                 if (action_array_active[action_id].action_bitmap &
768                                 lib_acl_action_dscp) {
769
770                         /* Set DSCP priority */
771                         uint32_t dscp_offset = IP_START +
772                                 IP_HDR_DSCP_OFST_IPV6;
773                         uint16_t *dscp = RTE_MBUF_METADATA_UINT16_PTR(
774                                         pkt, dscp_offset);
775                         uint16_t temp = *dscp;
776                         uint16_t dscp_value = (rte_bswap16(temp) &
777                                         0XF00F);
778                         uint8_t dscp_store =
779                                 action_array_active
780                                 [action_id].dscp_priority << 2;
781                         uint16_t dscp_temp = dscp_store;
782
783                         dscp_temp = dscp_temp << 4;
784                         *dscp = rte_bswap16(dscp_temp | dscp_value);
785                         if (ACL_LIB_DEBUG)
786                                 printf("Action DSCP   DSCP Priority: %"
787                                                 PRIu16"\n", *dscp);
788                 }
789
790                 if (action_array_active[action_id].action_bitmap
791                                 & lib_acl_action_packet_accept) {
792                         if (ACL_LIB_DEBUG)
793                                 printf("Action Accept\n");
794
795                         if (action_array_active[action_id].action_bitmap
796                                         & lib_acl_action_conntrack) {
797
798                                 /* Set conntrack bit for this pkt */
799                                 *conntrack_mask |= pkt_mask;
800                                 if (ACL_LIB_DEBUG)
801                                         printf("ACL CT enabled: 0x%"
802                                                         PRIx64" pkt_mask: 0x%"
803                                                         PRIx64"\n",
804                                                         *conntrack_mask,
805                                                         pkt_mask);
806                         }
807
808                         if (action_array_active[action_id].action_bitmap
809                                         & lib_acl_action_connexist) {
810
811                                 /* Set conntrack bit for this pkt */
812                                 *conntrack_mask |= pkt_mask;
813
814                                 /* Set connexist bit for this pkt for
815                                  * public -> private */
816                                 /* Private -> public packet will open
817                                  * the connection */
818                                 if (action_array_active[action_id].
819                                                 private_public ==
820                                                 lib_acl_public_private)
821                                         *connexist_mask |= pkt_mask;
822
823                                 if (ACL_LIB_DEBUG)
824                                         printf("ACL Connexist ENB CT:0x%"
825                                                         PRIx64"  connexist: 0x%"
826                                                         PRIx64"  pkt_mask: 0x%"
827                                                         PRIx64"\n",
828                                                         *conntrack_mask,
829                                                         *connexist_mask,
830                                                         pkt_mask);
831                         }
832                 }
833         }
834         return pkts_mask;
835 }