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