b6e6076df7cc67fbbea4189d87aa7bb39b9d4c32
[samplevnf.git] / VNFs / vACL / pipeline / pipeline_acl_be.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
17 /**
18  * @file
19  * Pipeline ACL BE Implementation.
20  *
21  * Implementation of Pipeline ACL Back End (BE).
22  * Responsible for packet processing.
23  *
24  */
25
26 #include <string.h>
27 #include <rte_common.h>
28 #include <rte_malloc.h>
29 #include <rte_ether.h>
30 #include <rte_ip.h>
31 #include <rte_tcp.h>
32 #include <rte_byteorder.h>
33 #include <rte_table_acl.h>
34 #include <rte_table_stub.h>
35 #include "pipeline_arpicmp_be.h"
36 #include "vnf_common.h"
37 #include "pipeline_common_be.h"
38 #include <rte_pipeline.h>
39 #include <rte_hash.h>
40
41 #include <rte_timer.h>
42 #include <rte_cycles.h>
43
44 #include "pipeline_acl.h"
45 #include "pipeline_acl_be.h"
46 #include "rte_cnxn_tracking.h"
47 #include "pipeline_actions_common.h"
48 #include "lib_arp.h"
49 #include "lib_icmpv6.h"
50 static uint8_t acl_prv_que_port_index[PIPELINE_MAX_PORT_IN];
51 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
52                                               uint8_t netmask_ipv6[]);
53 enum {
54         ACL_PUB_PORT_ID,
55         ACL_PRV_PORT_ID,
56 };
57
58 /**
59  * A structure defining the ACL pipeline per thread data.
60  */
61 struct pipeline_acl {
62         struct pipeline p;
63         pipeline_msg_req_handler custom_handlers[PIPELINE_ACL_MSG_REQS];
64
65         uint32_t n_rules;
66         uint32_t n_rule_fields;
67         struct rte_acl_field_def *field_format;
68         uint32_t field_format_size;
69
70         /* Connection Tracker */
71         struct rte_ct_cnxn_tracker *cnxn_tracker;
72         struct rte_ACL_counter_block *counters;
73         int action_counter_index;
74         /* timestamp retrieved during in-port computations */
75         uint64_t in_port_time_stamp;
76         uint32_t n_flows;
77
78         uint8_t pipeline_num;
79         uint8_t traffic_type;
80         uint8_t links_map[PIPELINE_MAX_PORT_IN];
81         uint8_t port_out_id[PIPELINE_MAX_PORT_IN];
82         uint64_t arpPktCount;
83         struct acl_table_entry *acl_entries_ipv4[RTE_PORT_IN_BURST_SIZE_MAX];
84         struct acl_table_entry *acl_entries_ipv6[RTE_PORT_IN_BURST_SIZE_MAX];
85
86         /* Local ARP & ND Tables */
87         struct lib_arp_route_table_entry
88          local_lib_arp_route_table[MAX_ARP_RT_ENTRY];
89         uint8_t local_lib_arp_route_ent_cnt;
90         struct lib_nd_route_table_entry
91          local_lib_nd_route_table[MAX_ND_RT_ENTRY];
92         uint8_t local_lib_nd_route_ent_cnt;
93
94 } __rte_cache_aligned;
95
96 /**
97  * A structure defining the mbuf meta data for ACL.
98  */
99 struct mbuf_acl_meta_data {
100         /* output port stored for RTE_PIPELINE_ACTION_PORT_META */
101         uint32_t output_port;
102         /* next hop ip address used by ARP code */
103         uint8_t nhip[16];
104 } __rte_cache_aligned;
105
106 #define META_DATA_OFFSET 128
107
108 struct rte_ACL_counter_block rte_acl_counter_table[MAX_ACL_INSTANCES]
109         __rte_cache_aligned;
110 int rte_ACL_hi_counter_block_in_use = -1;
111
112 /* a spin lock used during acl initialization only */
113 rte_spinlock_t rte_ACL_init_lock = RTE_SPINLOCK_INITIALIZER;
114
115 /* Action Array */
116 struct pipeline_action_key *action_array_a;
117 struct pipeline_action_key *action_array_b;
118 struct pipeline_action_key *action_array_active;
119 struct pipeline_action_key *action_array_standby;
120 uint32_t action_array_size;
121
122 struct action_counter_block
123         action_counter_table[MAX_ACL_INSTANCES][action_array_max]
124         __rte_cache_aligned;
125
126 static void *pipeline_acl_msg_req_custom_handler(struct pipeline *p, void *msg);
127
128 static pipeline_msg_req_handler handlers[] = {
129         [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler,
130         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
131             pipeline_msg_req_stats_port_in_handler,
132         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
133             pipeline_msg_req_stats_port_out_handler,
134         [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
135         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
136             pipeline_msg_req_port_in_enable_handler,
137         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
138             pipeline_msg_req_port_in_disable_handler,
139         [PIPELINE_MSG_REQ_CUSTOM] = pipeline_acl_msg_req_custom_handler,
140 };
141
142 static void *pipeline_acl_msg_req_dbg_handler(struct pipeline *p, void *msg);
143
144 static pipeline_msg_req_handler custom_handlers[] = {
145         [PIPELINE_ACL_MSG_REQ_DBG] = pipeline_acl_msg_req_dbg_handler,
146 };
147 uint64_t arp_pkts_mask;
148
149 uint8_t ACL_DEBUG;
150 uint32_t local_get_nh_ipv4(uint32_t ip,
151                            uint32_t *port,
152                            uint32_t *nhip, struct pipeline_acl *p_acl)
153 {
154         int i;
155
156         for (i = 0; i < p_acl->local_lib_arp_route_ent_cnt; i++) {
157                 if (((p_acl->local_lib_arp_route_table[i].ip &
158                         p_acl->local_lib_arp_route_table[i].mask) ==
159                         (ip & p_acl->local_lib_arp_route_table[i].mask))) {
160                         *port = p_acl->local_lib_arp_route_table[i].port;
161
162                         *nhip = p_acl->local_lib_arp_route_table[i].nh;
163                         return 1;
164                 }
165         }
166         return 0;
167 }
168
169 static uint32_t local_get_nh_ipv6(uint8_t *ip,
170                                   uint32_t *port,
171                                   uint8_t nhip[], struct pipeline_acl *p_acl)
172 {
173         int i = 0;
174         uint8_t netmask_ipv6[16],netip_nd[16],netip_in[16];
175         uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
176         memset (netmask_ipv6, 0, sizeof(netmask_ipv6));
177         memset (netip_nd, 0, sizeof(netip_nd));
178         memset (netip_in, 0, sizeof(netip_in));
179
180         for (i = 0; i < p_acl->local_lib_nd_route_ent_cnt; i++) {
181
182                 convert_prefixlen_to_netmask_ipv6
183                     (p_acl->local_lib_nd_route_table[i].depth, netmask_ipv6);
184
185                 for (k = 0; k < 16; k++)
186                         if (p_acl->local_lib_nd_route_table[i].ipv6[k] &
187                             netmask_ipv6[k]) {
188                                 depthflags++;
189                                 netip_nd[k] = p_acl->
190                                 local_lib_nd_route_table[i].ipv6[k];
191                         }
192
193
194                 for (l = 0; l < 16; l++)
195                         if (ip[l] & netmask_ipv6[l]) {
196                                 depthflags1++;
197                                 netip_in[l] = ip[l];
198                         }
199
200                 int j = 0;
201
202                 if ((depthflags == depthflags1) && (memcmp(netip_nd, netip_in,
203                                                         sizeof(netip_nd)) == 0)){
204                         *port = p_acl->local_lib_nd_route_table[i].port;
205
206                         for (j = 0; j < 16; j++)
207                                 nhip[j] =
208                                     p_acl->local_lib_nd_route_table[i].
209                                     nhipv6[j];
210                         return 1;
211                 }
212
213                 depthflags = 0;
214                 depthflags1 = 0;
215         }
216         return 0;
217 }
218
219 static uint8_t check_arp_icmp(struct rte_mbuf *pkt,
220                               uint64_t pkt_mask, struct pipeline_acl *p_acl)
221 {
222         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
223         struct ipv6_hdr *ipv6_h;
224         uint16_t *eth_proto =
225             RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
226         struct app_link_params *link;
227
228         //uint32_t *port_out_id = RTE_MBUF_METADATA_UINT32_PTR(pk
229         //                      offsetof(struct mbuf_acl_meta_dat
230
231         /* ARP outport number */
232         uint16_t out_port = p_acl->p.n_ports_out - 1;
233
234         uint8_t *protocol;
235         uint32_t prot_offset;
236
237         link = &myApp->link_params[pkt->port];
238
239         switch (rte_be_to_cpu_16(*eth_proto)) {
240
241         case ETH_TYPE_ARP:
242                 rte_pipeline_port_out_packet_insert(p_acl->p.p, out_port, pkt);
243
244                 /*
245                  * Pkt mask should be changed, and not changing the
246                  * drop mask
247                  */
248                 p_acl->arpPktCount++;
249
250                 return 0;
251 /*              break;*/
252         case ETH_TYPE_IPV4:{
253                         /* header room + eth hdr size +
254                          * src_aadr offset in ip header
255                          */
256                         uint32_t dst_addr_offset = MBUF_HDR_ROOM +
257                             ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
258                         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
259                                                           dst_addr_offset);
260                         prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
261                             IP_HDR_PROTOCOL_OFST;
262                         protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
263                                                                prot_offset);
264                         if ((*protocol == IP_PROTOCOL_ICMP) &&
265                             link->ip == rte_be_to_cpu_32(*dst_addr)) {
266
267                                 if (is_phy_port_privte(pkt->port)) {
268
269                                         rte_pipeline_port_out_packet_insert
270                                             (p_acl->p.p, out_port, pkt);
271                                         /*
272                                          * Pkt mask should be changed,
273                                          * and not changing the drop mask
274                                          */
275                                         p_acl->arpPktCount++;
276
277                                         return 0;
278                                 }
279                         }
280                         return 1;
281                 }
282                 break;
283 #if 0
284 #ifdef IPV6
285         case ETH_TYPE_IPV6:{
286
287                         uint32_t dst_addr_offset = MBUF_HDR_ROOM +
288                             ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
289                         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
290                                                           dst_addr_offset);
291
292                         uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
293                             ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
294                         struct ipv6_hdr *ipv6_h;
295
296                         ipv6_h = (struct ipv6_hdr *)MBUF_HDR_ROOM +
297                             ETH_HDR_SIZE;
298                         protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
299                                                        prot_offset_ipv6);
300
301                         if ((ipv6_h->proto == ICMPV6_PROTOCOL_ID) &&
302                             (link->ip == rte_be_to_cpu_32(dst_addr[3]))) {
303
304                                 if (is_phy_port_privte(pkt->port)) {
305
306                                         rte_pipeline_port_out_packet_insert
307                                             (p_acl->p.p, out_port, pkt);
308                                         /*
309                                          * Pkt mask should be changed,
310                                          * and not changing the drop mask
311                                          */
312                                         p_acl->arpPktCount++;
313
314                                         return 0;
315                                 }
316                         }
317                         return 1;
318                 }
319                 break;
320 #endif
321 #endif
322 #define IP_START (MBUF_HDR_ROOM + ETH_HDR_SIZE)
323 #ifdef IPV6
324         case ETH_TYPE_IPV6:
325                 ipv6_h = (struct ipv6_hdr *)
326                         RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
327
328                 if ((ipv6_h->proto == ICMPV6_PROTOCOL_ID) &&
329                                 (link->ip ==
330                          rte_be_to_cpu_32(ipv6_h->dst_addr[3]))) {
331
332                         if (is_phy_port_privte(pkt->port)) {
333                                 rte_pipeline_port_out_packet_insert(
334                                                 p_acl->p.p,
335                                                 out_port,
336                                                 pkt);
337
338                         p_acl->arpPktCount++;
339
340                                 return 0;
341                         }
342                 }
343                 break;
344 #endif
345         default:
346                 break;
347                 return 1;
348         }
349         return 1;
350 }
351
352 /**
353  * Print packet for debugging.
354  *
355  * @param pkt
356  *  A pointer to the packet.
357  *
358  */
359 void print_pkt_acl(struct rte_mbuf *pkt)
360 {
361         int i = 0, j = 0;
362
363         printf("Packet Contents:\n");
364         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
365
366         for (i = 0; i < 20; i++) {
367                 for (j = 0; j < 20; j++)
368                         printf("%02x ", rd[(20 * i) + j]);
369                 printf("\n");
370         }
371 }
372
373 /**
374  * Main packet processing function.
375  * 64 packet bit mask are used to identify which packets to forward.
376  * Performs the following:
377  *  - Burst lookup packets in the IPv4 ACL Rule Table.
378  *  - Burst lookup packets in the IPv6 ACL Rule Table.
379  *  - Lookup Action Table, perform actions.
380  *  - Burst lookup Connection Tracking, if enabled.
381  *  - Lookup MAC address.
382  *  - Set bit mask.
383  *  - Packets with bit mask set are forwarded
384  *
385  * @param p
386  *  A pointer to the pipeline.
387  * @param pkts
388  *  A pointer to a burst of packets.
389  * @param n_pkts
390  *  Number of packets to process.
391  * @param arg
392  *  A pointer to pipeline specific data.
393  *
394  * @return
395  *  0 on success, negative on error.
396  */
397 static int
398 pkt_work_acl_key(struct rte_pipeline *p,
399                  struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
400 {
401
402         struct pipeline_acl *p_acl = arg;
403
404         p_acl->counters->pkts_received =
405             p_acl->counters->pkts_received + n_pkts;
406         if (ACL_DEBUG)
407                 printf("pkt_work_acl_key pkts_received: %" PRIu64
408                        " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
409
410         uint64_t lookup_hit_mask = 0;
411         uint64_t lookup_hit_mask_ipv4 = 0;
412         uint64_t lookup_hit_mask_ipv6 = 0;
413         uint64_t lookup_miss_mask = 0;
414         uint64_t conntrack_mask = 0;
415         uint64_t connexist_mask = 0;
416         uint32_t dest_address = 0;
417         arp_pkts_mask = 0;
418         int dest_if = 0;
419         int status;
420         uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
421         uint64_t keep_mask = pkts_mask;
422         uint16_t port;
423         uint32_t ret;
424
425         p_acl->in_port_time_stamp = rte_get_tsc_cycles();
426
427         if (acl_ipv4_enabled) {
428                 if (ACL_DEBUG)
429                         printf("ACL IPV4 Lookup Mask Before = %p\n",
430                                (void *)pkts_mask);
431                 status =
432                     rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts,
433                                                pkts_mask, &lookup_hit_mask_ipv4,
434                                                (void **)
435                                                p_acl->acl_entries_ipv4);
436                 if (ACL_DEBUG)
437                         printf("ACL IPV4 Lookup Mask After = %p\n",
438                                (void *)lookup_hit_mask_ipv4);
439         }
440
441         if (acl_ipv6_enabled) {
442                 if (ACL_DEBUG)
443                         printf("ACL IPV6 Lookup Mask Before = %p\n",
444                                (void *)pkts_mask);
445                 status =
446                     rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts,
447                                                pkts_mask, &lookup_hit_mask_ipv6,
448                                                (void **)
449                                                p_acl->acl_entries_ipv6);
450                 if (ACL_DEBUG)
451                         printf("ACL IPV6 Lookup Mask After = %p\n",
452                                (void *)lookup_hit_mask_ipv6);
453         }
454
455         /* Merge lookup results since we process both IPv4 and IPv6 below */
456         lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
457         if (ACL_DEBUG)
458                 printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
459
460         lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
461         pkts_mask = lookup_hit_mask;
462         p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
463         if (ACL_DEBUG)
464                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
465                        p_acl->counters->pkts_drop,
466                        __builtin_popcountll(lookup_miss_mask));
467
468         uint64_t pkts_to_process = lookup_hit_mask;
469                 /* bitmap of packets left to process for ARP */
470
471         for (; pkts_to_process;) {
472                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
473                 uint64_t pkt_mask = 1LLU << pos;
474                 /* bitmask representing only this packet */
475
476                 pkts_to_process &= ~pkt_mask;
477                 /* remove this packet from remaining list */
478                 struct rte_mbuf *pkt = pkts[pos];
479
480                 if (enable_hwlb)
481                         if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
482                                 pkts_mask &= ~(1LLU << pos);
483                                 continue;
484                         }
485
486                 uint8_t hdr_chk =
487                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
488                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
489
490                 if (hdr_chk == IPv4_HDR_VERSION) {
491
492                         struct acl_table_entry *entry =
493                             (struct acl_table_entry *)
494                             p_acl->acl_entries_ipv4[pos];
495                         uint16_t phy_port = entry->head.port_id;
496                         uint32_t action_id = entry->action_id;
497
498                         if (ACL_DEBUG)
499                                 printf("action_id = %u\n", action_id);
500
501                         uint32_t dscp_offset =
502                             MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
503
504                         if (action_array_active[action_id].action_bitmap &
505                             acl_action_count) {
506                                 action_counter_table
507                                     [p_acl->action_counter_index]
508                                     [action_id].packetCount++;
509                                 action_counter_table
510                                     [p_acl->action_counter_index]
511                                     [action_id].byteCount +=
512                                     rte_pktmbuf_pkt_len(pkt);
513                                 if (ACL_DEBUG)
514                                         printf("Action Count   Packet Count: %"
515                                                PRIu64 "  Byte Count: %" PRIu64
516                                                "\n",
517                                                action_counter_table
518                                                [p_acl->action_counter_index]
519                                                [action_id].packetCount,
520                                                action_counter_table
521                                                [p_acl->action_counter_index]
522                                                [action_id].byteCount);
523                         }
524
525                         if (action_array_active[action_id].action_bitmap &
526                             acl_action_packet_drop) {
527
528                                 /* Drop packet by changing the mask */
529                                 if (ACL_DEBUG)
530                                         printf("ACL before drop pkt_mask "
531                                                         " %lu, pkt_num %d\n",
532                                              pkts_mask, pos);
533                                 pkts_mask &= ~(1LLU << pos);
534                                 if (ACL_DEBUG)
535                                         printf("ACL after drop pkt_mask  "
536                                                         "%lu, pkt_num %d\n",
537                                              pkts_mask, pos);
538                                 p_acl->counters->pkts_drop++;
539                         }
540
541                         if (action_array_active[action_id].action_bitmap &
542                             acl_action_fwd) {
543                                 phy_port =
544                                     action_array_active[action_id].fwd_port;
545                                 entry->head.port_id = phy_port;
546                                 if (ACL_DEBUG)
547                                         printf("Action FWD  Port ID: %u\n",
548                                                phy_port);
549                         }
550
551                         if (action_array_active[action_id].action_bitmap &
552                             acl_action_nat) {
553                                 phy_port =
554                                     action_array_active[action_id].nat_port;
555                                 entry->head.port_id = phy_port;
556                                 if (ACL_DEBUG)
557                                         printf("Action NAT  Port ID: %u\n",
558                                                phy_port);
559                         }
560
561                         if (action_array_active[action_id].action_bitmap &
562                             acl_action_dscp) {
563
564                                 /* Set DSCP priority */
565                                 uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
566                                                             dscp_offset);
567                                 *dscp =
568                                     action_array_active[action_id].dscp_priority
569                                     << 2;
570                                 if (ACL_DEBUG)
571                                         printf
572                                             ("Action DSCP  DSCP Priority: %u\n",
573                                              *dscp);
574                         }
575
576                         if (action_array_active[action_id].action_bitmap &
577                             acl_action_packet_accept) {
578                                 if (ACL_DEBUG)
579                                         printf("Action Accept\n");
580
581                                 if (action_array_active[action_id].action_bitmap
582                                     & acl_action_conntrack) {
583
584                                         /* Set conntrack bit for this pkt */
585                                         conntrack_mask |= pkt_mask;
586                                         if (ACL_DEBUG)
587                                                 printf("ACL Conntrack enabled: "
588                                                         "%p  pkt_mask: %p\n",
589                                                      (void *)conntrack_mask,
590                                                      (void *)pkt_mask);
591                                 }
592
593                                 if (action_array_active[action_id].action_bitmap
594                                     & acl_action_connexist) {
595
596                                         /* Set conntrack bit for this pkt */
597                                         conntrack_mask |= pkt_mask;
598
599                 /* Set connexist bit for this pkt for public -> private */
600                 /* Private -> public packet will open the connection */
601                                         if (action_array_active
602                                             [action_id].private_public ==
603                                             acl_public_private)
604                                                 connexist_mask |= pkt_mask;
605
606                                         if (ACL_DEBUG)
607                                                 printf("ACL Connexist enabled  "
608                                 "conntrack: %p  connexist: %p  pkt_mask: %p\n",
609                                                      (void *)conntrack_mask,
610                                                      (void *)connexist_mask,
611                                                      (void *)pkt_mask);
612                                 }
613                         }
614                 }
615
616                 if (hdr_chk == IPv6_HDR_VERSION) {
617
618                         struct acl_table_entry *entry =
619                             (struct acl_table_entry *)
620                             p_acl->acl_entries_ipv6[pos];
621                         uint16_t phy_port = entry->head.port_id;
622                         uint32_t action_id = entry->action_id;
623
624                         if (ACL_DEBUG)
625                                 printf("action_id = %u\n", action_id);
626
627                         if (action_array_active[action_id].action_bitmap &
628                             acl_action_count) {
629                                 action_counter_table
630                                     [p_acl->action_counter_index]
631                                     [action_id].packetCount++;
632                                 action_counter_table
633                                     [p_acl->action_counter_index]
634                                     [action_id].byteCount +=
635                                     rte_pktmbuf_pkt_len(pkt);
636                                 if (ACL_DEBUG)
637                                         printf("Action Count   Packet Count: %"
638                                                PRIu64 "  Byte Count: %" PRIu64
639                                                "\n",
640                                                action_counter_table
641                                                [p_acl->action_counter_index]
642                                                [action_id].packetCount,
643                                                action_counter_table
644                                                [p_acl->action_counter_index]
645                                                [action_id].byteCount);
646                         }
647
648                         if (action_array_active[action_id].action_bitmap &
649                             acl_action_packet_drop) {
650                                 /* Drop packet by changing the mask */
651                                 if (ACL_DEBUG)
652                                         printf("ACL before drop pkt_mask  "
653                                                         "%lu, pkt_num %d\n",
654                                              pkts_mask, pos);
655                                 pkts_mask &= ~(1LLU << pos);
656                                 if (ACL_DEBUG)
657                                         printf("ACL after drop pkt_mask  "
658                                                         "%lu, pkt_num %d\n",
659                                              pkts_mask, pos);
660                                 p_acl->counters->pkts_drop++;
661
662                         }
663
664                         if (action_array_active[action_id].action_bitmap &
665                             acl_action_fwd) {
666                                 phy_port =
667                                     action_array_active[action_id].fwd_port;
668                                 entry->head.port_id = phy_port;
669                                 if (ACL_DEBUG)
670                                         printf("Action FWD  Port ID: %u\n",
671                                                phy_port);
672                         }
673
674                         if (action_array_active[action_id].action_bitmap &
675                             acl_action_nat) {
676                                 phy_port =
677                                     action_array_active[action_id].nat_port;
678                                 entry->head.port_id = phy_port;
679                                 if (ACL_DEBUG)
680                                         printf("Action NAT  Port ID: %u\n",
681                                                phy_port);
682                         }
683
684                         if (action_array_active[action_id].action_bitmap &
685                             acl_action_dscp) {
686
687                                 /* Set DSCP priority */
688                                 uint32_t dscp_offset =
689                                     MBUF_HDR_ROOM + ETH_HDR_SIZE +
690                                     IP_HDR_DSCP_OFST_IPV6;
691                                 uint16_t *dscp =
692                                     RTE_MBUF_METADATA_UINT16_PTR(pkt,
693                                                                  dscp_offset);
694                                 uint16_t dscp_value =
695                                     (rte_bswap16
696                                      (RTE_MBUF_METADATA_UINT16
697                                       (pkt, dscp_offset)) & 0XF00F);
698                                 uint8_t dscp_store =
699                                     action_array_active[action_id].dscp_priority
700                                     << 2;
701                                 uint16_t dscp_temp = dscp_store;
702
703                                 dscp_temp = dscp_temp << 4;
704                                 *dscp = rte_bswap16(dscp_temp | dscp_value);
705                                 if (ACL_DEBUG)
706                                         printf
707                                             ("Action DSCP  DSCP Priority: %u\n",
708                                              *dscp);
709                         }
710
711                         if (action_array_active[action_id].action_bitmap &
712                             acl_action_packet_accept) {
713                                 if (ACL_DEBUG)
714                                         printf("Action Accept\n");
715
716                                 if (action_array_active[action_id].action_bitmap
717                                     & acl_action_conntrack) {
718
719                                         /* Set conntrack bit for this pkt */
720                                         conntrack_mask |= pkt_mask;
721                                         if (ACL_DEBUG)
722                                                 printf("ACL Conntrack enabled: "
723                                                         " %p  pkt_mask: %p\n",
724                                                      (void *)conntrack_mask,
725                                                      (void *)pkt_mask);
726                                 }
727
728                                 if (action_array_active[action_id].action_bitmap
729                                     & acl_action_connexist) {
730
731                                         /* Set conntrack bit for this pkt */
732                                         conntrack_mask |= pkt_mask;
733
734                 /* Set connexist bit for this pkt for public -> private */
735                 /* Private -> public packet will open the connection */
736                                         if (action_array_active
737                                             [action_id].private_public ==
738                                             acl_public_private)
739                                                 connexist_mask |= pkt_mask;
740
741                                         if (ACL_DEBUG)
742                                                 printf("ACL Connexist enabled  "
743                                 "conntrack: %p  connexist: %p  pkt_mask: %p\n",
744                                                      (void *)conntrack_mask,
745                                                      (void *)connexist_mask,
746                                                      (void *)pkt_mask);
747                                 }
748                         }
749                 }
750         }
751
752         /* Only call connection tracker if required */
753         if (conntrack_mask > 0) {
754                 if (ACL_DEBUG)
755                         printf
756                             ("ACL Call Conntrack Before = %p  Connexist = %p\n",
757                              (void *)conntrack_mask, (void *)connexist_mask);
758                 conntrack_mask =
759                     rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
760                     (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
761                 if (ACL_DEBUG)
762                         printf("ACL Call Conntrack After = %p\n",
763                                (void *)conntrack_mask);
764
765                 /* Only change pkt mask for pkts that have conntrack enabled */
766                 /* Need to loop through packets to check if conntrack enabled */
767                 pkts_to_process = pkts_mask;
768                 for (; pkts_to_process;) {
769                         uint32_t action_id = 0;
770                         uint8_t pos =
771                             (uint8_t) __builtin_ctzll(pkts_to_process);
772                         uint64_t pkt_mask = 1LLU << pos;
773                 /* bitmask representing only this packet */
774
775                         pkts_to_process &= ~pkt_mask;
776                 /* remove this packet from remaining list */
777                         struct rte_mbuf *pkt = pkts[pos];
778
779                         uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
780                                                                   MBUF_HDR_ROOM
781                                                                   +
782                                                                   ETH_HDR_SIZE);
783
784                         hdr_chk = hdr_chk >> IP_VERSION_CHECK;
785                         if (hdr_chk == IPv4_HDR_VERSION) {
786                                 struct acl_table_entry *entry =
787                                     (struct acl_table_entry *)
788                                     p_acl->acl_entries_ipv4[pos];
789                                 action_id = entry->action_id;
790                         } else {
791                                 struct acl_table_entry *entry =
792                                     (struct acl_table_entry *)
793                                     p_acl->acl_entries_ipv6[pos];
794                                 action_id = entry->action_id;
795                         }
796
797                         if ((action_array_active[action_id].action_bitmap &
798                              acl_action_conntrack)
799                             || (action_array_active[action_id].action_bitmap &
800                                 acl_action_connexist)) {
801
802                                 if (conntrack_mask & pkt_mask) {
803                                         if (ACL_DEBUG)
804                                                 printf("ACL Conntrack Accept  "
805                                                                 "packet = %p\n",
806                                                      (void *)pkt_mask);
807                                 } else {
808                                         /* Drop packet by changing the mask */
809                                         if (ACL_DEBUG)
810                                                 printf("ACL Conntrack Drop  "
811                                                                 "packet = %p\n",
812                                                      (void *)pkt_mask);
813                                         pkts_mask &= ~pkt_mask;
814                                         p_acl->counters->pkts_drop++;
815                                 }
816                         }
817                 }
818         }
819
820         pkts_to_process = pkts_mask;
821                 /* bitmap of packets left to process for ARP */
822
823         for (; pkts_to_process;) {
824                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
825                 uint64_t pkt_mask = 1LLU << pos;
826                 /* bitmask representing only this packet */
827
828                 pkts_to_process &= ~pkt_mask;
829                 /* remove this packet from remaining list */
830                 struct rte_mbuf *pkt = pkts[pos];
831
832                 uint8_t hdr_chk =
833                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
834                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
835
836                 if (hdr_chk == IPv4_HDR_VERSION) {
837
838                         struct acl_table_entry *entry =
839                             (struct acl_table_entry *)
840                             p_acl->acl_entries_ipv4[pos];
841                         uint16_t phy_port = pkt->port;
842                         uint32_t *port_out_id =
843                             RTE_MBUF_METADATA_UINT32_PTR(pkt,
844                                                          META_DATA_OFFSET +
845                                                          offsetof(struct
846                                                           mbuf_acl_meta_data,
847                                                                   output_port));
848                         if (ACL_DEBUG)
849                                 printf
850                                    ("phy_port = %i, links_map[phy_port] = %i\n",
851                                      phy_port, p_acl->links_map[phy_port]);
852
853                 /* header room + eth hdr size + dst_adr offset in ip header */
854                         uint32_t dst_addr_offset =
855                             MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
856                         uint32_t *dst_addr =
857                             RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
858                         uint8_t *eth_dest =
859                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
860                         uint8_t *eth_src =
861                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
862                         struct ether_addr hw_addr;
863                         uint32_t dest_address = rte_bswap32(*dst_addr);
864                         uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt,
865                                                               META_DATA_OFFSET
866                                                                       +
867                                                                       offsetof
868                                                                       (struct
869                                                        mbuf_acl_meta_data,
870                                                                        nhip));
871                         uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
872                         *nhip = 0;
873                         struct arp_entry_data *ret_arp_data = NULL;
874                         ret_arp_data = get_dest_mac_addr_port
875                             (dest_address, &dest_if, (struct ether_addr *) eth_dest);
876                         *port_out_id = p_acl->port_out_id[dest_if];
877                         if (arp_cache_dest_mac_present(dest_if)) {
878                                 ether_addr_copy(get_link_hw_addr(dest_if),
879                                          (struct ether_addr *)eth_src);
880                                 update_nhip_access(dest_if);
881                                 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
882                                         printf("sending buffered packets\n");
883                                         arp_send_buffered_pkts(ret_arp_data,
884                                         (struct ether_addr *)eth_dest, *port_out_id);
885
886                                 }
887                                 p_acl->counters->tpkts_processed++;
888                                 p_acl->counters->bytes_processed +=
889                                     packet_length;
890                         } else {
891                                 if (unlikely(ret_arp_data == NULL)) {
892                                         if (ACL_DEBUG)
893                                         printf("%s: NHIP Not Found, "
894                                         "outport_id: %d\n", __func__,
895                                         *port_out_id);
896
897                                         /* Drop the pkt */
898                                         pkts_mask &= ~(1LLU << pos);
899                                         if (ACL_DEBUG)
900                                                 printf("ACL after drop pkt_mask  "
901                                                 "%lu, pkt_num %d\n",
902                                                 pkts_mask, pos);
903                                                 p_acl->counters->pkts_drop++;
904                                                 continue;
905                                 }
906
907                                 if (ret_arp_data->status == INCOMPLETE ||
908                                         ret_arp_data->status == PROBE) {
909                                         if (ret_arp_data->num_pkts >= NUM_DESC) {
910                                                 /* Drop the pkt */
911                                                 pkts_mask &= ~(1LLU << pos);
912                                                 if (ACL_DEBUG)
913                                                         printf("ACL after drop pkt_mask  "
914                                                         "%lu, pkt_num %d\n",
915                                                         pkts_mask, pos);
916                                                 p_acl->counters->pkts_drop++;
917                                                 continue;
918                                         } else {
919                                                 arp_pkts_mask |= pkt_mask;
920                                                 arp_queue_unresolved_packet(ret_arp_data,
921                                                                          pkt);
922                                                 continue;
923                                         }
924                                 }
925                         }
926
927                 } /* end of if (hdr_chk == IPv4_HDR_VERSION) */
928
929                 if (hdr_chk == IPv6_HDR_VERSION) {
930
931                         struct acl_table_entry *entry =
932                             (struct acl_table_entry *)
933                             p_acl->acl_entries_ipv6[pos];
934                         //uint16_t phy_port = entry->head.port_id;
935                         uint16_t phy_port = pkt->port;
936                         uint32_t *port_out_id =
937                             RTE_MBUF_METADATA_UINT32_PTR(pkt,
938                                                          META_DATA_OFFSET +
939                                                          offsetof(struct
940                                                           mbuf_acl_meta_data,
941                                                                   output_port));
942                         /*if (is_phy_port_privte(phy_port))
943                                 *port_out_id = ACL_PUB_PORT_ID;
944                         else
945                                 *port_out_id = ACL_PRV_PORT_ID;*/
946
947                         /*      *port_out_id = p_acl->links_map[phy_port]; */
948                         if (ACL_DEBUG)
949                                 printf("phy_port = %i,  "
950                                         "links_map[phy_port] = %i\n",
951                                      phy_port, p_acl->links_map[phy_port]);
952
953                 /* header room + eth hdr size + dst_adr offset in ip header */
954                         uint32_t dst_addr_offset =
955                             MBUF_HDR_ROOM + ETH_HDR_SIZE +
956                             IP_HDR_DST_ADR_OFST_IPV6;
957                         uint8_t *eth_dest =
958                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
959                         uint8_t *eth_src =
960                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
961                         struct ether_addr hw_addr;
962                         uint8_t dest_address[16];
963                         uint8_t nhip[16];
964
965                         nhip[0] =
966                         RTE_MBUF_METADATA_UINT8(pkt,
967                                                     META_DATA_OFFSET +
968                                                     offsetof(struct
969                                                              mbuf_acl_meta_data,
970                                                              nhip));
971                         uint8_t *dst_addr[16];
972                         uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
973                         int i = 0;
974
975                         for (i = 0; i < 16; i++) {
976                                 dst_addr[i] =
977                                     RTE_MBUF_METADATA_UINT8_PTR(pkt,
978                                                                 dst_addr_offset
979                                                                 + i);
980                         }
981                         memcpy(dest_address, *dst_addr, sizeof(dest_address));
982                         memset(nhip, 0, sizeof(nhip));
983
984                         struct nd_entry_data *ret_nd_data = NULL;
985                         ret_nd_data = get_dest_mac_address_ipv6_port
986                             (dest_address, &dest_if, &hw_addr, &nhip[0]);
987                         *port_out_id = p_acl->port_out_id[dest_if];
988                         if (nd_cache_dest_mac_present(dest_if)) {
989                                 ether_addr_copy(get_link_hw_addr(dest_if),
990                                         (struct ether_addr *)eth_src);
991                                 update_nhip_access(dest_if);
992
993                                 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
994                                         printf("sending buffered packets\n");
995                                         p_acl->counters->tpkts_processed +=
996                                                  ret_nd_data->num_pkts;
997                                         nd_send_buffered_pkts(ret_nd_data,
998                                         (struct ether_addr *)eth_dest, *port_out_id);
999                                 }
1000                                 p_acl->counters->tpkts_processed++;
1001                                 p_acl->counters->bytes_processed +=
1002                                     packet_length;
1003                         } else {
1004                                 if (unlikely(ret_nd_data == NULL)) {
1005                                         if (ACL_DEBUG)
1006                                                 printf("ACL before drop pkt_mask  "
1007                                                 "%lu, pkt_num %d\n", pkts_mask, pos);
1008                                         pkts_mask &= ~(1LLU << pos);
1009                                         if (ACL_DEBUG)
1010                                                 printf("ACL after drop pkt_mask  "
1011                                                 "%lu, pkt_num %d\n", pkts_mask, pos);
1012                                         p_acl->counters->pkts_drop++;
1013                                         continue;
1014                                 }
1015
1016                                 if (ret_nd_data->status == INCOMPLETE ||
1017                                         ret_nd_data->status == PROBE) {
1018                                         if (ret_nd_data->num_pkts >= NUM_DESC) {
1019                                                 /* Drop the pkt */
1020                                                 if (ACL_DEBUG)
1021                                                         printf("ACL before drop pkt_mask  "
1022                                                         "%lu, pkt_num %d\n", pkts_mask, pos);
1023                                                 pkts_mask &= ~(1LLU << pos);
1024                                                 if (ACL_DEBUG)
1025                                                         printf("ACL after drop pkt_mask  "
1026                                                         "%lu, pkt_num %d\n", pkts_mask, pos);
1027                                                 p_acl->counters->pkts_drop++;
1028                                                 continue;
1029                                         } else {
1030                                                 arp_pkts_mask |= pkt_mask;
1031                                                 nd_queue_unresolved_packet(ret_nd_data,
1032                                                                                  pkt);
1033                                                 continue;
1034                                         }
1035                                 }
1036
1037                         }
1038
1039                 } /* if (hdr_chk == IPv6_HDR_VERSION) */
1040
1041         }
1042
1043         pkts_drop_mask = keep_mask & ~pkts_mask;
1044         rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
1045         keep_mask = pkts_mask;
1046
1047         if (arp_pkts_mask) {
1048                 keep_mask &= ~(arp_pkts_mask);
1049                 rte_pipeline_ah_packet_hijack(p, arp_pkts_mask);
1050         }
1051
1052         /* don't bother measuring if traffic very low, might skew stats */
1053         uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
1054
1055         if (packets_this_iteration > 1) {
1056                 uint64_t latency_this_iteration =
1057                     rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
1058
1059                 p_acl->counters->sum_latencies += latency_this_iteration;
1060                 p_acl->counters->count_latencies++;
1061         }
1062
1063         if (ACL_DEBUG)
1064                 printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
1065                        (void *)pkts_mask);
1066
1067         return 0;
1068 }
1069
1070 /**
1071  * Main packet processing function.
1072  * 64 packet bit mask are used to identify which packets to forward.
1073  * Performs the following:
1074  *  - Burst lookup packets in the IPv4 ACL Rule Table.
1075  *  - Burst lookup packets in the IPv6 ACL Rule Table.
1076  *  - Lookup Action Table, perform actions.
1077  *  - Burst lookup Connection Tracking, if enabled.
1078  *  - Lookup MAC address.
1079  *  - Set bit mask.
1080  *  - Packets with bit mask set are forwarded
1081  *
1082  * @param p
1083  *  A pointer to the pipeline.
1084  * @param pkts
1085  *  A pointer to a burst of packets.
1086  * @param n_pkts
1087  *  Number of packets to process.
1088  * @param arg
1089  *  A pointer to pipeline specific data.
1090  *
1091  * @return
1092  *  0 on success, negative on error.
1093  */
1094 static int
1095 pkt_work_acl_ipv4_key(struct rte_pipeline *p,
1096                       struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
1097 {
1098
1099         struct pipeline_acl *p_acl = arg;
1100
1101         p_acl->counters->pkts_received =
1102             p_acl->counters->pkts_received + n_pkts;
1103         if (ACL_DEBUG)
1104                 printf("pkt_work_acl_key pkts_received: %" PRIu64
1105                        " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
1106
1107         uint64_t lookup_hit_mask = 0;
1108         uint64_t lookup_hit_mask_ipv4 = 0;
1109         uint64_t lookup_hit_mask_ipv6 = 0;
1110         uint64_t lookup_miss_mask = 0;
1111         uint64_t conntrack_mask = 0;
1112         uint64_t connexist_mask = 0;
1113         uint32_t dest_address = 0;
1114         arp_pkts_mask = 0;
1115         int dest_if = 0;
1116         int status;
1117         uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
1118         uint64_t keep_mask = pkts_mask;
1119         uint16_t port;
1120         uint32_t ret;
1121
1122         p_acl->in_port_time_stamp = rte_get_tsc_cycles();
1123
1124         if (acl_ipv4_enabled) {
1125                 if (ACL_DEBUG)
1126                         printf("ACL IPV4 Lookup Mask Before = %p\n",
1127                                (void *)pkts_mask);
1128                 status =
1129                     rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts,
1130                                                pkts_mask, &lookup_hit_mask_ipv4,
1131                                                (void **)
1132                                                p_acl->acl_entries_ipv4);
1133                 if (ACL_DEBUG)
1134                         printf("ACL IPV4 Lookup Mask After = %p\n",
1135                                (void *)lookup_hit_mask_ipv4);
1136         }
1137
1138         /* Merge lookup results since we process both IPv4 and IPv6 below */
1139         lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
1140         if (ACL_DEBUG)
1141                 printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
1142
1143         lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
1144         pkts_mask = lookup_hit_mask;
1145         p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
1146         if (ACL_DEBUG)
1147                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
1148                        p_acl->counters->pkts_drop,
1149                        __builtin_popcountll(lookup_miss_mask));
1150
1151         uint64_t pkts_to_process = lookup_hit_mask;
1152                 /* bitmap of packets left to process for ARP */
1153
1154         for (; pkts_to_process;) {
1155                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
1156                 uint64_t pkt_mask = 1LLU << pos;
1157                 /* bitmask representing only this packet */
1158
1159                 pkts_to_process &= ~pkt_mask;
1160                 /* remove this packet from remaining list */
1161                 struct rte_mbuf *pkt = pkts[pos];
1162
1163                 if (enable_hwlb)
1164                         if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
1165                                 pkts_mask &= ~(1LLU << pos);
1166                                 continue;
1167                         }
1168
1169                 uint8_t hdr_chk =
1170                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
1171                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
1172
1173                 if (hdr_chk == IPv4_HDR_VERSION) {
1174                         struct acl_table_entry *entry =
1175                             (struct acl_table_entry *)
1176                             p_acl->acl_entries_ipv4[pos];
1177                         uint16_t phy_port = entry->head.port_id;
1178                         uint32_t action_id = entry->action_id;
1179
1180                         if (ACL_DEBUG)
1181                                 printf("action_id = %u\n", action_id);
1182
1183                         uint32_t dscp_offset =
1184                             MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
1185
1186                         if (action_array_active[action_id].action_bitmap &
1187                             acl_action_count) {
1188                                 action_counter_table
1189                                     [p_acl->action_counter_index]
1190                                     [action_id].packetCount++;
1191                                 action_counter_table
1192                                     [p_acl->action_counter_index]
1193                                     [action_id].byteCount +=
1194                                     rte_pktmbuf_pkt_len(pkt);
1195                                 if (ACL_DEBUG)
1196                                         printf("Action Count   Packet Count: %"
1197                                                PRIu64 "  Byte Count: %" PRIu64
1198                                                "\n",
1199                                                action_counter_table
1200                                                [p_acl->action_counter_index]
1201                                                [action_id].packetCount,
1202                                                action_counter_table
1203                                                [p_acl->action_counter_index]
1204                                                [action_id].byteCount);
1205                         }
1206
1207                         if (action_array_active[action_id].action_bitmap &
1208                             acl_action_packet_drop) {
1209
1210                                 /* Drop packet by changing the mask */
1211                                 if (ACL_DEBUG)
1212                                         printf("ACL before drop pkt_mask  "
1213                                                         "%lu, pkt_num %d\n",
1214                                              pkts_mask, pos);
1215                                 pkts_mask &= ~(1LLU << pos);
1216                                 if (ACL_DEBUG)
1217                                         printf("ACL after drop pkt_mask "
1218                                                         " %lu, pkt_num %d\n",
1219                                              pkts_mask, pos);
1220                                 p_acl->counters->pkts_drop++;
1221                         }
1222
1223                         if (action_array_active[action_id].action_bitmap &
1224                             acl_action_fwd) {
1225                                 phy_port =
1226                                     action_array_active[action_id].fwd_port;
1227                                 entry->head.port_id = phy_port;
1228                                 if (ACL_DEBUG)
1229                                         printf("Action FWD  Port ID: %u\n",
1230                                                phy_port);
1231                         }
1232
1233                         if (action_array_active[action_id].action_bitmap &
1234                             acl_action_nat) {
1235                                 phy_port =
1236                                     action_array_active[action_id].nat_port;
1237                                 entry->head.port_id = phy_port;
1238                                 if (ACL_DEBUG)
1239                                         printf("Action NAT  Port ID: %u\n",
1240                                                phy_port);
1241                         }
1242
1243                         if (action_array_active[action_id].action_bitmap &
1244                             acl_action_dscp) {
1245
1246                                 /* Set DSCP priority */
1247                                 uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1248                                                             dscp_offset);
1249                                 *dscp =
1250                                     action_array_active[action_id].dscp_priority
1251                                     << 2;
1252                                 if (ACL_DEBUG)
1253                                         printf
1254                                             ("Action DSCP  DSCP Priority: %u\n",
1255                                              *dscp);
1256                         }
1257
1258                         if (action_array_active[action_id].action_bitmap &
1259                             acl_action_packet_accept) {
1260                                 if (ACL_DEBUG)
1261                                         printf("Action Accept\n");
1262
1263                                 if (action_array_active[action_id].action_bitmap
1264                                     & acl_action_conntrack) {
1265
1266                                         /* Set conntrack bit for this pkt */
1267                                         conntrack_mask |= pkt_mask;
1268                                         if (ACL_DEBUG)
1269                                                 printf("ACL Conntrack  "
1270                                                 "enabled: %p  pkt_mask: %p\n",
1271                                                      (void *)conntrack_mask,
1272                                                      (void *)pkt_mask);
1273                                 }
1274
1275                                 if (action_array_active[action_id].action_bitmap
1276                                     & acl_action_connexist) {
1277
1278                                         /* Set conntrack bit for this pkt */
1279                                         conntrack_mask |= pkt_mask;
1280
1281                 /* Set connexist bit for this pkt for public -> private */
1282                 /* Private -> public packet will open the connection */
1283                                         if (action_array_active
1284                                             [action_id].private_public ==
1285                                             acl_public_private)
1286                                                 connexist_mask |= pkt_mask;
1287
1288                                         if (ACL_DEBUG)
1289                                                 printf("ACL Connexist  "
1290                         "enabled conntrack: %p  connexist: %p  pkt_mask: %p\n",
1291                                                      (void *)conntrack_mask,
1292                                                      (void *)connexist_mask,
1293                                                      (void *)pkt_mask);
1294                                 }
1295                         }
1296                 }
1297 #if 0
1298                 if (hdr_chk == IPv6_HDR_VERSION) {
1299
1300                         struct acl_table_entry *entry =
1301                             (struct acl_table_entry *)
1302                             p_acl->acl_entries_ipv6[pos];
1303                         uint16_t phy_port = entry->head.port_id;
1304                         uint32_t action_id = entry->action_id;
1305
1306                         if (ACL_DEBUG)
1307                                 printf("action_id = %u\n", action_id);
1308
1309                         if (action_array_active[action_id].action_bitmap &
1310                             acl_action_count) {
1311                                 action_counter_table
1312                                     [p_acl->action_counter_index]
1313                                     [action_id].packetCount++;
1314                                 action_counter_table
1315                                     [p_acl->action_counter_index]
1316                                     [action_id].byteCount +=
1317                                     rte_pktmbuf_pkt_len(pkt);
1318                                 if (ACL_DEBUG)
1319                                         printf("Action Count   Packet Count: %"
1320                                                PRIu64 "  Byte Count: %" PRIu64
1321                                                "\n",
1322                                                action_counter_table
1323                                                [p_acl->action_counter_index]
1324                                                [action_id].packetCount,
1325                                                action_counter_table
1326                                                [p_acl->action_counter_index]
1327                                                [action_id].byteCount);
1328                         }
1329
1330                         if (action_array_active[action_id].action_bitmap &
1331                             acl_action_packet_drop) {
1332                                 /* Drop packet by changing the mask */
1333                                 if (ACL_DEBUG)
1334                                         printf
1335                             ("ACL before drop pkt_mask %lu, pkt_num %d\n",
1336                                              pkts_mask, pos);
1337                                 pkts_mask &= ~(1LLU << pos);
1338                                 if (ACL_DEBUG)
1339                                         printf
1340                          ("ACL after drop pkt_mask %lu, pkt_num %d\n",
1341                                              pkts_mask, pos);
1342                                 p_acl->counters->pkts_drop++;
1343
1344                         }
1345
1346                         if (action_array_active[action_id].action_bitmap &
1347                             acl_action_fwd) {
1348                                 phy_port =
1349                                     action_array_active[action_id].fwd_port;
1350                                 entry->head.port_id = phy_port;
1351                                 if (ACL_DEBUG)
1352                                         printf("Action FWD  Port ID: %u\n",
1353                                                phy_port);
1354                         }
1355
1356                         if (action_array_active[action_id].action_bitmap &
1357                             acl_action_nat) {
1358                                 phy_port =
1359                                     action_array_active[action_id].nat_port;
1360                                 entry->head.port_id = phy_port;
1361                                 if (ACL_DEBUG)
1362                                         printf("Action NAT  Port ID: %u\n",
1363                                                phy_port);
1364                         }
1365
1366                         if (action_array_active[action_id].action_bitmap &
1367                             acl_action_dscp) {
1368
1369                                 /* Set DSCP priority */
1370                                 uint32_t dscp_offset =
1371                                     MBUF_HDR_ROOM + ETH_HDR_SIZE +
1372                                     IP_HDR_DSCP_OFST_IPV6;
1373                                 uint16_t *dscp =
1374                                     RTE_MBUF_METADATA_UINT16_PTR(pkt,
1375                                                                  dscp_offset);
1376                                 uint16_t dscp_value =
1377                                     (rte_bswap16
1378                                      (RTE_MBUF_METADATA_UINT16
1379                                       (pkt, dscp_offset)) & 0XF00F);
1380                                 uint8_t dscp_store =
1381                                     action_array_active[action_id].dscp_priority
1382                                     << 2;
1383                                 uint16_t dscp_temp = dscp_store;
1384
1385                                 dscp_temp = dscp_temp << 4;
1386                                 *dscp = rte_bswap16(dscp_temp | dscp_value);
1387                                 if (ACL_DEBUG)
1388                                         printf
1389                                     ("Action DSCP   DSCP Priority: %u\n",
1390                                              *dscp);
1391                         }
1392
1393                         if (action_array_active[action_id].action_bitmap &
1394                             acl_action_packet_accept) {
1395                                 if (ACL_DEBUG)
1396                                         printf("Action Accept\n");
1397
1398                                 if (action_array_active[action_id].action_bitmap
1399                                     & acl_action_conntrack) {
1400
1401                                         /* Set conntrack bit for this pkt */
1402                                         conntrack_mask |= pkt_mask;
1403                                         if (ACL_DEBUG)
1404                                                 printf("ACL Conntrack  "
1405                                                 "enabled: %p  pkt_mask: %p\n",
1406                                                      (void *)conntrack_mask,
1407                                                      (void *)pkt_mask);
1408                                 }
1409
1410                                 if (action_array_active[action_id].action_bitmap
1411                                     & acl_action_connexist) {
1412
1413                                         /* Set conntrack bit for this pkt */
1414                                         conntrack_mask |= pkt_mask;
1415
1416                 /* Set connexist bit for this pkt for public -> private */
1417                 /* Private -> public packet will open the connection */
1418                                         if (action_array_active
1419                                             [action_id].private_public ==
1420                                             acl_public_private)
1421                                                 connexist_mask |= pkt_mask;
1422
1423                                         if (ACL_DEBUG)
1424                                                 printf("ACL Connexist enabled  "
1425                                 "conntrack: %p  connexist: %p  pkt_mask: %p\n",
1426                                                      (void *)conntrack_mask,
1427                                                      (void *)connexist_mask,
1428                                                      (void *)pkt_mask);
1429                                 }
1430                         }
1431                 }
1432 #endif
1433         }
1434         /* Only call connection tracker if required */
1435         if (conntrack_mask > 0) {
1436                 if (ACL_DEBUG)
1437                         printf
1438                             ("ACL Call Conntrack Before = %p  Connexist = %p\n",
1439                              (void *)conntrack_mask, (void *)connexist_mask);
1440                 conntrack_mask =
1441                     rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
1442                     (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
1443                 if (ACL_DEBUG)
1444                         printf("ACL Call Conntrack After = %p\n",
1445                                (void *)conntrack_mask);
1446
1447                 /* Only change pkt mask for pkts that have conntrack enabled */
1448                 /* Need to loop through packets to check if conntrack enabled */
1449                 pkts_to_process = pkts_mask;
1450                 for (; pkts_to_process;) {
1451                         uint32_t action_id = 0;
1452                         uint8_t pos =
1453                             (uint8_t) __builtin_ctzll(pkts_to_process);
1454                         uint64_t pkt_mask = 1LLU << pos;
1455                 /* bitmask representing only this packet */
1456
1457                         pkts_to_process &= ~pkt_mask;
1458                 /* remove this packet from remaining list */
1459                         struct rte_mbuf *pkt = pkts[pos];
1460
1461                         uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
1462                                                                   MBUF_HDR_ROOM
1463                                                                   +
1464                                                                   ETH_HDR_SIZE);
1465                         hdr_chk = hdr_chk >> IP_VERSION_CHECK;
1466                         if (hdr_chk == IPv4_HDR_VERSION) {
1467                                 struct acl_table_entry *entry =
1468                                     (struct acl_table_entry *)
1469                                     p_acl->acl_entries_ipv4[pos];
1470                                 action_id = entry->action_id;
1471                         } else {
1472                                 struct acl_table_entry *entry =
1473                                     (struct acl_table_entry *)
1474                                     p_acl->acl_entries_ipv6[pos];
1475                                 action_id = entry->action_id;
1476                         }
1477
1478                         if ((action_array_active[action_id].action_bitmap &
1479                              acl_action_conntrack)
1480                             || (action_array_active[action_id].action_bitmap &
1481                                 acl_action_connexist)) {
1482
1483                                 if (conntrack_mask & pkt_mask) {
1484                                         if (ACL_DEBUG)
1485                                                 printf("ACL Conntrack Accept  "
1486                                                                 "packet = %p\n",
1487                                                      (void *)pkt_mask);
1488                                 } else {
1489 /* Drop packet by changing the mask */
1490                                         if (ACL_DEBUG)
1491                                                 printf("ACL Conntrack Drop  "
1492                                                                 "packet = %p\n",
1493                                                      (void *)pkt_mask);
1494                                         pkts_mask &= ~pkt_mask;
1495                                         p_acl->counters->pkts_drop++;
1496                                 }
1497                         }
1498                 }
1499         }
1500
1501         pkts_to_process = pkts_mask;
1502         /* bitmap of packets left to process for ARP */
1503
1504         for (; pkts_to_process;) {
1505                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
1506                 uint64_t pkt_mask = 1LLU << pos;
1507         /* bitmask representing only this packet */
1508
1509                 pkts_to_process &= ~pkt_mask;
1510         /* remove this packet from remaining list */
1511                 struct rte_mbuf *pkt = pkts[pos];
1512
1513                 uint8_t hdr_chk =
1514                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
1515                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
1516
1517                 if (hdr_chk == IPv4_HDR_VERSION) {
1518
1519                         struct acl_table_entry *entry =
1520                             (struct acl_table_entry *)
1521                             p_acl->acl_entries_ipv4[pos];
1522                         //uint16_t phy_port = entry->head.port_id;
1523                         uint16_t phy_port = pkt->port;
1524                         uint32_t *port_out_id =
1525                             RTE_MBUF_METADATA_UINT32_PTR(pkt,
1526                                                          META_DATA_OFFSET +
1527                                                          offsetof(struct
1528                                                           mbuf_acl_meta_data,
1529                                                                   output_port));
1530                         /*  *port_out_id = p_acl->links_map[phy_port]; */
1531 /*                      if (is_phy_port_privte(phy_port))
1532                                 *port_out_id = ACL_PUB_PORT_ID;
1533                         else
1534                                 *port_out_id = ACL_PRV_PORT_ID;*/
1535                         if (ACL_DEBUG)
1536                                 printf
1537                                    ("phy_port = %i, links_map[phy_port] = %i\n",
1538                                      phy_port, p_acl->links_map[phy_port]);
1539
1540         /* header room + eth hdr size + dst_adr offset in ip header */
1541                         uint32_t dst_addr_offset =
1542                             MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
1543                         uint32_t *dst_addr =
1544                             RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
1545                         uint8_t *eth_dest =
1546                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1547                         uint8_t *eth_src =
1548                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1549                         struct ether_addr hw_addr;
1550                         uint32_t dest_address = rte_bswap32(*dst_addr);
1551                         uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt,
1552                                                               META_DATA_OFFSET
1553                                                                       +
1554                                                                       offsetof
1555                                                                       (struct
1556                                                        mbuf_acl_meta_data,
1557                                                                        nhip));
1558                         uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
1559                         *nhip = 0;
1560                         dest_address = rte_bswap32(*dst_addr);
1561                         struct arp_entry_data *ret_arp_data = NULL;
1562                         ret_arp_data = get_dest_mac_addr_port
1563                             (dest_address, &dest_if, (struct ether_addr *)eth_dest);
1564                         *port_out_id = p_acl->port_out_id[dest_if];
1565
1566                         if (arp_cache_dest_mac_present(dest_if)) {
1567                                 ether_addr_copy(get_link_hw_addr(dest_if),
1568                                          (struct ether_addr *)eth_src);
1569                                 update_nhip_access(dest_if);
1570                                 if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) {
1571                                         printf("sending buffered packets\n");
1572                                         arp_send_buffered_pkts(ret_arp_data,
1573                                         (struct ether_addr *)eth_dest, *port_out_id);
1574
1575                                 }
1576                                 p_acl->counters->tpkts_processed++;
1577                                 p_acl->counters->bytes_processed +=
1578                                     packet_length;
1579                         } else {
1580                                 if (unlikely(ret_arp_data == NULL)) {
1581
1582                                         if (ACL_DEBUG)
1583                                         printf("%s: NHIP Not Found, "
1584                                         "outport_id: %d\n", __func__,
1585                                         *port_out_id);
1586
1587                                         /* Drop the pkt */
1588                                         pkts_mask &= ~(1LLU << pos);
1589                                         if (ACL_DEBUG)
1590                                                 printf("ACL after drop pkt_mask  "
1591                                                 "%lu, pkt_num %d\n",
1592                                                 pkts_mask, pos);
1593                                                 p_acl->counters->pkts_drop++;
1594                                         continue;
1595                                 }
1596
1597                                 if (ret_arp_data->status == INCOMPLETE ||
1598                                 ret_arp_data->status == PROBE) {
1599                                         if (ret_arp_data->num_pkts >= NUM_DESC) {
1600                                                 /* Drop the pkt */
1601                                                 pkts_mask &= ~(1LLU << pos);
1602                                                 if (ACL_DEBUG)
1603                                                         printf("ACL after drop pkt_mask  "
1604                                                         "%lu, pkt_num %d\n",
1605                                                         pkts_mask, pos);
1606                                                 p_acl->counters->pkts_drop++;
1607                                                 continue;
1608                                         } else {
1609                                         arp_pkts_mask |= pkt_mask;
1610                                         arp_queue_unresolved_packet(ret_arp_data, pkt);
1611                                         continue;
1612                                         }
1613                                 }
1614                         }
1615                 }
1616 #if 0
1617                 if (hdr_chk == IPv6_HDR_VERSION) {
1618
1619                         struct acl_table_entry *entry =
1620                             (struct acl_table_entry *)
1621                             p_acl->acl_entries_ipv6[pos];
1622                         uint16_t phy_port = entry->head.port_id;
1623                         uint32_t *port_out_id =
1624                             RTE_MBUF_METADATA_UINT32_PTR(pkt,
1625                                                          META_DATA_OFFSET +
1626                                                          offsetof(struct
1627                                                           mbuf_acl_meta_data,
1628                                                                   output_port));
1629                         if (is_phy_port_privte(phy_port))
1630                                 *port_out_id = ACL_PUB_PORT_ID;
1631                         else
1632                                 *port_out_id = ACL_PRV_PORT_ID;
1633
1634                         /*  *port_out_id = p_acl->links_map[phy_port]; */
1635                         if (ACL_DEBUG)
1636                                 printf
1637                             ("phy_port = %i, links_map[phy_port] = %i\n",
1638                                      phy_port, p_acl->links_map[phy_port]);
1639
1640         /* header room + eth hdr size + dst_adr offset in ip header */
1641                         uint32_t dst_addr_offset =
1642                             MBUF_HDR_ROOM + ETH_HDR_SIZE +
1643                             IP_HDR_DST_ADR_OFST_IPV6;
1644                         uint8_t *eth_dest =
1645                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1646                         uint8_t *eth_src =
1647                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1648                         struct ether_addr hw_addr;
1649                         uint8_t dest_address[16];
1650                         uint8_t nhip[16];
1651
1652                         nhip[0] =
1653                             RTE_MBUF_METADATA_UINT8(pkt,
1654                                                     META_DATA_OFFSET +
1655                                                     offsetof(struct
1656                                                              mbuf_acl_meta_data,
1657                                                              nhip));
1658                         uint8_t *dst_addr[16];
1659                         uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
1660                         int i = 0;
1661
1662                         for (i = 0; i < 16; i++) {
1663                                 dst_addr[i] =
1664                                     RTE_MBUF_METADATA_UINT8_PTR(pkt,
1665                                                                 dst_addr_offset
1666                                                                 + i);
1667                         }
1668                         memcpy(dest_address, *dst_addr, sizeof(dest_address));
1669                         memset(nhip, 0, sizeof(nhip));
1670                         if (is_phy_port_privte(phy_port))
1671                                 port = ACL_PUB_PORT_ID;
1672                         else
1673                                 port = ACL_PRV_PORT_ID;
1674
1675                         if (get_dest_mac_address_ipv6_port
1676                             (dest_address, port, &hw_addr, &nhip[0])) {
1677                                 if (ACL_DEBUG) {
1678
1679                                         printf
1680             ("MAC found for  port %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
1681                                              phy_port, hw_addr.addr_bytes[0],
1682                                              hw_addr.addr_bytes[1],
1683                                              hw_addr.addr_bytes[2],
1684                                              hw_addr.addr_bytes[3],
1685                                              hw_addr.addr_bytes[4],
1686                                              hw_addr.addr_bytes[5]);
1687                                         printf
1688                     ("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x\n",
1689                                              eth_dest[0], eth_dest[1],
1690                                              eth_dest[2], eth_dest[3],
1691                                              eth_dest[4], eth_dest[5]);
1692                                 }
1693                                 memcpy(eth_dest, &hw_addr,
1694                                        sizeof(struct ether_addr));
1695                                 if (ACL_DEBUG) {
1696                                         printf("PktP %p, dest_macP %p\n", pkt,
1697                                                eth_dest);
1698                                         printf
1699                             ("Dest MAC after - %02x:%02x:%02x:%02x:%02x:%02x\n",
1700                                              eth_dest[0], eth_dest[1],
1701                                              eth_dest[2], eth_dest[3],
1702                                              eth_dest[4], eth_dest[5]);
1703                                 }
1704                                 if (is_phy_port_privte(phy_port))
1705                                         memcpy(eth_src,
1706                                                get_link_hw_addr(dest_if),
1707                                                sizeof(struct ether_addr));
1708                                 else
1709                                         memcpy(eth_src,
1710                                                get_link_hw_addr(dest_if),
1711                                                sizeof(struct ether_addr));
1712
1713                 /*
1714                  * memcpy(eth_src, get_link_hw_addr(p_acl->links_map[phy_port]),
1715                  * sizeof(struct ether_addr));
1716                  */
1717                                 p_acl->counters->tpkts_processed++;
1718                                 p_acl->counters->bytes_processed +=
1719                                     packet_length;
1720                         }
1721
1722                         else {
1723
1724                                 /* Drop packet by changing the mask */
1725                                 if (ACL_DEBUG)
1726                                         printf("ACL before drop pkt_mask "
1727                                                         " %lu, pkt_num %d\n",
1728                                              pkts_mask, pos);
1729                                 pkts_mask &= ~(1LLU << pos);
1730                                 if (ACL_DEBUG)
1731                                         printf("ACL after drop pkt_mask  "
1732                                                         "%lu, pkt_num %d\n",
1733                                              pkts_mask, pos);
1734                                 p_acl->counters->pkts_drop++;
1735                         }
1736                 }
1737 #endif
1738
1739         }
1740
1741         pkts_drop_mask = keep_mask & ~pkts_mask;
1742         rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
1743         keep_mask = pkts_mask;
1744
1745         if (arp_pkts_mask) {
1746                 keep_mask &= ~(arp_pkts_mask);
1747                 rte_pipeline_ah_packet_hijack(p, arp_pkts_mask);
1748         }
1749
1750         /* don't bother measuring if traffic very low, might skew stats */
1751         uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
1752
1753         if (packets_this_iteration > 1) {
1754                 uint64_t latency_this_iteration =
1755                     rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
1756                 p_acl->counters->sum_latencies += latency_this_iteration;
1757                 p_acl->counters->count_latencies++;
1758         }
1759         if (ACL_DEBUG)
1760                 printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
1761                         (void *)pkts_mask);
1762
1763         return 0;
1764 }
1765
1766 /**
1767  * Main packet processing function.
1768  * 64 packet bit mask are used to identify which packets to forward.
1769  * Performs the following:
1770  *  - Burst lookup packets in the IPv4 ACL Rule Table.
1771  *  - Burst lookup packets in the IPv6 ACL Rule Table.
1772  *  - Lookup Action Table, perform actions.
1773  *  - Burst lookup Connection Tracking, if enabled.
1774  *  - Lookup MAC address.
1775  *  - Set bit mask.
1776  *  - Packets with bit mask set are forwarded
1777  *
1778  * @param p
1779  *  A pointer to the pipeline.
1780  * @param pkts
1781  *  A pointer to a burst of packets.
1782  * @param n_pkts
1783  *  Number of packets to process.
1784  * @param arg
1785  *  A pointer to pipeline specific data.
1786  *
1787  * @return
1788  *  0 on success, negative on error.
1789  */
1790 static int
1791 pkt_work_acl_ipv6_key(struct rte_pipeline *p,
1792                       struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
1793 {
1794
1795         struct pipeline_acl *p_acl = arg;
1796
1797         p_acl->counters->pkts_received =
1798             p_acl->counters->pkts_received + n_pkts;
1799         if (ACL_DEBUG)
1800                 printf("pkt_work_acl_key pkts_received: %" PRIu64
1801                        " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
1802
1803         uint64_t lookup_hit_mask = 0;
1804         uint64_t lookup_hit_mask_ipv4 = 0;
1805         uint64_t lookup_hit_mask_ipv6 = 0;
1806         uint64_t lookup_miss_mask = 0;
1807         uint64_t conntrack_mask = 0;
1808         uint64_t connexist_mask = 0;
1809         uint32_t dest_address = 0;
1810         arp_pkts_mask = 0;
1811         int dest_if = 0;
1812         int status;
1813         uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
1814         uint64_t keep_mask = pkts_mask;
1815         uint16_t port;
1816         uint32_t ret;
1817
1818         p_acl->in_port_time_stamp = rte_get_tsc_cycles();
1819
1820         if (acl_ipv6_enabled) {
1821                 if (ACL_DEBUG)
1822                         printf("ACL IPV6 Lookup Mask Before = %p\n",
1823                                (void *)pkts_mask);
1824                 status =
1825                     rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts,
1826                                                pkts_mask, &lookup_hit_mask_ipv6,
1827                                                (void **)
1828                                                p_acl->acl_entries_ipv6);
1829                 if (ACL_DEBUG)
1830                         printf("ACL IPV6 Lookup Mask After = %p\n",
1831                                (void *)lookup_hit_mask_ipv6);
1832         }
1833
1834         /* Merge lookup results since we process both IPv4 and IPv6 below */
1835         lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
1836         if (ACL_DEBUG)
1837                 printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
1838
1839         lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
1840         pkts_mask = lookup_hit_mask;
1841         p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
1842         if (ACL_DEBUG)
1843                 printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
1844                        p_acl->counters->pkts_drop,
1845                        __builtin_popcountll(lookup_miss_mask));
1846
1847         uint64_t pkts_to_process = lookup_hit_mask;
1848                 /* bitmap of packets left to process for ARP */
1849
1850         for (; pkts_to_process;) {
1851                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
1852                 uint64_t pkt_mask = 1LLU << pos;
1853                 /* bitmask representing only this packet */
1854
1855                 pkts_to_process &= ~pkt_mask;
1856                 /* remove this packet from remaining list */
1857                 struct rte_mbuf *pkt = pkts[pos];
1858
1859                 if (enable_hwlb)
1860                         if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
1861                                 pkts_mask &= ~(1LLU << pos);
1862                                 continue;
1863                         }
1864                 uint8_t hdr_chk =
1865                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
1866                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
1867 #if 0
1868                 if (hdr_chk == IPv4_HDR_VERSION) {
1869                         struct acl_table_entry *entry =
1870                             (struct acl_table_entry *)
1871                             p_acl->acl_entries_ipv4[pos];
1872                         uint16_t phy_port = entry->head.port_id;
1873                         uint32_t action_id = entry->action_id;
1874
1875                         if (ACL_DEBUG)
1876                                 printf("action_id = %u\n", action_id);
1877
1878                         uint32_t dscp_offset =
1879                             MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
1880
1881                         if (action_array_active[action_id].action_bitmap &
1882                             acl_action_count) {
1883                                 action_counter_table
1884                                     [p_acl->action_counter_index]
1885                                     [action_id].packetCount++;
1886                                 action_counter_table
1887                                     [p_acl->action_counter_index]
1888                                     [action_id].byteCount +=
1889                                     rte_pktmbuf_pkt_len(pkt);
1890                                 if (ACL_DEBUG)
1891                                         printf("Action Count   Packet Count: %"
1892                                                PRIu64 "  Byte Count: %" PRIu64
1893                                                "\n",
1894                                                action_counter_table
1895                                                [p_acl->action_counter_index]
1896                                                [action_id].packetCount,
1897                                                action_counter_table
1898                                                [p_acl->action_counter_index]
1899                                                [action_id].byteCount);
1900                         }
1901
1902                         if (action_array_active[action_id].action_bitmap &
1903                             acl_action_packet_drop) {
1904
1905                                 /* Drop packet by changing the mask */
1906                                 if (ACL_DEBUG)
1907                                         printf
1908                             ("ACL before drop pkt_mask %lu, pkt_num %d\n",
1909                                              pkts_mask, pos);
1910                                 pkts_mask &= ~(1LLU << pos);
1911                                 if (ACL_DEBUG)
1912                                         printf
1913                           ("ACL after drop pkt_mask %lu, pkt_num %d\n",
1914                                              pkts_mask, pos);
1915                                 p_acl->counters->pkts_drop++;
1916                         }
1917
1918                         if (action_array_active[action_id].action_bitmap &
1919                             acl_action_fwd) {
1920                                 phy_port =
1921                                     action_array_active[action_id].fwd_port;
1922                                 entry->head.port_id = phy_port;
1923                                 if (ACL_DEBUG)
1924                                         printf("Action FWD  Port ID: %u\n",
1925                                                phy_port);
1926                         }
1927
1928                         if (action_array_active[action_id].action_bitmap &
1929                             acl_action_nat) {
1930                                 phy_port =
1931                                     action_array_active[action_id].nat_port;
1932                                 entry->head.port_id = phy_port;
1933                                 if (ACL_DEBUG)
1934                                         printf("Action NAT  Port ID: %u\n",
1935                                                phy_port);
1936                         }
1937
1938                         if (action_array_active[action_id].action_bitmap &
1939                             acl_action_dscp) {
1940
1941                                 /* Set DSCP priority */
1942                                 uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
1943                                                             dscp_offset);
1944                                 *dscp =
1945                                     action_array_active[action_id].dscp_priority
1946                                     << 2;
1947                                 if (ACL_DEBUG)
1948                                         printf
1949                                             ("Action DSCP  DSCP Priority: %u\n",
1950                                              *dscp);
1951                         }
1952
1953                         if (action_array_active[action_id].action_bitmap &
1954                             acl_action_packet_accept) {
1955                                 if (ACL_DEBUG)
1956                                         printf("Action Accept\n");
1957
1958                                 if (action_array_active[action_id].action_bitmap
1959                                     & acl_action_conntrack) {
1960
1961                                         /* Set conntrack bit for this pkt */
1962                                         conntrack_mask |= pkt_mask;
1963                                         if (ACL_DEBUG)
1964                                                 printf("ACL Conntrack enabled: "
1965                                                         " %p  pkt_mask: %p\n",
1966                                                      (void *)conntrack_mask,
1967                                                      (void *)pkt_mask);
1968                                 }
1969
1970                                 if (action_array_active[action_id].action_bitmap
1971                                     & acl_action_connexist) {
1972
1973                                         /* Set conntrack bit for this pkt */
1974                                         conntrack_mask |= pkt_mask;
1975
1976                 /* Set connexist bit for this pkt for public -> private */
1977                         /* Private -> public packet will open the connection */
1978                                         if (action_array_active
1979                                             [action_id].private_public ==
1980                                             acl_public_private)
1981                                                 connexist_mask |= pkt_mask;
1982
1983                                         if (ACL_DEBUG)
1984                                                 printf("ACL Connexist enabled  "
1985                                 "conntrack: %p  connexist: %p  pkt_mask: %p\n",
1986                                                      (void *)conntrack_mask,
1987                                                      (void *)connexist_mask,
1988                                                      (void *)pkt_mask);
1989                                 }
1990                         }
1991                 }
1992 #endif
1993
1994                 if (hdr_chk == IPv6_HDR_VERSION) {
1995
1996                         struct acl_table_entry *entry =
1997                             (struct acl_table_entry *)
1998                             p_acl->acl_entries_ipv6[pos];
1999                         uint16_t phy_port = entry->head.port_id;
2000                         uint32_t action_id = entry->action_id;
2001
2002                         if (ACL_DEBUG)
2003                                 printf("action_id = %u\n", action_id);
2004
2005                         if (action_array_active[action_id].action_bitmap &
2006                             acl_action_count) {
2007                                 action_counter_table
2008                                     [p_acl->action_counter_index]
2009                                     [action_id].packetCount++;
2010                                 action_counter_table
2011                                     [p_acl->action_counter_index]
2012                                     [action_id].byteCount +=
2013                                     rte_pktmbuf_pkt_len(pkt);
2014                                 if (ACL_DEBUG)
2015                                         printf("Action Count   Packet Count: %"
2016                                                PRIu64 "  Byte Count: %" PRIu64
2017                                                "\n",
2018                                                action_counter_table
2019                                                [p_acl->action_counter_index]
2020                                                [action_id].packetCount,
2021                                                action_counter_table
2022                                                [p_acl->action_counter_index]
2023                                                [action_id].byteCount);
2024                         }
2025
2026                         if (action_array_active[action_id].action_bitmap &
2027                             acl_action_packet_drop) {
2028                                 /* Drop packet by changing the mask */
2029                                 if (ACL_DEBUG)
2030                                         printf("ACL before drop pkt_mask  "
2031                                                         "%lu, pkt_num %d\n",
2032                                              pkts_mask, pos);
2033                                 pkts_mask &= ~(1LLU << pos);
2034                                 if (ACL_DEBUG)
2035                                         printf("ACL after drop pkt_mask  "
2036                                                         "%lu, pkt_num %d\n",
2037                                              pkts_mask, pos);
2038                                 p_acl->counters->pkts_drop++;
2039
2040                         }
2041
2042                         if (action_array_active[action_id].action_bitmap &
2043                             acl_action_fwd) {
2044                                 phy_port =
2045                                     action_array_active[action_id].fwd_port;
2046                                 entry->head.port_id = phy_port;
2047                                 if (ACL_DEBUG)
2048                                         printf("Action FWD  Port ID: %u\n",
2049                                                phy_port);
2050                         }
2051
2052                         if (action_array_active[action_id].action_bitmap &
2053                             acl_action_nat) {
2054                                 phy_port =
2055                                     action_array_active[action_id].nat_port;
2056                                 entry->head.port_id = phy_port;
2057                                 if (ACL_DEBUG)
2058                                         printf("Action NAT  Port ID: %u\n",
2059                                                phy_port);
2060                         }
2061
2062                         if (action_array_active[action_id].action_bitmap &
2063                             acl_action_dscp) {
2064
2065                                 /* Set DSCP priority */
2066                                 uint32_t dscp_offset =
2067                                     MBUF_HDR_ROOM + ETH_HDR_SIZE +
2068                                     IP_HDR_DSCP_OFST_IPV6;
2069                                 uint16_t *dscp =
2070                                     RTE_MBUF_METADATA_UINT16_PTR(pkt,
2071                                                                  dscp_offset);
2072                                 uint16_t dscp_value =
2073                                     (rte_bswap16
2074                                      (RTE_MBUF_METADATA_UINT16
2075                                       (pkt, dscp_offset)) & 0XF00F);
2076                                 uint8_t dscp_store =
2077                                     action_array_active[action_id].dscp_priority
2078                                     << 2;
2079                                 uint16_t dscp_temp = dscp_store;
2080
2081                                 dscp_temp = dscp_temp << 4;
2082                                 *dscp = rte_bswap16(dscp_temp | dscp_value);
2083                                 if (ACL_DEBUG)
2084                                         printf
2085                                             ("Action DSCP  DSCP Priority: %u\n",
2086                                              *dscp);
2087                         }
2088
2089                         if (action_array_active[action_id].action_bitmap &
2090                             acl_action_packet_accept) {
2091                                 if (ACL_DEBUG)
2092                                         printf("Action Accept\n");
2093
2094                                 if (action_array_active[action_id].action_bitmap
2095                                     & acl_action_conntrack) {
2096
2097                                         /* Set conntrack bit for this pkt */
2098                                         conntrack_mask |= pkt_mask;
2099                                         if (ACL_DEBUG)
2100                                                 printf("ACL Conntrack enabled: "
2101                                                         " %p  pkt_mask: %p\n",
2102                                                      (void *)conntrack_mask,
2103                                                      (void *)pkt_mask);
2104                                 }
2105
2106                                 if (action_array_active[action_id].action_bitmap
2107                                     & acl_action_connexist) {
2108
2109                                         /* Set conntrack bit for this pkt */
2110                                         conntrack_mask |= pkt_mask;
2111
2112                 /* Set connexist bit for this pkt for public -> private */
2113                         /* Private -> public packet will open the connection */
2114                                         if (action_array_active
2115                                             [action_id].private_public ==
2116                                             acl_public_private)
2117                                                 connexist_mask |= pkt_mask;
2118
2119                                         if (ACL_DEBUG)
2120                                                 printf("ACL Connexist enabled "
2121                                 "conntrack: %p  connexist: %p  pkt_mask: %p\n",
2122                                                      (void *)conntrack_mask,
2123                                                      (void *)connexist_mask,
2124                                                      (void *)pkt_mask);
2125                                 }
2126                         }
2127                 }
2128         }
2129         /* Only call connection tracker if required */
2130         if (conntrack_mask > 0) {
2131                 if (ACL_DEBUG)
2132                         printf
2133                             ("ACL Call Conntrack Before = %p  Connexist = %p\n",
2134                              (void *)conntrack_mask, (void *)connexist_mask);
2135                 conntrack_mask =
2136                     rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
2137                     (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
2138                 if (ACL_DEBUG)
2139                         printf("ACL Call Conntrack After = %p\n",
2140                                (void *)conntrack_mask);
2141
2142                 /* Only change pkt mask for pkts that have conntrack enabled */
2143                 /* Need to loop through packets to check if conntrack enabled */
2144                 pkts_to_process = pkts_mask;
2145                 for (; pkts_to_process;) {
2146                         uint32_t action_id = 0;
2147                         uint8_t pos =
2148                             (uint8_t) __builtin_ctzll(pkts_to_process);
2149                         uint64_t pkt_mask = 1LLU << pos;
2150                 /* bitmask representing only this packet */
2151
2152                         pkts_to_process &= ~pkt_mask;
2153                 /* remove this packet from remaining list */
2154                         struct rte_mbuf *pkt = pkts[pos];
2155
2156                         uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
2157                                                                   MBUF_HDR_ROOM
2158                                                                   +
2159                                                                   ETH_HDR_SIZE);
2160                         hdr_chk = hdr_chk >> IP_VERSION_CHECK;
2161                         if (hdr_chk == IPv4_HDR_VERSION) {
2162                                 struct acl_table_entry *entry =
2163                                     (struct acl_table_entry *)
2164                                     p_acl->acl_entries_ipv4[pos];
2165                                 action_id = entry->action_id;
2166                         } else {
2167                                 struct acl_table_entry *entry =
2168                                     (struct acl_table_entry *)
2169                                     p_acl->acl_entries_ipv6[pos];
2170                                 action_id = entry->action_id;
2171                         }
2172
2173                         if ((action_array_active[action_id].action_bitmap &
2174                              acl_action_conntrack)
2175                             || (action_array_active[action_id].action_bitmap &
2176                                 acl_action_connexist)) {
2177
2178                                 if (conntrack_mask & pkt_mask) {
2179                                         if (ACL_DEBUG)
2180                                                 printf("ACL Conntrack Accept  "
2181                                                         "packet = %p\n",
2182                                                      (void *)pkt_mask);
2183                                 } else {
2184 /* Drop packet by changing the mask */
2185                                         if (ACL_DEBUG)
2186                                                 printf
2187                                             ("ACL Conntrack Drop packet = %p\n",
2188                                                      (void *)pkt_mask);
2189                                         pkts_mask &= ~pkt_mask;
2190                                         p_acl->counters->pkts_drop++;
2191                                 }
2192                         }
2193                 }
2194         }
2195
2196         pkts_to_process = pkts_mask;
2197         /* bitmap of packets left to process for ARP */
2198
2199         for (; pkts_to_process;) {
2200                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
2201                 uint64_t pkt_mask = 1LLU << pos;
2202         /* bitmask representing only this packet */
2203
2204                 pkts_to_process &= ~pkt_mask;
2205         /* remove this packet from remaining list */
2206                 struct rte_mbuf *pkt = pkts[pos];
2207
2208                 uint8_t hdr_chk =
2209                     RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
2210                 hdr_chk = hdr_chk >> IP_VERSION_CHECK;
2211
2212                 if (hdr_chk == IPv6_HDR_VERSION) {
2213
2214                         struct acl_table_entry *entry =
2215                             (struct acl_table_entry *)
2216                             p_acl->acl_entries_ipv6[pos];
2217                         //uint16_t phy_port = entry->head.port_id;
2218                         uint16_t phy_port = pkt->port;
2219                         uint32_t *port_out_id =
2220                             RTE_MBUF_METADATA_UINT32_PTR(pkt,
2221                                                          META_DATA_OFFSET +
2222                                                          offsetof(struct
2223                                                           mbuf_acl_meta_data,
2224                                                                   output_port));
2225                 /*      if (is_phy_port_privte(phy_port))
2226                                 *port_out_id = ACL_PUB_PORT_ID;
2227                         else
2228                                 *port_out_id = ACL_PRV_PORT_ID;*/
2229
2230                         /*  *port_out_id = p_acl->links_map[phy_port]; */
2231                         if (ACL_DEBUG)
2232                                 printf
2233                                     ("phy_port = %i,links_map[phy_port] = %i\n",
2234                                      phy_port, p_acl->links_map[phy_port]);
2235
2236         /* header room + eth hdr size + dst_adr offset in ip header */
2237                         uint32_t dst_addr_offset =
2238                             MBUF_HDR_ROOM + ETH_HDR_SIZE +
2239                             IP_HDR_DST_ADR_OFST_IPV6;
2240                         uint8_t *eth_dest =
2241                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
2242                         uint8_t *eth_src =
2243                             RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
2244                         struct ether_addr hw_addr;
2245                         uint8_t dest_address[16];
2246                         uint8_t nhip[16];
2247
2248                         nhip[0] =
2249                             RTE_MBUF_METADATA_UINT8(pkt,
2250                                                     META_DATA_OFFSET +
2251                                                     offsetof(struct
2252                                                              mbuf_acl_meta_data,
2253                                                              nhip));
2254                         uint8_t *dst_addr[16];
2255                         uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
2256                         int i = 0;
2257
2258                         for (i = 0; i < 16; i++) {
2259                                 dst_addr[i] =
2260                                     RTE_MBUF_METADATA_UINT8_PTR(pkt,
2261                                                                 dst_addr_offset
2262                                                                 + i);
2263                         }
2264                         memcpy(dest_address, *dst_addr, sizeof(dest_address));
2265                         memset(nhip, 0, sizeof(nhip));
2266                         struct nd_entry_data *ret_nd_data = NULL;
2267                         ret_nd_data = get_dest_mac_address_ipv6_port
2268                             (dest_address, &dest_if, &hw_addr, &nhip[0]);
2269                         *port_out_id = p_acl->port_out_id[dest_if];
2270
2271                         if (nd_cache_dest_mac_present(dest_if)) {
2272                                 ether_addr_copy(get_link_hw_addr(dest_if),
2273                                         (struct ether_addr *)eth_src);
2274                                 update_nhip_access(dest_if);
2275
2276                                 if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) {
2277                                         printf("sending buffered packets\n");
2278                                         p_acl->counters->tpkts_processed +=
2279                                                  ret_nd_data->num_pkts;
2280                                         nd_send_buffered_pkts(ret_nd_data,
2281                                         (struct ether_addr *)eth_dest, *port_out_id);
2282                                 }
2283                                 p_acl->counters->tpkts_processed++;
2284                                 p_acl->counters->bytes_processed +=
2285                                     packet_length;
2286                         } else {
2287                                 if (unlikely(ret_nd_data == NULL)) {
2288                                         if (ACL_DEBUG)
2289                                                 printf("ACL before drop pkt_mask  "
2290                                                 "%lu, pkt_num %d\n", pkts_mask, pos);
2291                                         pkts_mask &= ~(1LLU << pos);
2292                                         if (ACL_DEBUG)
2293                                                 printf("ACL after drop pkt_mask  "
2294                                                 "%lu, pkt_num %d\n", pkts_mask, pos);
2295                                         p_acl->counters->pkts_drop++;
2296                                         continue;
2297                                 }
2298
2299                                 if (ret_nd_data->status == INCOMPLETE ||
2300                                         ret_nd_data->status == PROBE) {
2301                                         if (ret_nd_data->num_pkts >= NUM_DESC) {
2302                                                 /* Drop the pkt */
2303                                                 if (ACL_DEBUG)
2304                                                         printf("ACL before drop pkt_mask  "
2305                                                         "%lu, pkt_num %d\n", pkts_mask, pos);
2306                                                 pkts_mask &= ~(1LLU << pos);
2307                                                 if (ACL_DEBUG)
2308                                                         printf("ACL after drop pkt_mask  "
2309                                                         "%lu, pkt_num %d\n", pkts_mask, pos);
2310                                                 p_acl->counters->pkts_drop++;
2311                                                 continue;
2312                                         } else {
2313                                                 arp_pkts_mask |= pkt_mask;
2314                                                 nd_queue_unresolved_packet(ret_nd_data,
2315                                                                                  pkt);
2316                                                 continue;
2317                                         }
2318                                 }
2319
2320                         }
2321
2322                 }
2323
2324         } /* end of for loop */
2325
2326         pkts_drop_mask = keep_mask & ~pkts_mask;
2327         rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
2328         keep_mask = pkts_mask;
2329
2330         if (arp_pkts_mask) {
2331                 keep_mask &= ~(arp_pkts_mask);
2332                 rte_pipeline_ah_packet_hijack(p, arp_pkts_mask);
2333         }
2334
2335         /* don't bother measuring if traffic very low, might skew stats */
2336         uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
2337
2338         if (packets_this_iteration > 1) {
2339                 uint64_t latency_this_iteration =
2340                     rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
2341                 p_acl->counters->sum_latencies += latency_this_iteration;
2342                 p_acl->counters->count_latencies++;
2343         }
2344         if (ACL_DEBUG)
2345                 printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
2346                        (void *)pkts_mask);
2347
2348         return 0;
2349 }
2350
2351 static struct rte_acl_field_def field_format_ipv4[] = {
2352         /* Protocol */
2353         [0] = {
2354                .type = RTE_ACL_FIELD_TYPE_BITMASK,
2355                .size = sizeof(uint8_t),
2356                .field_index = 0,
2357                .input_index = 0,
2358                .offset = sizeof(struct ether_hdr) +
2359                offsetof(struct ipv4_hdr, next_proto_id),
2360                },
2361
2362         /* Source IP address (IPv4) */
2363         [1] = {
2364                .type = RTE_ACL_FIELD_TYPE_MASK,
2365                .size = sizeof(uint32_t),
2366                .field_index = 1,
2367                .input_index = 1,
2368                .offset = sizeof(struct ether_hdr) +
2369                offsetof(struct ipv4_hdr, src_addr),
2370                },
2371
2372         /* Destination IP address (IPv4) */
2373         [2] = {
2374                .type = RTE_ACL_FIELD_TYPE_MASK,
2375                .size = sizeof(uint32_t),
2376                .field_index = 2,
2377                .input_index = 2,
2378                .offset = sizeof(struct ether_hdr) +
2379                offsetof(struct ipv4_hdr, dst_addr),
2380                },
2381
2382         /* Source Port */
2383         [3] = {
2384                .type = RTE_ACL_FIELD_TYPE_RANGE,
2385                .size = sizeof(uint16_t),
2386                .field_index = 3,
2387                .input_index = 3,
2388                .offset = sizeof(struct ether_hdr) +
2389                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
2390                },
2391
2392         /* Destination Port */
2393         [4] = {
2394                .type = RTE_ACL_FIELD_TYPE_RANGE,
2395                .size = sizeof(uint16_t),
2396                .field_index = 4,
2397                .input_index = 3,
2398                .offset = sizeof(struct ether_hdr) +
2399                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
2400                },
2401 };
2402
2403 #define SIZEOF_VLAN_HDR                          4
2404
2405 static struct rte_acl_field_def field_format_vlan_ipv4[] = {
2406         /* Protocol */
2407         [0] = {
2408                .type = RTE_ACL_FIELD_TYPE_BITMASK,
2409                .size = sizeof(uint8_t),
2410                .field_index = 0,
2411                .input_index = 0,
2412                .offset = sizeof(struct ether_hdr) +
2413                SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, next_proto_id),
2414                },
2415
2416         /* Source IP address (IPv4) */
2417         [1] = {
2418                .type = RTE_ACL_FIELD_TYPE_MASK,
2419                .size = sizeof(uint32_t),
2420                .field_index = 1,
2421                .input_index = 1,
2422                .offset = sizeof(struct ether_hdr) +
2423                SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, src_addr),
2424                },
2425
2426         /* Destination IP address (IPv4) */
2427         [2] = {
2428                .type = RTE_ACL_FIELD_TYPE_MASK,
2429                .size = sizeof(uint32_t),
2430                .field_index = 2,
2431                .input_index = 2,
2432                .offset = sizeof(struct ether_hdr) +
2433                SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, dst_addr),
2434                },
2435
2436         /* Source Port */
2437         [3] = {
2438                .type = RTE_ACL_FIELD_TYPE_RANGE,
2439                .size = sizeof(uint16_t),
2440                .field_index = 3,
2441                .input_index = 3,
2442                .offset = sizeof(struct ether_hdr) +
2443                SIZEOF_VLAN_HDR +
2444                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
2445                },
2446
2447         /* Destination Port */
2448         [4] = {
2449                .type = RTE_ACL_FIELD_TYPE_RANGE,
2450                .size = sizeof(uint16_t),
2451                .field_index = 4,
2452                .input_index = 4,
2453                .offset = sizeof(struct ether_hdr) +
2454                SIZEOF_VLAN_HDR +
2455                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
2456                },
2457 };
2458
2459 #define SIZEOF_QINQ_HEADER                       8
2460
2461 static struct rte_acl_field_def field_format_qinq_ipv4[] = {
2462         /* Protocol */
2463         [0] = {
2464                .type = RTE_ACL_FIELD_TYPE_BITMASK,
2465                .size = sizeof(uint8_t),
2466                .field_index = 0,
2467                .input_index = 0,
2468                .offset = sizeof(struct ether_hdr) +
2469                SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, next_proto_id),
2470                },
2471
2472         /* Source IP address (IPv4) */
2473         [1] = {
2474                .type = RTE_ACL_FIELD_TYPE_MASK,
2475                .size = sizeof(uint32_t),
2476                .field_index = 1,
2477                .input_index = 1,
2478                .offset = sizeof(struct ether_hdr) +
2479                SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, src_addr),
2480                },
2481
2482         /* Destination IP address (IPv4) */
2483         [2] = {
2484                .type = RTE_ACL_FIELD_TYPE_MASK,
2485                .size = sizeof(uint32_t),
2486                .field_index = 2,
2487                .input_index = 2,
2488                .offset = sizeof(struct ether_hdr) +
2489                SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, dst_addr),
2490                },
2491
2492         /* Source Port */
2493         [3] = {
2494                .type = RTE_ACL_FIELD_TYPE_RANGE,
2495                .size = sizeof(uint16_t),
2496                .field_index = 3,
2497                .input_index = 3,
2498                .offset = sizeof(struct ether_hdr) +
2499                SIZEOF_QINQ_HEADER +
2500                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
2501                },
2502
2503         /* Destination Port */
2504         [4] = {
2505                .type = RTE_ACL_FIELD_TYPE_RANGE,
2506                .size = sizeof(uint16_t),
2507                .field_index = 4,
2508                .input_index = 4,
2509                .offset = sizeof(struct ether_hdr) +
2510                SIZEOF_QINQ_HEADER +
2511                sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
2512                },
2513 };
2514
2515 static struct rte_acl_field_def field_format_ipv6[] = {
2516         /* Protocol */
2517         [0] = {
2518                .type = RTE_ACL_FIELD_TYPE_BITMASK,
2519                .size = sizeof(uint8_t),
2520                .field_index = 0,
2521                .input_index = 0,
2522                .offset = sizeof(struct ether_hdr) +
2523                offsetof(struct ipv6_hdr, proto),
2524                },
2525
2526         /* Source IP address (IPv6) */
2527         [1] = {
2528                .type = RTE_ACL_FIELD_TYPE_MASK,
2529                .size = sizeof(uint32_t),
2530                .field_index = 1,
2531                .input_index = 1,
2532                .offset = sizeof(struct ether_hdr) +
2533                offsetof(struct ipv6_hdr, src_addr),
2534                },
2535
2536         [2] = {
2537                .type = RTE_ACL_FIELD_TYPE_MASK,
2538                .size = sizeof(uint32_t),
2539                .field_index = 2,
2540                .input_index = 2,
2541                .offset = sizeof(struct ether_hdr) +
2542                offsetof(struct ipv6_hdr, src_addr) + sizeof(uint32_t),
2543         }
2544         ,
2545
2546         [3] = {
2547                .type = RTE_ACL_FIELD_TYPE_MASK,
2548                .size = sizeof(uint32_t),
2549                .field_index = 3,
2550                .input_index = 3,
2551                .offset = sizeof(struct ether_hdr) +
2552                offsetof(struct ipv6_hdr, src_addr) + 2 * sizeof(uint32_t),
2553         }
2554         ,
2555
2556         [4] = {
2557                .type = RTE_ACL_FIELD_TYPE_MASK,
2558                .size = sizeof(uint32_t),
2559                .field_index = 4,
2560                .input_index = 4,
2561                .offset = sizeof(struct ether_hdr) +
2562                offsetof(struct ipv6_hdr, src_addr) + 3 * sizeof(uint32_t),
2563         }
2564         ,
2565
2566         /* Destination IP address (IPv6) */
2567         [5] = {
2568                .type = RTE_ACL_FIELD_TYPE_MASK,
2569                .size = sizeof(uint32_t),
2570                .field_index = 5,
2571                .input_index = 5,
2572                .offset = sizeof(struct ether_hdr) +
2573                offsetof(struct ipv6_hdr, dst_addr),
2574                },
2575
2576         [6] = {
2577                .type = RTE_ACL_FIELD_TYPE_MASK,
2578                .size = sizeof(uint32_t),
2579                .field_index = 6,
2580                .input_index = 6,
2581                .offset = sizeof(struct ether_hdr) +
2582                offsetof(struct ipv6_hdr, dst_addr) + sizeof(uint32_t),
2583         }
2584         ,
2585
2586         [7] = {
2587                .type = RTE_ACL_FIELD_TYPE_MASK,
2588                .size = sizeof(uint32_t),
2589                .field_index = 7,
2590                .input_index = 7,
2591                .offset = sizeof(struct ether_hdr) +
2592                offsetof(struct ipv6_hdr, dst_addr) + 2 * sizeof(uint32_t),
2593         }
2594         ,
2595
2596         [8] = {
2597                .type = RTE_ACL_FIELD_TYPE_MASK,
2598                .size = sizeof(uint32_t),
2599                .field_index = 8,
2600                .input_index = 8,
2601                .offset = sizeof(struct ether_hdr) +
2602                offsetof(struct ipv6_hdr, dst_addr) + 3 * sizeof(uint32_t),
2603         }
2604         ,
2605
2606         /* Source Port */
2607         [9] = {
2608                .type = RTE_ACL_FIELD_TYPE_RANGE,
2609                .size = sizeof(uint16_t),
2610                .field_index = 9,
2611                .input_index = 9,
2612                .offset = sizeof(struct ether_hdr) +
2613                sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, src_port),
2614                },
2615
2616         /* Destination Port */
2617         [10] = {
2618                 .type = RTE_ACL_FIELD_TYPE_RANGE,
2619                 .size = sizeof(uint16_t),
2620                 .field_index = 10,
2621                 .input_index = 9,
2622                 .offset = sizeof(struct ether_hdr) +
2623                 sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, dst_port),
2624                 },
2625 };
2626
2627 /**
2628  * Parse arguments in config file.
2629  *
2630  * @param p
2631  *  A pointer to the pipeline.
2632  * @param params
2633  *  A pointer to pipeline specific parameters.
2634  *
2635  * @return
2636  *  0 on success, negative on error.
2637  */
2638 static int
2639 pipeline_acl_parse_args(struct pipeline_acl *p, struct pipeline_params *params)
2640 {
2641         uint32_t n_rules_present = 0;
2642         uint32_t pkt_type_present = 0;
2643         uint32_t i;
2644         uint8_t prv_que_handler_present = 0;
2645         uint8_t n_prv_in_port = 0;
2646
2647         /* defaults */
2648         p->n_rules = 4 * 1024;
2649         acl_n_rules = 4 * 1024;
2650         p->n_rule_fields = RTE_DIM(field_format_ipv4);
2651         p->field_format = field_format_ipv4;
2652         p->field_format_size = sizeof(field_format_ipv4);
2653
2654         for (i = 0; i < params->n_args; i++) {
2655                 char *arg_name = params->args_name[i];
2656                 char *arg_value = params->args_value[i];
2657
2658                 if (strcmp(arg_name, "n_rules") == 0) {
2659                         if (n_rules_present)
2660                                 return -1;
2661                         n_rules_present = 1;
2662
2663                         p->n_rules = atoi(arg_value);
2664                         acl_n_rules = atoi(arg_value);
2665                         continue;
2666                 }
2667
2668                 if (strcmp(arg_name, "pkt_type") == 0) {
2669                         if (pkt_type_present)
2670                                 return -1;
2671                         pkt_type_present = 1;
2672
2673                         /* ipv4 */
2674                         if (strcmp(arg_value, "ipv4") == 0) {
2675                                 p->n_rule_fields = RTE_DIM(field_format_ipv4);
2676                                 p->field_format = field_format_ipv4;
2677                                 p->field_format_size =
2678                                     sizeof(field_format_ipv4);
2679                                 continue;
2680                         }
2681
2682                         /* vlan_ipv4 */
2683                         if (strcmp(arg_value, "vlan_ipv4") == 0) {
2684                                 p->n_rule_fields =
2685                                     RTE_DIM(field_format_vlan_ipv4);
2686                                 p->field_format = field_format_vlan_ipv4;
2687                                 p->field_format_size =
2688                                     sizeof(field_format_vlan_ipv4);
2689                                 continue;
2690                         }
2691
2692                         /* qinq_ipv4 */
2693                         if (strcmp(arg_value, "qinq_ipv4") == 0) {
2694                                 p->n_rule_fields =
2695                                     RTE_DIM(field_format_qinq_ipv4);
2696                                 p->field_format = field_format_qinq_ipv4;
2697                                 p->field_format_size =
2698                                     sizeof(field_format_qinq_ipv4);
2699                                 continue;
2700                         }
2701
2702                         /* ipv6 */
2703                         if (strcmp(arg_value, "ipv6") == 0) {
2704                                 p->n_rule_fields = RTE_DIM(field_format_ipv6);
2705                                 p->field_format = field_format_ipv6;
2706                                 p->field_format_size =
2707                                     sizeof(field_format_ipv6);
2708                                 continue;
2709                         }
2710
2711                         /* other */
2712                         return -1;
2713                 }
2714                 /* traffic_type */
2715                 if (strcmp(arg_name, "traffic_type") == 0) {
2716                         int traffic_type = atoi(arg_value);
2717
2718                         if (traffic_type == 0
2719                             || !(traffic_type == IPv4_HDR_VERSION
2720                                  || traffic_type == IPv6_HDR_VERSION)) {
2721                                 printf("not IPVR4/IPVR6");
2722                                 return -1;
2723                         }
2724
2725                         p->traffic_type = traffic_type;
2726                         continue;
2727                 }
2728
2729                 if (strcmp(arg_name, "prv_que_handler") == 0) {
2730
2731                         if (prv_que_handler_present) {
2732                                 printf("Duplicate pktq_in_prv ..\n\n");
2733                                 return -1;
2734                         }
2735                         prv_que_handler_present = 1;
2736                         n_prv_in_port = 0;
2737
2738                         char *token;
2739                         int rxport = 0;
2740                         /* get the first token */
2741                         token = strtok(arg_value, "(");
2742                         token = strtok(token, ")");
2743                         token = strtok(token, ",");
2744                         printf("***** prv_que_handler *****\n");
2745
2746                         if (token == NULL){
2747                                 printf("string is null\n");
2748                                 printf("prv_que_handler is invalid\n");
2749                                 return -1;
2750                         }
2751                         printf("string is :%s\n", token);
2752
2753                         while (token != NULL) {
2754                                 printf(" %s\n", token);
2755                                 rxport = atoi(token);
2756                                 acl_prv_que_port_index[n_prv_in_port++] =
2757                                     rxport;
2758                                 token = strtok(NULL, ",");
2759                         }
2760
2761                         if (n_prv_in_port == 0) {
2762                         printf("VNF common parse err  - no prv RX phy port\n");
2763                                 return -1;
2764                         }
2765                         continue;
2766                 }
2767
2768                 /* n_flows */
2769                 if (strcmp(arg_name, "n_flows") == 0) {
2770                         p->n_flows = atoi(arg_value);
2771                         if (p->n_flows == 0)
2772                                 return -1;
2773
2774                         continue;/* needed when multiple parms are checked */
2775                 }
2776
2777         }
2778
2779         return 0;
2780 }
2781
2782 /**
2783  * Create and initialize Pipeline Back End (BE).
2784  *
2785  * @param params
2786  *  A pointer to the pipeline.
2787  * @param arg
2788  *  A pointer to pipeline specific data.
2789  *
2790  * @return
2791  *  A pointer to the pipeline create, NULL on error.
2792  */
2793 static void *pipeline_acl_init(struct pipeline_params *params,
2794                                __rte_unused void *arg)
2795 {
2796         struct pipeline *p;
2797         struct pipeline_acl *p_acl;
2798         uint32_t size, i;
2799
2800         /* Check input arguments */
2801         if ((params == NULL) ||
2802             (params->n_ports_in == 0) || (params->n_ports_out == 0))
2803                 return NULL;
2804
2805         /* Memory allocation */
2806         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_acl));
2807         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2808         p_acl = (struct pipeline_acl *)p;
2809         if (p == NULL)
2810                 return NULL;
2811
2812         strcpy(p->name, params->name);
2813         p->log_level = params->log_level;
2814
2815         PLOG(p, HIGH, "ACL");
2816
2817         /*
2818          *  p_acl->links_map[0] = 0xff;
2819          *  p_acl->links_map[1] = 0xff;]
2820          */
2821         p_acl->traffic_type = IPv4_HDR_VERSION;
2822         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2823                 p_acl->links_map[i] = 0xff;
2824                 p_acl->port_out_id[i] = 0xff;
2825                 acl_prv_que_port_index[i] = 0;
2826         }
2827
2828         p_acl->pipeline_num = 0xff;
2829
2830         /* if(enable_hwlb || enable_flow_dir) */
2831 //        lib_arp_init(params, arg);
2832
2833         p_acl->n_flows = 4096;  /* small default value */
2834         /* Create a single firewall instance and initialize. */
2835         p_acl->cnxn_tracker =
2836             rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
2837                         RTE_CACHE_LINE_SIZE);
2838
2839         if (p_acl->cnxn_tracker == NULL)
2840                 return NULL;
2841
2842         /*
2843          * Now allocate a counter block entry.It appears that the initialization
2844          * of all instances is serialized on core 0, so no lock is necessary.
2845          */
2846         struct rte_ACL_counter_block *counter_ptr;
2847
2848         if (rte_ACL_hi_counter_block_in_use == MAX_ACL_INSTANCES) {
2849                 /* error, exceeded table bounds */
2850                 return NULL;
2851         }
2852
2853         rte_ACL_hi_counter_block_in_use++;
2854         counter_ptr = &rte_acl_counter_table[rte_ACL_hi_counter_block_in_use];
2855         strcpy(counter_ptr->name, params->name);
2856         p_acl->action_counter_index = rte_ACL_hi_counter_block_in_use;
2857
2858         p_acl->counters = counter_ptr;
2859
2860         rte_ct_initialize_default_timeouts(p_acl->cnxn_tracker);
2861         p_acl->arpPktCount = 0;
2862
2863         /* Parse arguments */
2864         if (pipeline_acl_parse_args(p_acl, params))
2865                 return NULL;
2866         /*n_flows already checked, ignore Klockwork issue */
2867         if (p_acl->n_flows > 0) {
2868                 rte_ct_initialize_cnxn_tracker(p_acl->cnxn_tracker,
2869                                                p_acl->n_flows, params->name);
2870                 p_acl->counters->ct_counters =
2871                     rte_ct_get_counter_address(p_acl->cnxn_tracker);
2872         } else {
2873                 printf("ACL invalid p_acl->n_flows: %u\n", p_acl->n_flows);
2874                 return NULL;
2875         }
2876
2877         /* Pipeline */
2878         {
2879                 struct rte_pipeline_params pipeline_params = {
2880                         .name = params->name,
2881                         .socket_id = params->socket_id,
2882                         .offset_port_id = META_DATA_OFFSET +
2883                             offsetof(struct mbuf_acl_meta_data, output_port),
2884                 };
2885
2886                 p->p = rte_pipeline_create(&pipeline_params);
2887                 if (p->p == NULL) {
2888                         rte_free(p);
2889                         return NULL;
2890                 }
2891         }
2892
2893         /* Input ports */
2894         p->n_ports_in = params->n_ports_in;
2895         for (i = 0; i < p->n_ports_in; i++) {
2896                 struct rte_pipeline_port_in_params port_params = {
2897                         .ops =
2898                             pipeline_port_in_params_get_ops(&params->port_in
2899                                                             [i]),
2900                         .arg_create =
2901                             pipeline_port_in_params_convert(&params->port_in
2902                                                             [i]),
2903                         .f_action = pkt_work_acl_key,
2904                         .arg_ah = p_acl,
2905                         .burst_size = params->port_in[i].burst_size,
2906                 };
2907                 if (p_acl->traffic_type == IPv4_HDR_VERSION)
2908                         port_params.f_action = pkt_work_acl_ipv4_key;
2909
2910                 if (p_acl->traffic_type == IPv6_HDR_VERSION)
2911                         port_params.f_action = pkt_work_acl_ipv6_key;
2912
2913                 int status = rte_pipeline_port_in_create(p->p,
2914                                                          &port_params,
2915                                                          &p->port_in_id[i]);
2916
2917                 if (status) {
2918                         rte_pipeline_free(p->p);
2919                         rte_free(p);
2920                         return NULL;
2921                 }
2922         }
2923
2924         /* Output ports */
2925         p->n_ports_out = params->n_ports_out;
2926         for (i = 0; i < p->n_ports_out; i++) {
2927                 struct rte_pipeline_port_out_params port_params = {
2928                         .ops =
2929                             pipeline_port_out_params_get_ops(&params->port_out
2930                                                              [i]),
2931                         .arg_create =
2932                             pipeline_port_out_params_convert(&params->port_out
2933                                                              [i]),
2934                         .f_action = NULL,
2935                         .arg_ah = NULL,
2936                 };
2937
2938                 int status = rte_pipeline_port_out_create(p->p,
2939                                                           &port_params,
2940                                                           &p->port_out_id[i]);
2941
2942                 if (status) {
2943                         rte_pipeline_free(p->p);
2944                         rte_free(p);
2945                         return NULL;
2946                 }
2947         }
2948
2949         int pipeline_num = 0;
2950
2951         int temp = sscanf(params->name, "PIPELINE%d", &pipeline_num);
2952         p_acl->pipeline_num = (uint8_t) pipeline_num;
2953 /*      set_phy_outport_map(p_acl->pipeline_num, p_acl->links_map);*/
2954         register_pipeline_Qs(p_acl->pipeline_num, p);
2955         set_link_map(p_acl->pipeline_num, p, p_acl->links_map);
2956         set_outport_id(p_acl->pipeline_num, p, p_acl->port_out_id);
2957
2958         /* If this is the first ACL thread, create common ACL Rule tables */
2959         if (rte_ACL_hi_counter_block_in_use == 0) {
2960
2961                 printf("Create ACL Tables rte_socket_id(): %i\n",
2962                        rte_socket_id());
2963
2964                 /* Create IPV4 ACL Rule Tables */
2965                 struct rte_table_acl_params common_ipv4_table_acl_params = {
2966                         .name = "ACLIPV4A",
2967                         .n_rules = acl_n_rules,
2968                         .n_rule_fields = RTE_DIM(field_format_ipv4),
2969                 };
2970
2971                 memcpy(common_ipv4_table_acl_params.field_format,
2972                        field_format_ipv4, sizeof(field_format_ipv4));
2973
2974                 uint32_t ipv4_entry_size = sizeof(struct acl_table_entry);
2975
2976                 acl_rule_table_ipv4_active =
2977                     rte_table_acl_ops.f_create(&common_ipv4_table_acl_params,
2978                                                rte_socket_id(),
2979                                                ipv4_entry_size);
2980
2981                 if (acl_rule_table_ipv4_active == NULL) {
2982                         printf
2983                             ("Failed to create common ACL IPV4A Rule table\n");
2984                         rte_pipeline_free(p->p);
2985                         rte_free(p);
2986                         return NULL;
2987                 }
2988
2989                 /* Create second IPV4 Table */
2990                 common_ipv4_table_acl_params.name = "ACLIPV4B";
2991                 acl_rule_table_ipv4_standby =
2992                     rte_table_acl_ops.f_create(&common_ipv4_table_acl_params,
2993                                                rte_socket_id(),
2994                                                ipv4_entry_size);
2995
2996                 if (acl_rule_table_ipv4_standby == NULL) {
2997                         printf
2998                             ("Failed to create common ACL IPV4B Rule table\n");
2999                         rte_pipeline_free(p->p);
3000                         rte_free(p);
3001                         return NULL;
3002                 }
3003
3004                 /* Create IPV6 ACL Rule Tables */
3005                 struct rte_table_acl_params common_ipv6_table_acl_params = {
3006                         .name = "ACLIPV6A",
3007                         .n_rules = acl_n_rules,
3008                         .n_rule_fields = RTE_DIM(field_format_ipv6),
3009                 };
3010
3011                 memcpy(common_ipv6_table_acl_params.field_format,
3012                        field_format_ipv6, sizeof(field_format_ipv6));
3013
3014                 uint32_t ipv6_entry_size = sizeof(struct acl_table_entry);
3015
3016                 acl_rule_table_ipv6_active =
3017                     rte_table_acl_ops.f_create(&common_ipv6_table_acl_params,
3018                                                rte_socket_id(),
3019                                                ipv6_entry_size);
3020
3021                 if (acl_rule_table_ipv6_active == NULL) {
3022                         printf
3023                             ("Failed to create common ACL IPV6A Rule table\n");
3024                         rte_pipeline_free(p->p);
3025                         rte_free(p);
3026                         return NULL;
3027                 }
3028
3029                 /* Create second IPV6 table */
3030                 common_ipv6_table_acl_params.name = "ACLIPV6B";
3031                 acl_rule_table_ipv6_standby =
3032                     rte_table_acl_ops.f_create(&common_ipv6_table_acl_params,
3033                                                rte_socket_id(),
3034                                                ipv6_entry_size);
3035
3036                 if (acl_rule_table_ipv6_standby == NULL) {
3037                         printf
3038                             ("Failed to create common ACL IPV6B Rule table\n");
3039                         rte_pipeline_free(p->p);
3040                         rte_free(p);
3041                         return NULL;
3042                 }
3043         }
3044
3045         /* Tables */
3046         p->n_tables = 1;
3047         {
3048
3049                 struct rte_pipeline_table_params table_params = {
3050                         .ops = &rte_table_stub_ops,
3051                         .arg_create = NULL,
3052                         .f_action_hit = NULL,
3053                         .f_action_miss = NULL,
3054                         .arg_ah = NULL,
3055                         .action_data_size = 0,
3056                 };
3057
3058                 int status = rte_pipeline_table_create(p->p,
3059                                                        &table_params,
3060                                                        &p->table_id[0]);
3061
3062                 if (status) {
3063                         rte_pipeline_free(p->p);
3064                         rte_free(p);
3065                         return NULL;
3066                 }
3067
3068                 struct rte_pipeline_table_entry default_entry = {
3069                         .action = RTE_PIPELINE_ACTION_PORT_META
3070                 };
3071
3072                 struct rte_pipeline_table_entry *default_entry_ptr;
3073
3074                 status = rte_pipeline_table_default_entry_add(p->p,
3075                                                       p->table_id[0],
3076                                                       &default_entry,
3077                                                       &default_entry_ptr);
3078
3079                 if (status) {
3080                         rte_pipeline_free(p->p);
3081                         rte_free(p);
3082                         return NULL;
3083                 }
3084         }
3085
3086         /* Connecting input ports to tables */
3087         for (i = 0; i < p->n_ports_in; i++) {
3088                 int status = rte_pipeline_port_in_connect_to_table(p->p,
3089                                                                    p->port_in_id
3090                                                                    [i],
3091                                                                    p->table_id
3092                                                                    [0]);
3093
3094                 if (status) {
3095                         rte_pipeline_free(p->p);
3096                         rte_free(p);
3097                         return NULL;
3098                 }
3099         }
3100
3101         /* Enable input ports */
3102         for (i = 0; i < p->n_ports_in; i++) {
3103                 int status = rte_pipeline_port_in_enable(p->p,
3104                                                          p->port_in_id[i]);
3105
3106                 if (status) {
3107                         rte_pipeline_free(p->p);
3108                         rte_free(p);
3109                         return NULL;
3110                 }
3111         }
3112
3113         /* Check pipeline consistency */
3114         if (rte_pipeline_check(p->p) < 0) {
3115                 rte_pipeline_free(p->p);
3116                 rte_free(p);
3117                 return NULL;
3118         }
3119
3120         /* Message queues */
3121         p->n_msgq = params->n_msgq;
3122         for (i = 0; i < p->n_msgq; i++)
3123                 p->msgq_in[i] = params->msgq_in[i];
3124         for (i = 0; i < p->n_msgq; i++)
3125                 p->msgq_out[i] = params->msgq_out[i];
3126
3127         /* Message handlers */
3128         memcpy(p->handlers, handlers, sizeof(p->handlers));
3129         memcpy(p_acl->custom_handlers,
3130                custom_handlers, sizeof(p_acl->custom_handlers));
3131
3132         return p;
3133 }
3134
3135 /**
3136  * Free resources and delete pipeline.
3137  *
3138  * @param p
3139  *  A pointer to the pipeline.
3140  *
3141  * @return
3142  *  0 on success, negative on error.
3143  */
3144 static int pipeline_acl_free(void *pipeline)
3145 {
3146         struct pipeline *p = (struct pipeline *)pipeline;
3147
3148         /* Check input arguments */
3149         if (p == NULL)
3150                 return -1;
3151
3152         /* Free resources */
3153         rte_pipeline_free(p->p);
3154         rte_free(p);
3155         return 0;
3156 }
3157
3158 /**
3159  * Callback function to map input/output ports.
3160  *
3161  * @param pipeline
3162  *  A pointer to the pipeline.
3163  * @param port_in
3164  *  Input port ID
3165  * @param port_out
3166  *  A pointer to the Output port.
3167  *
3168  * @return
3169  *  0 on success, negative on error.
3170  */
3171 static int
3172 pipeline_acl_track(void *pipeline,
3173                    __rte_unused uint32_t port_in, uint32_t *port_out)
3174 {
3175         struct pipeline *p = (struct pipeline *)pipeline;
3176
3177         /* Check input arguments */
3178         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
3179                 return -1;
3180
3181         if (p->n_ports_in == 1) {
3182                 *port_out = 0;
3183                 return 0;
3184         }
3185
3186         return -1;
3187 }
3188
3189 /**
3190  * Callback function to process timers.
3191  *
3192  * @param pipeline
3193  *  A pointer to the pipeline.
3194  *
3195  * @return
3196  *  0 on success, negative on error.
3197  */
3198 static int pipeline_acl_timer(void *pipeline)
3199 {
3200
3201         struct pipeline *p = (struct pipeline *)pipeline;
3202         struct pipeline_acl *p_acl = (struct pipeline_acl *)pipeline;
3203
3204         pipeline_msg_req_handle(p);
3205         rte_pipeline_flush(p->p);
3206
3207         rte_ct_handle_expired_timers(p_acl->cnxn_tracker);
3208
3209         return 0;
3210 }
3211
3212 /**
3213  * Callback function to process CLI commands from FE.
3214  *
3215  * @param p
3216  *  A pointer to the pipeline.
3217  * @param msg
3218  *  A pointer to command specific data.
3219  *
3220  * @return
3221  *  A pointer to message handler on success,
3222  *  pipeline_msg_req_invalid_hander on error.
3223  */
3224 void *pipeline_acl_msg_req_custom_handler(struct pipeline *p, void *msg)
3225 {
3226         struct pipeline_acl *p_acl = (struct pipeline_acl *)p;
3227         struct pipeline_custom_msg_req *req = msg;
3228         pipeline_msg_req_handler f_handle;
3229
3230         f_handle = (req->subtype < PIPELINE_ACL_MSG_REQS) ?
3231             p_acl->custom_handlers[req->subtype] :
3232             pipeline_msg_req_invalid_handler;
3233
3234         if (f_handle == NULL)
3235                 f_handle = pipeline_msg_req_invalid_handler;
3236
3237         return f_handle(p, req);
3238 }
3239
3240 /**
3241  * Handler for DBG CLI command.
3242  *
3243  * @param p
3244  *  A pointer to the pipeline.
3245  * @param msg
3246  *  A pointer to command specific data.
3247  *
3248  * @return
3249  *  A pointer to response message.
3250  *  Response message contains status.
3251  */
3252 void *pipeline_acl_msg_req_dbg_handler(struct pipeline *p, void *msg)
3253 {
3254         (void)p;
3255         struct pipeline_acl_dbg_msg_req *req = msg;
3256         struct pipeline_acl_dbg_msg_rsp *rsp = msg;
3257
3258         if (req->dbg == 0) {
3259                 printf("DBG turned OFF\n");
3260                 ACL_DEBUG = 0;
3261                 rsp->status = 0;
3262         } else if (req->dbg == 1) {
3263                 printf("DBG turned ON\n");
3264                 ACL_DEBUG = 1;
3265                 rsp->status = 0;
3266         } else {
3267                 printf("Invalid DBG setting\n");
3268                 rsp->status = -1;
3269         }
3270
3271         return rsp;
3272 }
3273
3274 struct pipeline_be_ops pipeline_acl_be_ops = {
3275         .f_init = pipeline_acl_init,
3276         .f_free = pipeline_acl_free,
3277         .f_run = NULL,
3278         .f_timer = pipeline_acl_timer,
3279         .f_track = pipeline_acl_track,
3280 };