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