summaryrefslogtreecommitdiffstats
path: root/VNFs/vACL/pipeline/pipeline_acl_be.c
diff options
context:
space:
mode:
authorBindya Narayan <bindya.narayan@intel.com>2017-04-18 12:13:10 +0530
committerDeepak S <deepak.s@linux.intel.com>2017-04-19 03:14:55 -0700
commit8a4e9e534fcb1ef718ed5c1089fdc8698b13fb7f (patch)
tree3a4321a48be36c03baf8f2d64bfbb3e1b938249f /VNFs/vACL/pipeline/pipeline_acl_be.c
parentf0bfb2b0c8467154990b49beafb991b7515e37e3 (diff)
vACL VNF initial check-in
JIRA: SAMPLEVNF-2 Features include: - CLI based Run-time rule configuration. (Add, Delete, List, Display, Clear, Modify) - Ipv4 and ipv6 standard 5 tuple packet Selector support. - Multithread support - Multiple physical port support Change-Id: Ie266be23cd2d81f6d01df508ba44bd0998be13b3 Signed-off-by: Bindya Narayan <bindya.narayan@intel.com> [Push patch to gerrit] Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Diffstat (limited to 'VNFs/vACL/pipeline/pipeline_acl_be.c')
-rw-r--r--VNFs/vACL/pipeline/pipeline_acl_be.c3639
1 files changed, 3639 insertions, 0 deletions
diff --git a/VNFs/vACL/pipeline/pipeline_acl_be.c b/VNFs/vACL/pipeline/pipeline_acl_be.c
new file mode 100644
index 00000000..039d6d59
--- /dev/null
+++ b/VNFs/vACL/pipeline/pipeline_acl_be.c
@@ -0,0 +1,3639 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+/**
+ * @file
+ * Pipeline ACL BE Implementation.
+ *
+ * Implementation of Pipeline ACL Back End (BE).
+ * Responsible for packet processing.
+ *
+ */
+
+#include <string.h>
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_byteorder.h>
+#include <rte_table_acl.h>
+#include <rte_table_stub.h>
+#include "pipeline_arpicmp_be.h"
+#include "vnf_common.h"
+#include "pipeline_common_be.h"
+#include <rte_pipeline.h>
+#include <rte_hash.h>
+
+#include <rte_timer.h>
+#include <rte_cycles.h>
+
+#include "pipeline_acl.h"
+#include "pipeline_acl_be.h"
+#include "rte_cnxn_tracking.h"
+#include "pipeline_actions_common.h"
+#include "lib_arp.h"
+#include "lib_icmpv6.h"
+static uint8_t acl_prv_que_port_index[PIPELINE_MAX_PORT_IN];
+extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
+ uint8_t netmask_ipv6[]);
+enum {
+ ACL_PUB_PORT_ID,
+ ACL_PRV_PORT_ID,
+};
+
+/**
+ * A structure defining the ACL pipeline per thread data.
+ */
+struct pipeline_acl {
+ struct pipeline p;
+ pipeline_msg_req_handler custom_handlers[PIPELINE_ACL_MSG_REQS];
+
+ uint32_t n_rules;
+ uint32_t n_rule_fields;
+ struct rte_acl_field_def *field_format;
+ uint32_t field_format_size;
+
+ /* Connection Tracker */
+ struct rte_ct_cnxn_tracker *cnxn_tracker;
+ struct rte_ACL_counter_block *counters;
+ int action_counter_index;
+ /* timestamp retrieved during in-port computations */
+ uint64_t in_port_time_stamp;
+ uint32_t n_flows;
+
+ uint8_t pipeline_num;
+ uint8_t traffic_type;
+ uint8_t links_map[PIPELINE_MAX_PORT_IN];
+ uint8_t port_out_id[PIPELINE_MAX_PORT_IN];
+ uint64_t arpPktCount;
+ struct acl_table_entry *acl_entries_ipv4[RTE_PORT_IN_BURST_SIZE_MAX];
+ struct acl_table_entry *acl_entries_ipv6[RTE_PORT_IN_BURST_SIZE_MAX];
+
+ /* Local ARP & ND Tables */
+ struct lib_arp_route_table_entry
+ local_lib_arp_route_table[MAX_ARP_RT_ENTRY];
+ uint8_t local_lib_arp_route_ent_cnt;
+ struct lib_nd_route_table_entry
+ local_lib_nd_route_table[MAX_ND_RT_ENTRY];
+ uint8_t local_lib_nd_route_ent_cnt;
+
+} __rte_cache_aligned;
+
+/**
+ * A structure defining the mbuf meta data for ACL.
+ */
+struct mbuf_acl_meta_data {
+ /* output port stored for RTE_PIPELINE_ACTION_PORT_META */
+ uint32_t output_port;
+ /* next hop ip address used by ARP code */
+ uint8_t nhip[16];
+} __rte_cache_aligned;
+
+#define META_DATA_OFFSET 128
+
+struct rte_ACL_counter_block rte_acl_counter_table[MAX_ACL_INSTANCES]
+ __rte_cache_aligned;
+int rte_ACL_hi_counter_block_in_use = -1;
+
+/* a spin lock used during acl initialization only */
+rte_spinlock_t rte_ACL_init_lock = RTE_SPINLOCK_INITIALIZER;
+
+/* Action Array */
+struct pipeline_action_key *action_array_a;
+struct pipeline_action_key *action_array_b;
+struct pipeline_action_key *action_array_active;
+struct pipeline_action_key *action_array_standby;
+uint32_t action_array_size;
+
+struct action_counter_block
+ action_counter_table[MAX_ACL_INSTANCES][action_array_max]
+ __rte_cache_aligned;
+
+static void *pipeline_acl_msg_req_custom_handler(struct pipeline *p, void *msg);
+
+static pipeline_msg_req_handler handlers[] = {
+ [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler,
+ [PIPELINE_MSG_REQ_STATS_PORT_IN] =
+ pipeline_msg_req_stats_port_in_handler,
+ [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
+ pipeline_msg_req_stats_port_out_handler,
+ [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler,
+ [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
+ pipeline_msg_req_port_in_enable_handler,
+ [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
+ pipeline_msg_req_port_in_disable_handler,
+ [PIPELINE_MSG_REQ_CUSTOM] = pipeline_acl_msg_req_custom_handler,
+};
+
+static void *pipeline_acl_msg_req_dbg_handler(struct pipeline *p, void *msg);
+
+static pipeline_msg_req_handler custom_handlers[] = {
+ [PIPELINE_ACL_MSG_REQ_DBG] = pipeline_acl_msg_req_dbg_handler,
+};
+
+uint8_t ACL_DEBUG;
+uint32_t local_get_nh_ipv4(uint32_t ip,
+ uint32_t *port,
+ uint32_t *nhip, struct pipeline_acl *p_acl)
+{
+ int i;
+
+ for (i = 0; i < p_acl->local_lib_arp_route_ent_cnt; i++) {
+ if (((p_acl->local_lib_arp_route_table[i].ip &
+ p_acl->local_lib_arp_route_table[i].mask) ==
+ (ip & p_acl->local_lib_arp_route_table[i].mask))) {
+ *port = p_acl->local_lib_arp_route_table[i].port;
+
+ *nhip = p_acl->local_lib_arp_route_table[i].nh;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void do_local_nh_ipv4_cache(uint32_t dest_if, struct pipeline_acl *p_acl)
+{
+
+ /* Search for the entry and do local copy */
+ int i;
+
+ for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
+ if (lib_arp_route_table[i].port == dest_if) {
+
+ struct lib_arp_route_table_entry *lentry =
+ &p_acl->local_lib_arp_route_table
+ [p_acl->local_lib_arp_route_ent_cnt];
+
+ lentry->ip = lib_arp_route_table[i].ip;
+ lentry->mask = lib_arp_route_table[i].mask;
+ lentry->port = lib_arp_route_table[i].port;
+ lentry->nh = lib_arp_route_table[i].nh;
+
+ p_acl->local_lib_arp_route_ent_cnt++;
+ break;
+ }
+ }
+}
+
+static uint32_t local_get_nh_ipv6(uint8_t *ip,
+ uint32_t *port,
+ uint8_t nhip[], struct pipeline_acl *p_acl)
+{
+ int i = 0;
+ uint8_t netmask_ipv6[16],netip_nd[16],netip_in[16];
+ uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
+ memset (netmask_ipv6, 0, sizeof(netmask_ipv6));
+ memset (netip_nd, 0, sizeof(netip_nd));
+ memset (netip_in, 0, sizeof(netip_in));
+
+ for (i = 0; i < p_acl->local_lib_nd_route_ent_cnt; i++) {
+
+ convert_prefixlen_to_netmask_ipv6
+ (p_acl->local_lib_nd_route_table[i].depth, netmask_ipv6);
+
+ for (k = 0; k < 16; k++)
+ if (p_acl->local_lib_nd_route_table[i].ipv6[k] &
+ netmask_ipv6[k]) {
+ depthflags++;
+ netip_nd[k] = p_acl->
+ local_lib_nd_route_table[i].ipv6[k];
+ }
+
+
+ for (l = 0; l < 16; l++)
+ if (ip[l] & netmask_ipv6[l]) {
+ depthflags1++;
+ netip_in[l] = ip[l];
+ }
+
+ int j = 0;
+
+ if ((depthflags == depthflags1) && (memcmp(netip_nd, netip_in,
+ sizeof(netip_nd)) == 0)){
+ *port = p_acl->local_lib_nd_route_table[i].port;
+
+ for (j = 0; j < 16; j++)
+ nhip[j] =
+ p_acl->local_lib_nd_route_table[i].
+ nhipv6[j];
+ return 1;
+ }
+
+ depthflags = 0;
+ depthflags1 = 0;
+ }
+ return 0;
+}
+void do_local_nh_ipv6_cache(uint32_t dest_if, struct pipeline_acl *p_acl)
+{
+ /* Search for the entry and do local copy */
+ int i, l;
+
+ for (i = 0; i < MAX_ND_RT_ENTRY; i++) {
+
+ if (lib_nd_route_table[i].port == dest_if) {
+
+ struct lib_nd_route_table_entry *lentry =
+ &p_acl->local_lib_nd_route_table
+ [p_acl->local_lib_nd_route_ent_cnt];
+
+ for (l = 0; l < 16; l++) {
+ lentry->ipv6[l] = lib_nd_route_table[i].ipv6[l];
+ lentry->nhipv6[l] =
+ lib_nd_route_table[i].nhipv6[l];
+ }
+ lentry->depth = lib_nd_route_table[i].depth;
+ lentry->port = lib_nd_route_table[i].port;
+
+ p_acl->local_lib_nd_route_ent_cnt++;
+ break;
+ } /* if */
+ } /* for */
+}
+
+static uint8_t check_arp_icmp(struct rte_mbuf *pkt,
+ uint64_t pkt_mask, struct pipeline_acl *p_acl)
+{
+ uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
+ struct ipv6_hdr *ipv6_h;
+ uint16_t *eth_proto =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
+ struct app_link_params *link;
+
+ //uint32_t *port_out_id = RTE_MBUF_METADATA_UINT32_PTR(pk
+ // offsetof(struct mbuf_acl_meta_dat
+
+ /* ARP outport number */
+ uint16_t out_port = p_acl->p.n_ports_out - 1;
+
+ uint8_t *protocol;
+ uint32_t prot_offset;
+
+ link = &myApp->link_params[pkt->port];
+
+ switch (rte_be_to_cpu_16(*eth_proto)) {
+
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_acl->p.p, out_port, pkt);
+
+ /*
+ * Pkt mask should be changed, and not changing the
+ * drop mask
+ */
+ p_acl->arpPktCount++;
+
+ return 0;
+/* break;*/
+ case ETH_TYPE_IPV4:{
+ /* header room + eth hdr size +
+ * src_aadr offset in ip header
+ */
+ uint32_t dst_addr_offset = MBUF_HDR_ROOM +
+ ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ dst_addr_offset);
+ prot_offset = MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_PROTOCOL_OFST;
+ protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ prot_offset);
+ if ((*protocol == IP_PROTOCOL_ICMP) &&
+ link->ip == rte_be_to_cpu_32(*dst_addr)) {
+
+ if (is_phy_port_privte(pkt->port)) {
+
+ rte_pipeline_port_out_packet_insert
+ (p_acl->p.p, out_port, pkt);
+ /*
+ * Pkt mask should be changed,
+ * and not changing the drop mask
+ */
+ p_acl->arpPktCount++;
+
+ return 0;
+ }
+ }
+ return 1;
+ }
+ break;
+#if 0
+#ifdef IPV6
+ case ETH_TYPE_IPV6:{
+
+ uint32_t dst_addr_offset = MBUF_HDR_ROOM +
+ ETH_HDR_SIZE + IPV6_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ dst_addr_offset);
+
+ uint32_t prot_offset_ipv6 = MBUF_HDR_ROOM +
+ ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
+ struct ipv6_hdr *ipv6_h;
+
+ ipv6_h = (struct ipv6_hdr *)MBUF_HDR_ROOM +
+ ETH_HDR_SIZE;
+ protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ prot_offset_ipv6);
+
+ if ((ipv6_h->proto == ICMPV6_PROTOCOL_ID) &&
+ (link->ip == rte_be_to_cpu_32(dst_addr[3]))) {
+
+ if (is_phy_port_privte(pkt->port)) {
+
+ rte_pipeline_port_out_packet_insert
+ (p_acl->p.p, out_port, pkt);
+ /*
+ * Pkt mask should be changed,
+ * and not changing the drop mask
+ */
+ p_acl->arpPktCount++;
+
+ return 0;
+ }
+ }
+ return 1;
+ }
+ break;
+#endif
+#endif
+#define IP_START (MBUF_HDR_ROOM + ETH_HDR_SIZE)
+#ifdef IPV6
+ case ETH_TYPE_IPV6:
+ ipv6_h = (struct ipv6_hdr *)
+ RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
+
+ if ((ipv6_h->proto == ICMPV6_PROTOCOL_ID) &&
+ (link->ip ==
+ rte_be_to_cpu_32(ipv6_h->dst_addr[3]))) {
+
+ if (is_phy_port_privte(pkt->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_acl->p.p,
+ out_port,
+ pkt);
+
+ p_acl->arpPktCount++;
+
+ return 0;
+ }
+ }
+ break;
+#endif
+ default:
+ break;
+ return 1;
+ }
+ return 1;
+}
+
+/**
+ * Print packet for debugging.
+ *
+ * @param pkt
+ * A pointer to the packet.
+ *
+ */
+void print_pkt_acl(struct rte_mbuf *pkt)
+{
+ int i = 0, j = 0;
+
+ printf("Packet Contents:\n");
+ uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
+
+ for (i = 0; i < 20; i++) {
+ for (j = 0; j < 20; j++)
+ printf("%02x ", rd[(20 * i) + j]);
+ printf("\n");
+ }
+}
+
+/**
+ * Main packet processing function.
+ * 64 packet bit mask are used to identify which packets to forward.
+ * Performs the following:
+ * - Burst lookup packets in the IPv4 ACL Rule Table.
+ * - Burst lookup packets in the IPv6 ACL Rule Table.
+ * - Lookup Action Table, perform actions.
+ * - Burst lookup Connection Tracking, if enabled.
+ * - Lookup MAC address.
+ * - Set bit mask.
+ * - Packets with bit mask set are forwarded
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param pkts
+ * A pointer to a burst of packets.
+ * @param n_pkts
+ * Number of packets to process.
+ * @param arg
+ * A pointer to pipeline specific data.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+pkt_work_acl_key(struct rte_pipeline *p,
+ struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
+{
+
+ struct pipeline_acl *p_acl = arg;
+
+ p_acl->counters->pkts_received =
+ p_acl->counters->pkts_received + n_pkts;
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_received: %" PRIu64
+ " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
+
+ uint64_t lookup_hit_mask = 0;
+ uint64_t lookup_hit_mask_ipv4 = 0;
+ uint64_t lookup_hit_mask_ipv6 = 0;
+ uint64_t lookup_miss_mask = 0;
+ uint64_t conntrack_mask = 0;
+ uint64_t connexist_mask = 0;
+ uint32_t dest_address = 0;
+ int dest_if = 0;
+ int status;
+ uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
+ uint64_t keep_mask = pkts_mask;
+ uint16_t port;
+ uint32_t ret;
+
+ p_acl->in_port_time_stamp = rte_get_tsc_cycles();
+
+ if (acl_ipv4_enabled) {
+ if (ACL_DEBUG)
+ printf("ACL IPV4 Lookup Mask Before = %p\n",
+ (void *)pkts_mask);
+ status =
+ rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts,
+ pkts_mask, &lookup_hit_mask_ipv4,
+ (void **)
+ p_acl->acl_entries_ipv4);
+ if (ACL_DEBUG)
+ printf("ACL IPV4 Lookup Mask After = %p\n",
+ (void *)lookup_hit_mask_ipv4);
+ }
+
+ if (acl_ipv6_enabled) {
+ if (ACL_DEBUG)
+ printf("ACL IPV6 Lookup Mask Before = %p\n",
+ (void *)pkts_mask);
+ status =
+ rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts,
+ pkts_mask, &lookup_hit_mask_ipv6,
+ (void **)
+ p_acl->acl_entries_ipv6);
+ if (ACL_DEBUG)
+ printf("ACL IPV6 Lookup Mask After = %p\n",
+ (void *)lookup_hit_mask_ipv6);
+ }
+
+ /* Merge lookup results since we process both IPv4 and IPv6 below */
+ lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
+ if (ACL_DEBUG)
+ printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
+
+ lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
+ pkts_mask = lookup_hit_mask;
+ p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ p_acl->counters->pkts_drop,
+ __builtin_popcountll(lookup_miss_mask));
+
+ uint64_t pkts_to_process = lookup_hit_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ if (enable_hwlb)
+ if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
+ pkts_mask &= ~(1LLU << pos);
+ continue;
+ }
+
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+
+ if (hdr_chk == IPv4_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ " %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dscp_offset);
+ *dscp =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack enabled: "
+ "%p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist enabled "
+ "conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DSCP_OFST_IPV6;
+ uint16_t *dscp =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt,
+ dscp_offset);
+ uint16_t dscp_value =
+ (rte_bswap16
+ (RTE_MBUF_METADATA_UINT16
+ (pkt, dscp_offset)) & 0XF00F);
+ uint8_t dscp_store =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ uint16_t dscp_temp = dscp_store;
+
+ dscp_temp = dscp_temp << 4;
+ *dscp = rte_bswap16(dscp_temp | dscp_value);
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack enabled: "
+ " %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist enabled "
+ "conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+ }
+
+ /* Only call connection tracker if required */
+ if (conntrack_mask > 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL Call Conntrack Before = %p Connexist = %p\n",
+ (void *)conntrack_mask, (void *)connexist_mask);
+ conntrack_mask =
+ rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
+ (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
+ if (ACL_DEBUG)
+ printf("ACL Call Conntrack After = %p\n",
+ (void *)conntrack_mask);
+
+ /* Only change pkt mask for pkts that have conntrack enabled */
+ /* Need to loop through packets to check if conntrack enabled */
+ pkts_to_process = pkts_mask;
+ for (; pkts_to_process;) {
+ uint32_t action_id = 0;
+ uint8_t pos =
+ (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
+ MBUF_HDR_ROOM
+ +
+ ETH_HDR_SIZE);
+
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+ if (hdr_chk == IPv4_HDR_VERSION) {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ action_id = entry->action_id;
+ } else {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ action_id = entry->action_id;
+ }
+
+ if ((action_array_active[action_id].action_bitmap &
+ acl_action_conntrack)
+ || (action_array_active[action_id].action_bitmap &
+ acl_action_connexist)) {
+
+ if (conntrack_mask & pkt_mask) {
+ if (ACL_DEBUG)
+ printf("ACL Conntrack Accept "
+ "packet = %p\n",
+ (void *)pkt_mask);
+ } else {
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL Conntrack Drop "
+ "packet = %p\n",
+ (void *)pkt_mask);
+ pkts_mask &= ~pkt_mask;
+ p_acl->counters->pkts_drop++;
+ }
+ }
+ }
+ }
+
+ pkts_to_process = pkts_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+
+ if (hdr_chk == IPv4_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ uint16_t phy_port = pkt->port;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ if (ACL_DEBUG)
+ printf
+ ("phy_port = %i, links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint32_t dest_address = rte_bswap32(*dst_addr);
+ uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET
+ +
+ offsetof
+ (struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ *nhip = 0;
+ if (is_phy_port_privte(phy_port)) {
+ dest_address = rte_bswap32(*dst_addr);
+ ret =
+ local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_prv_to_pub_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ }
+ *port_out_id = p_acl->port_out_id[dest_if];
+ } else {
+ dest_address = rte_bswap32(*dst_addr);
+
+ ret = local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_pub_to_prv_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ };
+ *port_out_id = p_acl->port_out_id[dest_if];
+ }
+ /* port = ACL_PRV_PORT_ID; */
+
+ int ret_mac = 0;
+
+ ret_mac = get_dest_mac_addr_port
+ (dest_address, &dest_if, &hw_addr);
+ if (ret_mac == ARP_FOUND) {
+ if (ACL_DEBUG) {
+ printf("MAC found for ip 0x%x, "
+ "port %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dest_address, phy_port,
+ hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf("Dest MAC before - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf("Dest MAC after - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+ if (*nhip != 0) {
+ if (ACL_DEBUG)
+ printf("ACL requesting ARP for "
+ "ip %x, port %d\n",
+ dest_address, phy_port);
+ if (ret_mac == ARP_NOT_FOUND)
+ request_arp(dest_if, *nhip);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ //uint16_t phy_port = entry->head.port_id;
+ uint16_t phy_port = pkt->port;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ /*if (is_phy_port_privte(phy_port))
+ *port_out_id = ACL_PUB_PORT_ID;
+ else
+ *port_out_id = ACL_PRV_PORT_ID;*/
+
+ /* *port_out_id = p_acl->links_map[phy_port]; */
+ if (ACL_DEBUG)
+ printf("phy_port = %i, "
+ "links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DST_ADR_OFST_IPV6;
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint8_t dest_address[16];
+ uint8_t nhip[16];
+
+ nhip[0] =
+ RTE_MBUF_METADATA_UINT8(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint8_t *dst_addr[16];
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ int i = 0;
+
+ for (i = 0; i < 16; i++) {
+ dst_addr[i] =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dst_addr_offset
+ + i);
+ }
+ memcpy(dest_address, *dst_addr, sizeof(dest_address));
+ memset(nhip, 0, sizeof(nhip));
+ ret = local_get_nh_ipv6(&dest_address[0], &dest_if,
+ &nhip[0], p_acl);
+
+ if (is_phy_port_privte(phy_port)) {
+ if (!ret) {
+ dest_if = get_prv_to_pub_port((
+ uint32_t
+ *)
+ &dest_address[0], IP_VERSION_6);
+ do_local_nh_ipv6_cache(dest_if, p_acl);
+ *port_out_id =
+ p_acl->port_out_id[dest_if];
+ }
+ // port = ACL_PUB_PORT_ID;
+
+ } else {
+ if (!ret) {
+ dest_if = get_pub_to_prv_port((
+ uint32_t
+ *)
+ &dest_address[0], IP_VERSION_6);
+ do_local_nh_ipv6_cache(dest_if, p_acl);
+ *port_out_id =
+ p_acl->port_out_id[dest_if];
+ }
+// port = ACL_PRV_PORT_ID;
+
+ }
+
+ if (get_dest_mac_address_ipv6_port
+ (dest_address, &dest_if, &hw_addr, &nhip[0])) {
+ if (ACL_DEBUG) {
+ printf("MAC found for port %d - "
+ " %02x:%02x:%02x:%02x:%02x:%02x\n",
+ phy_port, hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf("Dest MAC before - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf("Dest MAC after - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+
+/* memcpy(eth_src, get_link_hw_addr(p_acl->links_map[phy_port]), */
+/* sizeof(struct ether_addr)); */
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+
+#if 0
+ /* Request next neighbor for Ipv6 is yet to be done. */
+ if (*nhip != 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL requesting ARP for ip %x, port %d\n",
+ dest_address, phy_port);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+#endif
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+
+ }
+
+ pkts_drop_mask = keep_mask & ~pkts_mask;
+ rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
+ keep_mask = pkts_mask;
+
+ /* don't bother measuring if traffic very low, might skew stats */
+ uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
+
+ if (packets_this_iteration > 1) {
+ uint64_t latency_this_iteration =
+ rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
+
+ p_acl->counters->sum_latencies += latency_this_iteration;
+ p_acl->counters->count_latencies++;
+ }
+
+ if (ACL_DEBUG)
+ printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
+ (void *)pkts_mask);
+
+ return 0;
+}
+
+/**
+ * Main packet processing function.
+ * 64 packet bit mask are used to identify which packets to forward.
+ * Performs the following:
+ * - Burst lookup packets in the IPv4 ACL Rule Table.
+ * - Burst lookup packets in the IPv6 ACL Rule Table.
+ * - Lookup Action Table, perform actions.
+ * - Burst lookup Connection Tracking, if enabled.
+ * - Lookup MAC address.
+ * - Set bit mask.
+ * - Packets with bit mask set are forwarded
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param pkts
+ * A pointer to a burst of packets.
+ * @param n_pkts
+ * Number of packets to process.
+ * @param arg
+ * A pointer to pipeline specific data.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+pkt_work_acl_ipv4_key(struct rte_pipeline *p,
+ struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
+{
+
+ struct pipeline_acl *p_acl = arg;
+
+ p_acl->counters->pkts_received =
+ p_acl->counters->pkts_received + n_pkts;
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_received: %" PRIu64
+ " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
+
+ uint64_t lookup_hit_mask = 0;
+ uint64_t lookup_hit_mask_ipv4 = 0;
+ uint64_t lookup_hit_mask_ipv6 = 0;
+ uint64_t lookup_miss_mask = 0;
+ uint64_t conntrack_mask = 0;
+ uint64_t connexist_mask = 0;
+ uint32_t dest_address = 0;
+ int dest_if = 0;
+ int status;
+ uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
+ uint64_t keep_mask = pkts_mask;
+ uint16_t port;
+ uint32_t ret;
+
+ p_acl->in_port_time_stamp = rte_get_tsc_cycles();
+
+ if (acl_ipv4_enabled) {
+ if (ACL_DEBUG)
+ printf("ACL IPV4 Lookup Mask Before = %p\n",
+ (void *)pkts_mask);
+ status =
+ rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts,
+ pkts_mask, &lookup_hit_mask_ipv4,
+ (void **)
+ p_acl->acl_entries_ipv4);
+ if (ACL_DEBUG)
+ printf("ACL IPV4 Lookup Mask After = %p\n",
+ (void *)lookup_hit_mask_ipv4);
+ }
+
+ /* Merge lookup results since we process both IPv4 and IPv6 below */
+ lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
+ if (ACL_DEBUG)
+ printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
+
+ lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
+ pkts_mask = lookup_hit_mask;
+ p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ p_acl->counters->pkts_drop,
+ __builtin_popcountll(lookup_miss_mask));
+
+ uint64_t pkts_to_process = lookup_hit_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ if (enable_hwlb)
+ if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
+ pkts_mask &= ~(1LLU << pos);
+ continue;
+ }
+
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+
+ if (hdr_chk == IPv4_HDR_VERSION) {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ " %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dscp_offset);
+ *dscp =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack "
+ "enabled: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist "
+ "enabled conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+#if 0
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf
+ ("ACL before drop pkt_mask %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf
+ ("ACL after drop pkt_mask %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DSCP_OFST_IPV6;
+ uint16_t *dscp =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt,
+ dscp_offset);
+ uint16_t dscp_value =
+ (rte_bswap16
+ (RTE_MBUF_METADATA_UINT16
+ (pkt, dscp_offset)) & 0XF00F);
+ uint8_t dscp_store =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ uint16_t dscp_temp = dscp_store;
+
+ dscp_temp = dscp_temp << 4;
+ *dscp = rte_bswap16(dscp_temp | dscp_value);
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack "
+ "enabled: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist enabled "
+ "conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+#endif
+ }
+ /* Only call connection tracker if required */
+ if (conntrack_mask > 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL Call Conntrack Before = %p Connexist = %p\n",
+ (void *)conntrack_mask, (void *)connexist_mask);
+ conntrack_mask =
+ rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
+ (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
+ if (ACL_DEBUG)
+ printf("ACL Call Conntrack After = %p\n",
+ (void *)conntrack_mask);
+
+ /* Only change pkt mask for pkts that have conntrack enabled */
+ /* Need to loop through packets to check if conntrack enabled */
+ pkts_to_process = pkts_mask;
+ for (; pkts_to_process;) {
+ uint32_t action_id = 0;
+ uint8_t pos =
+ (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
+ MBUF_HDR_ROOM
+ +
+ ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+ if (hdr_chk == IPv4_HDR_VERSION) {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ action_id = entry->action_id;
+ } else {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ action_id = entry->action_id;
+ }
+
+ if ((action_array_active[action_id].action_bitmap &
+ acl_action_conntrack)
+ || (action_array_active[action_id].action_bitmap &
+ acl_action_connexist)) {
+
+ if (conntrack_mask & pkt_mask) {
+ if (ACL_DEBUG)
+ printf("ACL Conntrack Accept "
+ "packet = %p\n",
+ (void *)pkt_mask);
+ } else {
+/* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL Conntrack Drop "
+ "packet = %p\n",
+ (void *)pkt_mask);
+ pkts_mask &= ~pkt_mask;
+ p_acl->counters->pkts_drop++;
+ }
+ }
+ }
+ }
+
+ pkts_to_process = pkts_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+
+ if (hdr_chk == IPv4_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ //uint16_t phy_port = entry->head.port_id;
+ uint16_t phy_port = pkt->port;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ /* *port_out_id = p_acl->links_map[phy_port]; */
+/* if (is_phy_port_privte(phy_port))
+ *port_out_id = ACL_PUB_PORT_ID;
+ else
+ *port_out_id = ACL_PRV_PORT_ID;*/
+ if (ACL_DEBUG)
+ printf
+ ("phy_port = %i, links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint32_t dest_address = rte_bswap32(*dst_addr);
+ uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET
+ +
+ offsetof
+ (struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ *nhip = 0;
+ if (is_phy_port_privte(phy_port)) {
+ dest_address = rte_bswap32(*dst_addr);
+ ret =
+ local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_prv_to_pub_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ }
+ *port_out_id = p_acl->port_out_id[dest_if];
+ }
+ /* port = ACL_PUB_PORT_ID; */
+ else {
+ dest_address = rte_bswap32(*dst_addr);
+
+ ret = local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_pub_to_prv_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ };
+ *port_out_id = p_acl->port_out_id[dest_if];
+ }
+ /* port = ACL_PRV_PORT_ID; */
+ int ret_mac = 0;
+
+ ret_mac = get_dest_mac_addr_port
+ (dest_address, &dest_if, &hw_addr);
+
+ if (ret_mac == ARP_FOUND) {
+ if (ACL_DEBUG) {
+ printf("MAC found for ip 0x%x, port "
+ "%d - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dest_address, phy_port,
+ hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf("Dest MAC before - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf("Dest MAC after - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+ if (*nhip != 0) {
+ if (ACL_DEBUG)
+ printf("ACL requesting ARP for "
+ "ip %x, port %d\n",
+ dest_address, phy_port);
+ if (ret_mac == ARP_NOT_FOUND)
+ request_arp(dest_if, *nhip);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf
+ ("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+#if 0
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ if (is_phy_port_privte(phy_port))
+ *port_out_id = ACL_PUB_PORT_ID;
+ else
+ *port_out_id = ACL_PRV_PORT_ID;
+
+ /* *port_out_id = p_acl->links_map[phy_port]; */
+ if (ACL_DEBUG)
+ printf
+ ("phy_port = %i, links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DST_ADR_OFST_IPV6;
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint8_t dest_address[16];
+ uint8_t nhip[16];
+
+ nhip[0] =
+ RTE_MBUF_METADATA_UINT8(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint8_t *dst_addr[16];
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ int i = 0;
+
+ for (i = 0; i < 16; i++) {
+ dst_addr[i] =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dst_addr_offset
+ + i);
+ }
+ memcpy(dest_address, *dst_addr, sizeof(dest_address));
+ memset(nhip, 0, sizeof(nhip));
+ if (is_phy_port_privte(phy_port))
+ port = ACL_PUB_PORT_ID;
+ else
+ port = ACL_PRV_PORT_ID;
+
+ if (get_dest_mac_address_ipv6_port
+ (dest_address, port, &hw_addr, &nhip[0])) {
+ if (ACL_DEBUG) {
+
+ printf
+ ("MAC found for port %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ phy_port, hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf
+ ("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf
+ ("Dest MAC after - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+
+ /*
+ * memcpy(eth_src, get_link_hw_addr(p_acl->links_map[phy_port]),
+ * sizeof(struct ether_addr));
+ */
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+
+#if 0
+ /* Request next neighbor for Ipv6 is yet to be done. */
+ if (*nhip != 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL requesting ARP for ip %x, port %d\n",
+ dest_address, phy_port);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+#endif
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ " %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+#endif
+
+ }
+
+ pkts_drop_mask = keep_mask & ~pkts_mask;
+ rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
+ keep_mask = pkts_mask;
+
+ /* don't bother measuring if traffic very low, might skew stats */
+ uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
+
+ if (packets_this_iteration > 1) {
+ uint64_t latency_this_iteration =
+ rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
+ p_acl->counters->sum_latencies += latency_this_iteration;
+ p_acl->counters->count_latencies++;
+ }
+ if (ACL_DEBUG)
+ printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
+ (void *)pkts_mask);
+
+ return 0;
+}
+
+/**
+ * Main packet processing function.
+ * 64 packet bit mask are used to identify which packets to forward.
+ * Performs the following:
+ * - Burst lookup packets in the IPv4 ACL Rule Table.
+ * - Burst lookup packets in the IPv6 ACL Rule Table.
+ * - Lookup Action Table, perform actions.
+ * - Burst lookup Connection Tracking, if enabled.
+ * - Lookup MAC address.
+ * - Set bit mask.
+ * - Packets with bit mask set are forwarded
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param pkts
+ * A pointer to a burst of packets.
+ * @param n_pkts
+ * Number of packets to process.
+ * @param arg
+ * A pointer to pipeline specific data.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+pkt_work_acl_ipv6_key(struct rte_pipeline *p,
+ struct rte_mbuf **pkts, uint32_t n_pkts, void *arg)
+{
+
+ struct pipeline_acl *p_acl = arg;
+
+ p_acl->counters->pkts_received =
+ p_acl->counters->pkts_received + n_pkts;
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_received: %" PRIu64
+ " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts);
+
+ uint64_t lookup_hit_mask = 0;
+ uint64_t lookup_hit_mask_ipv4 = 0;
+ uint64_t lookup_hit_mask_ipv6 = 0;
+ uint64_t lookup_miss_mask = 0;
+ uint64_t conntrack_mask = 0;
+ uint64_t connexist_mask = 0;
+ uint32_t dest_address = 0;
+ int dest_if = 0;
+ int status;
+ uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
+ uint64_t keep_mask = pkts_mask;
+ uint16_t port;
+ uint32_t ret;
+
+ p_acl->in_port_time_stamp = rte_get_tsc_cycles();
+
+ if (acl_ipv6_enabled) {
+ if (ACL_DEBUG)
+ printf("ACL IPV6 Lookup Mask Before = %p\n",
+ (void *)pkts_mask);
+ status =
+ rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts,
+ pkts_mask, &lookup_hit_mask_ipv6,
+ (void **)
+ p_acl->acl_entries_ipv6);
+ if (ACL_DEBUG)
+ printf("ACL IPV6 Lookup Mask After = %p\n",
+ (void *)lookup_hit_mask_ipv6);
+ }
+
+ /* Merge lookup results since we process both IPv4 and IPv6 below */
+ lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6;
+ if (ACL_DEBUG)
+ printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask);
+
+ lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
+ pkts_mask = lookup_hit_mask;
+ p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask);
+ if (ACL_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ p_acl->counters->pkts_drop,
+ __builtin_popcountll(lookup_miss_mask));
+
+ uint64_t pkts_to_process = lookup_hit_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ if (enable_hwlb)
+ if (!check_arp_icmp(pkt, pkt_mask, p_acl)) {
+ pkts_mask &= ~(1LLU << pos);
+ continue;
+ }
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+#if 0
+ if (hdr_chk == IPv4_HDR_VERSION) {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST;
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf
+ ("ACL before drop pkt_mask %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf
+ ("ACL after drop pkt_mask %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dscp_offset);
+ *dscp =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack enabled: "
+ " %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist enabled "
+ "conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+#endif
+
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_count) {
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount++;
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n",
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].packetCount,
+ action_counter_table
+ [p_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_drop) {
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_fwd) {
+ phy_port =
+ action_array_active[action_id].fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action FWD Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_nat) {
+ phy_port =
+ action_array_active[action_id].nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_DEBUG)
+ printf("Action NAT Port ID: %u\n",
+ phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint32_t dscp_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DSCP_OFST_IPV6;
+ uint16_t *dscp =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt,
+ dscp_offset);
+ uint16_t dscp_value =
+ (rte_bswap16
+ (RTE_MBUF_METADATA_UINT16
+ (pkt, dscp_offset)) & 0XF00F);
+ uint8_t dscp_store =
+ action_array_active[action_id].dscp_priority
+ << 2;
+ uint16_t dscp_temp = dscp_store;
+
+ dscp_temp = dscp_temp << 4;
+ *dscp = rte_bswap16(dscp_temp | dscp_value);
+ if (ACL_DEBUG)
+ printf
+ ("Action DSCP DSCP Priority: %u\n",
+ *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ acl_action_packet_accept) {
+ if (ACL_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+ if (ACL_DEBUG)
+ printf("ACL Conntrack enabled: "
+ " %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & acl_action_connexist) {
+
+ /* Set conntrack bit for this pkt */
+ conntrack_mask |= pkt_mask;
+
+ /* Set connexist bit for this pkt for public -> private */
+ /* Private -> public packet will open the connection */
+ if (action_array_active
+ [action_id].private_public ==
+ acl_public_private)
+ connexist_mask |= pkt_mask;
+
+ if (ACL_DEBUG)
+ printf("ACL Connexist enabled "
+ "conntrack: %p connexist: %p pkt_mask: %p\n",
+ (void *)conntrack_mask,
+ (void *)connexist_mask,
+ (void *)pkt_mask);
+ }
+ }
+ }
+ }
+ /* Only call connection tracker if required */
+ if (conntrack_mask > 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL Call Conntrack Before = %p Connexist = %p\n",
+ (void *)conntrack_mask, (void *)connexist_mask);
+ conntrack_mask =
+ rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control
+ (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask);
+ if (ACL_DEBUG)
+ printf("ACL Call Conntrack After = %p\n",
+ (void *)conntrack_mask);
+
+ /* Only change pkt mask for pkts that have conntrack enabled */
+ /* Need to loop through packets to check if conntrack enabled */
+ pkts_to_process = pkts_mask;
+ for (; pkts_to_process;) {
+ uint32_t action_id = 0;
+ uint8_t pos =
+ (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt,
+ MBUF_HDR_ROOM
+ +
+ ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+ if (hdr_chk == IPv4_HDR_VERSION) {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ action_id = entry->action_id;
+ } else {
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ action_id = entry->action_id;
+ }
+
+ if ((action_array_active[action_id].action_bitmap &
+ acl_action_conntrack)
+ || (action_array_active[action_id].action_bitmap &
+ acl_action_connexist)) {
+
+ if (conntrack_mask & pkt_mask) {
+ if (ACL_DEBUG)
+ printf("ACL Conntrack Accept "
+ "packet = %p\n",
+ (void *)pkt_mask);
+ } else {
+/* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf
+ ("ACL Conntrack Drop packet = %p\n",
+ (void *)pkt_mask);
+ pkts_mask &= ~pkt_mask;
+ p_acl->counters->pkts_drop++;
+ }
+ }
+ }
+ }
+
+ pkts_to_process = pkts_mask;
+ /* bitmap of packets left to process for ARP */
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process);
+ uint64_t pkt_mask = 1LLU << pos;
+ /* bitmask representing only this packet */
+
+ pkts_to_process &= ~pkt_mask;
+ /* remove this packet from remaining list */
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk =
+ RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE);
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+#if 0
+ if (hdr_chk == IPv4_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ /* *port_out_id = p_acl->links_map[phy_port]; */
+ if (is_phy_port_privte(phy_port))
+ *port_out_id = ACL_PUB_PORT_ID;
+ else
+ *port_out_id = ACL_PRV_PORT_ID;
+ if (ACL_DEBUG)
+ printf
+ ("phy_port = %i,links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint32_t dest_address = rte_bswap32(*dst_addr);
+ uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET
+ +
+ offsetof
+ (struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ *nhip = 0;
+ if (is_phy_port_privte(phy_port)) {
+ dest_address = rte_bswap32(*dst_addr);
+ ret =
+ local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_prv_to_pub_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ }
+ *port_out_id = p_acl->port_out_id[dest_if];
+ }
+ /* port = ACL_PUB_PORT_ID; */
+ else {
+ dest_address = rte_bswap32(*dst_addr);
+
+ ret = local_get_nh_ipv4(dest_address, &dest_if,
+ nhip, p_acl);
+ if (!ret) {
+ dest_if =
+ get_pub_to_prv_port(&dest_address,
+ IP_VERSION_4);
+ do_local_nh_ipv4_cache(dest_if, p_acl);
+ };
+ *port_out_id = p_acl->port_out_id[dest_if];
+ }
+ /* port = ACL_PRV_PORT_ID; */
+
+ if (get_dest_mac_addr_port
+ (dest_address, &dest_if, &hw_addr)) {
+ if (ACL_DEBUG) {
+ printf("MAC found for ip 0x%x, port "
+ " %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dest_address, phy_port,
+ hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf("Dest MAC before - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf("Dest MAC after - "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+ if (*nhip != 0) {
+
+ if (ACL_DEBUG)
+
+ printf("ACL requesting ARP for "
+ " ip %x, port %d\n",
+ dest_address, phy_port);
+ if (is_phy_port_privte(phy_port))
+ request_arp(dest_if, *nhip);
+
+ else
+ request_arp(dest_if, *nhip);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ "%lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+#endif
+
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct acl_table_entry *entry =
+ (struct acl_table_entry *)
+ p_acl->acl_entries_ipv6[pos];
+ //uint16_t phy_port = entry->head.port_id;
+ uint16_t phy_port = pkt->port;
+ uint32_t *port_out_id =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ output_port));
+ /* if (is_phy_port_privte(phy_port))
+ *port_out_id = ACL_PUB_PORT_ID;
+ else
+ *port_out_id = ACL_PRV_PORT_ID;*/
+
+ /* *port_out_id = p_acl->links_map[phy_port]; */
+ if (ACL_DEBUG)
+ printf
+ ("phy_port = %i,links_map[phy_port] = %i\n",
+ phy_port, p_acl->links_map[phy_port]);
+
+ /* header room + eth hdr size + dst_adr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE +
+ IP_HDR_DST_ADR_OFST_IPV6;
+ uint8_t *eth_dest =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ uint8_t *eth_src =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+ struct ether_addr hw_addr;
+ uint8_t dest_address[16];
+ uint8_t nhip[16];
+
+ nhip[0] =
+ RTE_MBUF_METADATA_UINT8(pkt,
+ META_DATA_OFFSET +
+ offsetof(struct
+ mbuf_acl_meta_data,
+ nhip));
+ uint8_t *dst_addr[16];
+ uint32_t packet_length = rte_pktmbuf_pkt_len(pkt);
+ int i = 0;
+
+ for (i = 0; i < 16; i++) {
+ dst_addr[i] =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ dst_addr_offset
+ + i);
+ }
+ memcpy(dest_address, *dst_addr, sizeof(dest_address));
+ memset(nhip, 0, sizeof(nhip));
+ ret = local_get_nh_ipv6(&dest_address[0], &dest_if,
+ &nhip[0], p_acl);
+
+ if (is_phy_port_privte(phy_port)) {
+ if (!ret) {
+ dest_if = get_prv_to_pub_port((
+ uint32_t
+ *)
+ &dest_address[0], IP_VERSION_6);
+ do_local_nh_ipv6_cache(dest_if, p_acl);
+ }
+ // port = ACL_PUB_PORT_ID;
+ *port_out_id =
+ p_acl->port_out_id[dest_if];
+
+ } else {
+ if (!ret) {
+ dest_if = get_pub_to_prv_port((
+ uint32_t
+ *)
+ &dest_address[0], IP_VERSION_6);
+ do_local_nh_ipv6_cache(dest_if, p_acl);
+ }
+ // port = ACL_PRV_PORT_ID;
+ *port_out_id =
+ p_acl->port_out_id[dest_if];
+
+ }
+
+ if (get_dest_mac_address_ipv6_port
+ (dest_address, &dest_if, &hw_addr, &nhip[0])) {
+ if (ACL_DEBUG) {
+ printf("MAC found for port %d "
+ "- %02x:%02x:%02x:%02x:%02x:%02x\n",
+ phy_port, hw_addr.addr_bytes[0],
+ hw_addr.addr_bytes[1],
+ hw_addr.addr_bytes[2],
+ hw_addr.addr_bytes[3],
+ hw_addr.addr_bytes[4],
+ hw_addr.addr_bytes[5]);
+ printf("Dest MAC before - "
+ " %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ memcpy(eth_dest, &hw_addr,
+ sizeof(struct ether_addr));
+ if (ACL_DEBUG) {
+ printf("PktP %p, dest_macP %p\n", pkt,
+ eth_dest);
+ printf("Dest MAC after - "
+ " %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth_dest[0], eth_dest[1],
+ eth_dest[2], eth_dest[3],
+ eth_dest[4], eth_dest[5]);
+ }
+ if (is_phy_port_privte(phy_port))
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+ else
+ memcpy(eth_src,
+ get_link_hw_addr(dest_if),
+ sizeof(struct ether_addr));
+
+ /*
+ * memcpy(eth_src, get_link_hw_addr(p_acl->links_map[phy_port]),
+ * sizeof(struct ether_addr));
+ */
+ p_acl->counters->tpkts_processed++;
+ p_acl->counters->bytes_processed +=
+ packet_length;
+ }
+
+ else {
+
+#if 0
+ /* Request next neighbor for Ipv6 is yet to be done. */
+ if (*nhip != 0) {
+ if (ACL_DEBUG)
+ printf
+ ("ACL requesting ARP for ip %x, port %d\n",
+ dest_address, phy_port);
+
+ /* request_arp(p_acl->links_map[phy_port], *nhip); */
+ }
+#endif
+ /* Drop packet by changing the mask */
+ if (ACL_DEBUG)
+ printf("ACL before drop pkt_mask "
+ " %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ if (ACL_DEBUG)
+ printf("ACL after drop pkt_mask "
+ " %lu, pkt_num %d\n",
+ pkts_mask, pos);
+ p_acl->counters->pkts_drop++;
+ }
+ }
+
+ }
+
+ pkts_drop_mask = keep_mask & ~pkts_mask;
+ rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
+ keep_mask = pkts_mask;
+
+ /* don't bother measuring if traffic very low, might skew stats */
+ uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask);
+
+ if (packets_this_iteration > 1) {
+ uint64_t latency_this_iteration =
+ rte_get_tsc_cycles() - p_acl->in_port_time_stamp;
+ p_acl->counters->sum_latencies += latency_this_iteration;
+ p_acl->counters->count_latencies++;
+ }
+ if (ACL_DEBUG)
+ printf("Leaving pkt_work_acl_key pkts_mask = %p\n",
+ (void *)pkts_mask);
+
+ return 0;
+}
+
+static struct rte_acl_field_def field_format_ipv4[] = {
+ /* Protocol */
+ [0] = {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = 0,
+ .input_index = 0,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, next_proto_id),
+ },
+
+ /* Source IP address (IPv4) */
+ [1] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 1,
+ .input_index = 1,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, src_addr),
+ },
+
+ /* Destination IP address (IPv4) */
+ [2] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 2,
+ .input_index = 2,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, dst_addr),
+ },
+
+ /* Source Port */
+ [3] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 3,
+ .input_index = 3,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
+ },
+
+ /* Destination Port */
+ [4] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 4,
+ .input_index = 3,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
+ },
+};
+
+#define SIZEOF_VLAN_HDR 4
+
+static struct rte_acl_field_def field_format_vlan_ipv4[] = {
+ /* Protocol */
+ [0] = {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = 0,
+ .input_index = 0,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, next_proto_id),
+ },
+
+ /* Source IP address (IPv4) */
+ [1] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 1,
+ .input_index = 1,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, src_addr),
+ },
+
+ /* Destination IP address (IPv4) */
+ [2] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 2,
+ .input_index = 2,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, dst_addr),
+ },
+
+ /* Source Port */
+ [3] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 3,
+ .input_index = 3,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_VLAN_HDR +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
+ },
+
+ /* Destination Port */
+ [4] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 4,
+ .input_index = 4,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_VLAN_HDR +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
+ },
+};
+
+#define SIZEOF_QINQ_HEADER 8
+
+static struct rte_acl_field_def field_format_qinq_ipv4[] = {
+ /* Protocol */
+ [0] = {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = 0,
+ .input_index = 0,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, next_proto_id),
+ },
+
+ /* Source IP address (IPv4) */
+ [1] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 1,
+ .input_index = 1,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, src_addr),
+ },
+
+ /* Destination IP address (IPv4) */
+ [2] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 2,
+ .input_index = 2,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, dst_addr),
+ },
+
+ /* Source Port */
+ [3] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 3,
+ .input_index = 3,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_QINQ_HEADER +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port),
+ },
+
+ /* Destination Port */
+ [4] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 4,
+ .input_index = 4,
+ .offset = sizeof(struct ether_hdr) +
+ SIZEOF_QINQ_HEADER +
+ sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port),
+ },
+};
+
+static struct rte_acl_field_def field_format_ipv6[] = {
+ /* Protocol */
+ [0] = {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = 0,
+ .input_index = 0,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, proto),
+ },
+
+ /* Source IP address (IPv6) */
+ [1] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 1,
+ .input_index = 1,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, src_addr),
+ },
+
+ [2] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 2,
+ .input_index = 2,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, src_addr) + sizeof(uint32_t),
+ }
+ ,
+
+ [3] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 3,
+ .input_index = 3,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, src_addr) + 2 * sizeof(uint32_t),
+ }
+ ,
+
+ [4] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 4,
+ .input_index = 4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, src_addr) + 3 * sizeof(uint32_t),
+ }
+ ,
+
+ /* Destination IP address (IPv6) */
+ [5] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 5,
+ .input_index = 5,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, dst_addr),
+ },
+
+ [6] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 6,
+ .input_index = 6,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, dst_addr) + sizeof(uint32_t),
+ }
+ ,
+
+ [7] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 7,
+ .input_index = 7,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, dst_addr) + 2 * sizeof(uint32_t),
+ }
+ ,
+
+ [8] = {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = 8,
+ .input_index = 8,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv6_hdr, dst_addr) + 3 * sizeof(uint32_t),
+ }
+ ,
+
+ /* Source Port */
+ [9] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 9,
+ .input_index = 9,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, src_port),
+ },
+
+ /* Destination Port */
+ [10] = {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = 10,
+ .input_index = 9,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv6_hdr) + offsetof(struct tcp_hdr, dst_port),
+ },
+};
+
+/**
+ * Parse arguments in config file.
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param params
+ * A pointer to pipeline specific parameters.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+pipeline_acl_parse_args(struct pipeline_acl *p, struct pipeline_params *params)
+{
+ uint32_t n_rules_present = 0;
+ uint32_t pkt_type_present = 0;
+ uint32_t i;
+ uint8_t prv_que_handler_present = 0;
+ uint8_t n_prv_in_port = 0;
+
+ /* defaults */
+ p->n_rules = 4 * 1024;
+ acl_n_rules = 4 * 1024;
+ p->n_rule_fields = RTE_DIM(field_format_ipv4);
+ p->field_format = field_format_ipv4;
+ p->field_format_size = sizeof(field_format_ipv4);
+
+ for (i = 0; i < params->n_args; i++) {
+ char *arg_name = params->args_name[i];
+ char *arg_value = params->args_value[i];
+
+ if (strcmp(arg_name, "n_rules") == 0) {
+ if (n_rules_present)
+ return -1;
+ n_rules_present = 1;
+
+ p->n_rules = atoi(arg_value);
+ acl_n_rules = atoi(arg_value);
+ continue;
+ }
+
+ if (strcmp(arg_name, "pkt_type") == 0) {
+ if (pkt_type_present)
+ return -1;
+ pkt_type_present = 1;
+
+ /* ipv4 */
+ if (strcmp(arg_value, "ipv4") == 0) {
+ p->n_rule_fields = RTE_DIM(field_format_ipv4);
+ p->field_format = field_format_ipv4;
+ p->field_format_size =
+ sizeof(field_format_ipv4);
+ continue;
+ }
+
+ /* vlan_ipv4 */
+ if (strcmp(arg_value, "vlan_ipv4") == 0) {
+ p->n_rule_fields =
+ RTE_DIM(field_format_vlan_ipv4);
+ p->field_format = field_format_vlan_ipv4;
+ p->field_format_size =
+ sizeof(field_format_vlan_ipv4);
+ continue;
+ }
+
+ /* qinq_ipv4 */
+ if (strcmp(arg_value, "qinq_ipv4") == 0) {
+ p->n_rule_fields =
+ RTE_DIM(field_format_qinq_ipv4);
+ p->field_format = field_format_qinq_ipv4;
+ p->field_format_size =
+ sizeof(field_format_qinq_ipv4);
+ continue;
+ }
+
+ /* ipv6 */
+ if (strcmp(arg_value, "ipv6") == 0) {
+ p->n_rule_fields = RTE_DIM(field_format_ipv6);
+ p->field_format = field_format_ipv6;
+ p->field_format_size =
+ sizeof(field_format_ipv6);
+ continue;
+ }
+
+ /* other */
+ return -1;
+ }
+ /* traffic_type */
+ if (strcmp(arg_name, "traffic_type") == 0) {
+ int traffic_type = atoi(arg_value);
+
+ if (traffic_type == 0
+ || !(traffic_type == IPv4_HDR_VERSION
+ || traffic_type == IPv6_HDR_VERSION)) {
+ printf("not IPVR4/IPVR6");
+ return -1;
+ }
+
+ p->traffic_type = traffic_type;
+ continue;
+ }
+
+ if (strcmp(arg_name, "prv_que_handler") == 0) {
+
+ if (prv_que_handler_present) {
+ printf("Duplicate pktq_in_prv ..\n\n");
+ return -1;
+ }
+ prv_que_handler_present = 1;
+ n_prv_in_port = 0;
+
+ char *token;
+ int rxport = 0;
+ /* get the first token */
+ token = strtok(arg_value, "(");
+ token = strtok(token, ")");
+ token = strtok(token, ",");
+ printf("***** prv_que_handler *****\n");
+
+ if (token == NULL){
+ printf("string is null\n");
+ printf("prv_que_handler is invalid\n");
+ return -1;
+ }
+ printf("string is :%s\n", token);
+
+ while (token != NULL) {
+ printf(" %s\n", token);
+ rxport = atoi(token);
+ acl_prv_que_port_index[n_prv_in_port++] =
+ rxport;
+ token = strtok(NULL, ",");
+ }
+
+ if (n_prv_in_port == 0) {
+ printf("VNF common parse err - no prv RX phy port\n");
+ return -1;
+ }
+ continue;
+ }
+
+ /* n_flows */
+ if (strcmp(arg_name, "n_flows") == 0) {
+ p->n_flows = atoi(arg_value);
+ if (p->n_flows == 0)
+ return -1;
+
+ continue;/* needed when multiple parms are checked */
+ }
+
+ }
+
+ return 0;
+}
+
+/**
+ * Create and initialize Pipeline Back End (BE).
+ *
+ * @param params
+ * A pointer to the pipeline.
+ * @param arg
+ * A pointer to pipeline specific data.
+ *
+ * @return
+ * A pointer to the pipeline create, NULL on error.
+ */
+static void *pipeline_acl_init(struct pipeline_params *params,
+ __rte_unused void *arg)
+{
+ struct pipeline *p;
+ struct pipeline_acl *p_acl;
+ uint32_t size, i;
+
+ /* Check input arguments */
+ if ((params == NULL) ||
+ (params->n_ports_in == 0) || (params->n_ports_out == 0))
+ return NULL;
+
+ /* Memory allocation */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_acl));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ p_acl = (struct pipeline_acl *)p;
+ if (p == NULL)
+ return NULL;
+
+ strcpy(p->name, params->name);
+ p->log_level = params->log_level;
+
+ PLOG(p, HIGH, "ACL");
+
+ /*
+ * p_acl->links_map[0] = 0xff;
+ * p_acl->links_map[1] = 0xff;]
+ */
+ p_acl->traffic_type = MIX;
+ for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
+ p_acl->links_map[i] = 0xff;
+ p_acl->port_out_id[i] = 0xff;
+ acl_prv_que_port_index[i] = 0;
+ }
+
+ p_acl->pipeline_num = 0xff;
+
+ /* if(enable_hwlb || enable_flow_dir) */
+// lib_arp_init(params, arg);
+
+ p_acl->n_flows = 4096; /* small default value */
+ /* Create a single firewall instance and initialize. */
+ p_acl->cnxn_tracker =
+ rte_zmalloc(NULL, rte_ct_get_cnxn_tracker_size(),
+ RTE_CACHE_LINE_SIZE);
+
+ if (p_acl->cnxn_tracker == NULL)
+ return NULL;
+
+ /*
+ * Now allocate a counter block entry.It appears that the initialization
+ * of all instances is serialized on core 0, so no lock is necessary.
+ */
+ struct rte_ACL_counter_block *counter_ptr;
+
+ if (rte_ACL_hi_counter_block_in_use == MAX_ACL_INSTANCES) {
+ /* error, exceeded table bounds */
+ return NULL;
+ }
+
+ rte_ACL_hi_counter_block_in_use++;
+ counter_ptr = &rte_acl_counter_table[rte_ACL_hi_counter_block_in_use];
+ strcpy(counter_ptr->name, params->name);
+ p_acl->action_counter_index = rte_ACL_hi_counter_block_in_use;
+
+ p_acl->counters = counter_ptr;
+
+ rte_ct_initialize_default_timeouts(p_acl->cnxn_tracker);
+ p_acl->arpPktCount = 0;
+
+ /* Parse arguments */
+ if (pipeline_acl_parse_args(p_acl, params))
+ return NULL;
+ /*n_flows already checked, ignore Klockwork issue */
+ if (p_acl->n_flows > 0) {
+ rte_ct_initialize_cnxn_tracker(p_acl->cnxn_tracker,
+ p_acl->n_flows, params->name);
+ p_acl->counters->ct_counters =
+ rte_ct_get_counter_address(p_acl->cnxn_tracker);
+ } else {
+ printf("ACL invalid p_acl->n_flows: %u\n", p_acl->n_flows);
+ return NULL;
+ }
+
+ /* Pipeline */
+ {
+ struct rte_pipeline_params pipeline_params = {
+ .name = params->name,
+ .socket_id = params->socket_id,
+ .offset_port_id = META_DATA_OFFSET +
+ offsetof(struct mbuf_acl_meta_data, output_port),
+ };
+
+ p->p = rte_pipeline_create(&pipeline_params);
+ if (p->p == NULL) {
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Input ports */
+ p->n_ports_in = params->n_ports_in;
+ for (i = 0; i < p->n_ports_in; i++) {
+ struct rte_pipeline_port_in_params port_params = {
+ .ops =
+ pipeline_port_in_params_get_ops(&params->port_in
+ [i]),
+ .arg_create =
+ pipeline_port_in_params_convert(&params->port_in
+ [i]),
+ .f_action = pkt_work_acl_key,
+ .arg_ah = p_acl,
+ .burst_size = params->port_in[i].burst_size,
+ };
+ if (p_acl->traffic_type == IPv4_HDR_VERSION)
+ port_params.f_action = pkt_work_acl_ipv4_key;
+
+ if (p_acl->traffic_type == IPv6_HDR_VERSION)
+ port_params.f_action = pkt_work_acl_ipv6_key;
+
+ int status = rte_pipeline_port_in_create(p->p,
+ &port_params,
+ &p->port_in_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Output ports */
+ p->n_ports_out = params->n_ports_out;
+ for (i = 0; i < p->n_ports_out; i++) {
+ struct rte_pipeline_port_out_params port_params = {
+ .ops =
+ pipeline_port_out_params_get_ops(&params->port_out
+ [i]),
+ .arg_create =
+ pipeline_port_out_params_convert(&params->port_out
+ [i]),
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ int status = rte_pipeline_port_out_create(p->p,
+ &port_params,
+ &p->port_out_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ int pipeline_num = 0;
+
+ int temp = sscanf(params->name, "PIPELINE%d", &pipeline_num);
+ p_acl->pipeline_num = (uint8_t) pipeline_num;
+/* set_phy_outport_map(p_acl->pipeline_num, p_acl->links_map);*/
+ register_pipeline_Qs(p_acl->pipeline_num, p);
+ set_link_map(p_acl->pipeline_num, p, p_acl->links_map);
+ set_outport_id(p_acl->pipeline_num, p, p_acl->port_out_id);
+
+ /* If this is the first ACL thread, create common ACL Rule tables */
+ if (rte_ACL_hi_counter_block_in_use == 0) {
+
+ printf("Create ACL Tables rte_socket_id(): %i\n",
+ rte_socket_id());
+
+ /* Create IPV4 ACL Rule Tables */
+ struct rte_table_acl_params common_ipv4_table_acl_params = {
+ .name = "ACLIPV4A",
+ .n_rules = acl_n_rules,
+ .n_rule_fields = RTE_DIM(field_format_ipv4),
+ };
+
+ memcpy(common_ipv4_table_acl_params.field_format,
+ field_format_ipv4, sizeof(field_format_ipv4));
+
+ uint32_t ipv4_entry_size = sizeof(struct acl_table_entry);
+
+ acl_rule_table_ipv4_active =
+ rte_table_acl_ops.f_create(&common_ipv4_table_acl_params,
+ rte_socket_id(),
+ ipv4_entry_size);
+
+ if (acl_rule_table_ipv4_active == NULL) {
+ printf
+ ("Failed to create common ACL IPV4A Rule table\n");
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ /* Create second IPV4 Table */
+ common_ipv4_table_acl_params.name = "ACLIPV4B";
+ acl_rule_table_ipv4_standby =
+ rte_table_acl_ops.f_create(&common_ipv4_table_acl_params,
+ rte_socket_id(),
+ ipv4_entry_size);
+
+ if (acl_rule_table_ipv4_standby == NULL) {
+ printf
+ ("Failed to create common ACL IPV4B Rule table\n");
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ /* Create IPV6 ACL Rule Tables */
+ struct rte_table_acl_params common_ipv6_table_acl_params = {
+ .name = "ACLIPV6A",
+ .n_rules = acl_n_rules,
+ .n_rule_fields = RTE_DIM(field_format_ipv6),
+ };
+
+ memcpy(common_ipv6_table_acl_params.field_format,
+ field_format_ipv6, sizeof(field_format_ipv6));
+
+ uint32_t ipv6_entry_size = sizeof(struct acl_table_entry);
+
+ acl_rule_table_ipv6_active =
+ rte_table_acl_ops.f_create(&common_ipv6_table_acl_params,
+ rte_socket_id(),
+ ipv6_entry_size);
+
+ if (acl_rule_table_ipv6_active == NULL) {
+ printf
+ ("Failed to create common ACL IPV6A Rule table\n");
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ /* Create second IPV6 table */
+ common_ipv6_table_acl_params.name = "ACLIPV6B";
+ acl_rule_table_ipv6_standby =
+ rte_table_acl_ops.f_create(&common_ipv6_table_acl_params,
+ rte_socket_id(),
+ ipv6_entry_size);
+
+ if (acl_rule_table_ipv6_standby == NULL) {
+ printf
+ ("Failed to create common ACL IPV6B Rule table\n");
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Tables */
+ p->n_tables = 1;
+ {
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_stub_ops,
+ .arg_create = NULL,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ int status = rte_pipeline_table_create(p->p,
+ &table_params,
+ &p->table_id[0]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT_META
+ };
+
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ status = rte_pipeline_table_default_entry_add(p->p,
+ p->table_id[0],
+ &default_entry,
+ &default_entry_ptr);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Connecting input ports to tables */
+ for (i = 0; i < p->n_ports_in; i++) {
+ int status = rte_pipeline_port_in_connect_to_table(p->p,
+ p->port_in_id
+ [i],
+ p->table_id
+ [0]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < p->n_ports_in; i++) {
+ int status = rte_pipeline_port_in_enable(p->p,
+ p->port_in_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p->p) < 0) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ /* Message queues */
+ p->n_msgq = params->n_msgq;
+ for (i = 0; i < p->n_msgq; i++)
+ p->msgq_in[i] = params->msgq_in[i];
+ for (i = 0; i < p->n_msgq; i++)
+ p->msgq_out[i] = params->msgq_out[i];
+
+ /* Message handlers */
+ memcpy(p->handlers, handlers, sizeof(p->handlers));
+ memcpy(p_acl->custom_handlers,
+ custom_handlers, sizeof(p_acl->custom_handlers));
+
+ return p;
+}
+
+/**
+ * Free resources and delete pipeline.
+ *
+ * @param p
+ * A pointer to the pipeline.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int pipeline_acl_free(void *pipeline)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ /* Check input arguments */
+ if (p == NULL)
+ return -1;
+
+ /* Free resources */
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return 0;
+}
+
+/**
+ * Callback function to map input/output ports.
+ *
+ * @param pipeline
+ * A pointer to the pipeline.
+ * @param port_in
+ * Input port ID
+ * @param port_out
+ * A pointer to the Output port.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+pipeline_acl_track(void *pipeline,
+ __rte_unused uint32_t port_in, uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_in == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ * Callback function to process timers.
+ *
+ * @param pipeline
+ * A pointer to the pipeline.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int pipeline_acl_timer(void *pipeline)
+{
+
+ struct pipeline *p = (struct pipeline *)pipeline;
+ struct pipeline_acl *p_acl = (struct pipeline_acl *)pipeline;
+
+ pipeline_msg_req_handle(p);
+ rte_pipeline_flush(p->p);
+
+ rte_ct_handle_expired_timers(p_acl->cnxn_tracker);
+
+ return 0;
+}
+
+/**
+ * Callback function to process CLI commands from FE.
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param msg
+ * A pointer to command specific data.
+ *
+ * @return
+ * A pointer to message handler on success,
+ * pipeline_msg_req_invalid_hander on error.
+ */
+void *pipeline_acl_msg_req_custom_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_acl *p_acl = (struct pipeline_acl *)p;
+ struct pipeline_custom_msg_req *req = msg;
+ pipeline_msg_req_handler f_handle;
+
+ f_handle = (req->subtype < PIPELINE_ACL_MSG_REQS) ?
+ p_acl->custom_handlers[req->subtype] :
+ pipeline_msg_req_invalid_handler;
+
+ if (f_handle == NULL)
+ f_handle = pipeline_msg_req_invalid_handler;
+
+ return f_handle(p, req);
+}
+
+/**
+ * Handler for DBG CLI command.
+ *
+ * @param p
+ * A pointer to the pipeline.
+ * @param msg
+ * A pointer to command specific data.
+ *
+ * @return
+ * A pointer to response message.
+ * Response message contains status.
+ */
+void *pipeline_acl_msg_req_dbg_handler(struct pipeline *p, void *msg)
+{
+ (void)p;
+ struct pipeline_acl_dbg_msg_req *req = msg;
+ struct pipeline_acl_dbg_msg_rsp *rsp = msg;
+
+ if (req->dbg == 0) {
+ printf("DBG turned OFF\n");
+ ACL_DEBUG = 0;
+ rsp->status = 0;
+ } else if (req->dbg == 1) {
+ printf("DBG turned ON\n");
+ ACL_DEBUG = 1;
+ rsp->status = 0;
+ } else {
+ printf("Invalid DBG setting\n");
+ rsp->status = -1;
+ }
+
+ return rsp;
+}
+
+struct pipeline_be_ops pipeline_acl_be_ops = {
+ .f_init = pipeline_acl_init,
+ .f_free = pipeline_acl_free,
+ .f_run = NULL,
+ .f_timer = pipeline_acl_timer,
+ .f_track = pipeline_acl_track,
+};