summaryrefslogtreecommitdiffstats
path: root/common/VIL/acl/lib_acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/acl/lib_acl.c')
-rw-r--r--common/VIL/acl/lib_acl.c1203
1 files changed, 1203 insertions, 0 deletions
diff --git a/common/VIL/acl/lib_acl.c b/common/VIL/acl/lib_acl.c
new file mode 100644
index 00000000..279727ef
--- /dev/null
+++ b/common/VIL/acl/lib_acl.c
@@ -0,0 +1,1203 @@
+/*
+// 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.
+*/
+#include "lib_acl.h"
+#include "vnf_common.h"
+#include <rte_port.h>
+#define ACL_LIB_DEBUG 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),
+ },
+};
+
+void *lib_acl_create_active_standby_table_ipv4(uint8_t table_num,
+ uint32_t *libacl_n_rules)
+{
+ printf("Create LIBACL active IPV4 Tables rte_socket_id(): %i\n",
+ rte_socket_id());
+
+ /* Create IPV4 LIBACL Rule Tables */
+ struct rte_table_acl_params common_ipv4_table_libacl_params = {
+ .name = "LIBACLIPV4A",
+ .n_rules = *libacl_n_rules,
+ .n_rule_fields = RTE_DIM(field_format_ipv4),
+ };
+
+ memcpy(common_ipv4_table_libacl_params.field_format,
+ field_format_ipv4, sizeof(field_format_ipv4));
+
+ uint32_t ipv4_entry_size = sizeof(struct lib_acl_table_entry);
+ /* Create second IPV4 Table */
+ if (table_num == 2)
+ common_ipv4_table_libacl_params.name = "LIBACLIPV4B";
+ return rte_table_acl_ops.f_create(&common_ipv4_table_libacl_params,
+ rte_socket_id(),
+ ipv4_entry_size);
+
+
+}
+
+void *lib_acl_create_active_standby_table_ipv6(uint8_t table_num,
+ uint32_t *libacl_n_rules)
+{
+ printf("Create LIBACL active IPV6 Tables rte_socket_id(): %i\n",
+ rte_socket_id());
+ /* Create IPV6 LIBACL Rule Tables */
+ struct rte_table_acl_params common_ipv6_table_libacl_params = {
+ .name = "LIBACLIPV6A",
+ .n_rules = *libacl_n_rules,
+ .n_rule_fields = RTE_DIM(field_format_ipv6),
+ };
+
+ memcpy(common_ipv6_table_libacl_params.field_format,
+ field_format_ipv6, sizeof(field_format_ipv6));
+
+ uint32_t ipv6_entry_size = sizeof(struct lib_acl_table_entry);
+ /* Create second IPV6 table */
+ if (table_num == 2)
+ common_ipv6_table_libacl_params.name = "LIBACLIPV6B";
+ return rte_table_acl_ops.f_create(&common_ipv6_table_libacl_params,
+ rte_socket_id(),
+ ipv6_entry_size);
+
+
+}
+int lib_acl_parse_config(struct lib_acl *plib_acl,
+ char *arg_name, char *arg_value,
+ uint32_t *libacl_n_rules)
+{
+ uint32_t n_rules_present = 0;
+ uint32_t pkt_type_present = 0;
+ /* defaults */
+ plib_acl->n_rules = DEFULT_NUM_RULE;
+ *libacl_n_rules = DEFULT_NUM_RULE;
+ plib_acl->n_rule_fields = RTE_DIM(field_format_ipv4);
+ plib_acl->field_format = field_format_ipv4;
+ plib_acl->field_format_size = sizeof(field_format_ipv4);
+ if (strcmp(arg_name, "n_rules") == 0) {
+ if (n_rules_present) {
+ printf("n_rules_present");
+ return -1;
+ }
+ n_rules_present = 1;
+
+ plib_acl->n_rules = atoi(arg_value);
+ *libacl_n_rules = atoi(arg_value);
+ return 0;
+ }
+ if (strcmp(arg_name, "pkt_type") == 0) {
+ if (pkt_type_present) {
+ printf("pkt_type");
+ return -1;
+ }
+ pkt_type_present = 1;
+
+ /* ipv4 */
+ if (strcmp(arg_value, "ipv4") == 0) {
+ plib_acl->n_rule_fields =
+ RTE_DIM(field_format_ipv4);
+ plib_acl->field_format = field_format_ipv4;
+ plib_acl->field_format_size =
+ sizeof(field_format_ipv4);
+ return 0;
+ }
+
+ /* vlan_ipv4 */
+ if (strcmp(arg_value, "vlan_ipv4") == 0) {
+ plib_acl->n_rule_fields =
+ RTE_DIM(field_format_vlan_ipv4);
+ plib_acl->field_format =
+ field_format_vlan_ipv4;
+ plib_acl->field_format_size =
+ sizeof(field_format_vlan_ipv4);
+ return 0;
+ }
+
+ /* qinq_ipv4 */
+ if (strcmp(arg_value, "qinq_ipv4") == 0) {
+ plib_acl->n_rule_fields =
+ RTE_DIM(field_format_qinq_ipv4);
+ plib_acl->field_format =
+ field_format_qinq_ipv4;
+ plib_acl->field_format_size =
+ sizeof(field_format_qinq_ipv4);
+ return 0;
+ }
+
+ /* ipv6 */
+ if (strcmp(arg_value, "ipv6") == 0) {
+ plib_acl->n_rule_fields =
+ RTE_DIM(field_format_ipv6);
+ plib_acl->field_format = field_format_ipv6;
+ plib_acl->field_format_size =
+ sizeof(field_format_ipv6);
+ return 0;
+ }
+ /* other */
+ printf("other");
+ return -1;
+ }
+ /* Parameter not processed in this parse function */
+ return 1;
+}
+/**
+ * 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.
+ */
+ uint64_t
+lib_acl_pkt_work_key(struct lib_acl *plib_acl,
+ struct rte_mbuf **pkts, uint64_t pkts_mask,
+ uint64_t *pkts_drop_without_rule,
+ void *plib_acl_rule_table_ipv4_active,
+ void *plib_acl_rule_table_ipv6_active,
+ struct pipeline_action_key *action_array_active,
+ struct action_counter_block (*p_action_counter_table)[action_array_max],
+ uint64_t *conntrack_mask,
+ uint64_t *connexist_mask,
+ int lib_acl_ipv4_enabled, int lib_acl_ipv6_enabled)
+{
+
+ 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;
+ int status;
+
+
+ if (lib_acl_ipv4_enabled) {
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV4 Lookup Mask Before = 0x%"PRIx64"\n",
+ pkts_mask);
+ status = rte_table_acl_ops.f_lookup(
+ plib_acl_rule_table_ipv4_active,
+ pkts, pkts_mask, &lookup_hit_mask_ipv4,
+ (void **) plib_acl->plib_acl_entries_ipv4);
+ if (status < 0)
+ printf("Lookup failed\n");
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV4 Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask_ipv4);
+ }
+
+ if (lib_acl_ipv6_enabled) {
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV6 Lookup Mask Before = 0x%"PRIx64"\n",
+ pkts_mask);
+ status = rte_table_acl_ops.f_lookup(
+ plib_acl_rule_table_ipv6_active,
+ pkts, pkts_mask, &lookup_hit_mask_ipv6,
+ (void **) plib_acl->plib_acl_entries_ipv6);
+ if (status < 0)
+ printf("Lookup Failed\n");
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV6 Lookup Mask After = 0x%"PRIx64"\n",
+ 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_LIB_DEBUG)
+ printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask);
+
+ lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
+ pkts_mask = lookup_hit_mask;
+ *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask);
+ if (ACL_LIB_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ *pkts_drop_without_rule,
+ __builtin_popcountll(lookup_miss_mask));
+ /* bitmap of packets left to process for ARP */
+ uint64_t pkts_to_process = lookup_hit_mask;
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
+ /* bitmask representing only this packet */
+ uint64_t pkt_mask = 1LLU << pos;
+ /* remove this packet from remaining list */
+ pkts_to_process &= ~pkt_mask;
+ struct rte_mbuf *pkt = pkts[pos];
+
+ uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, IP_START);
+
+ hdr_chk = hdr_chk >> IP_VERSION_CHECK;
+
+ if (hdr_chk == IPv4_HDR_VERSION) {
+
+ struct lib_acl_table_entry *entry =
+ (struct lib_acl_table_entry *)
+ plib_acl->plib_acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_LIB_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ uint32_t dscp_offset = IP_START + IP_HDR_DSCP_OFST;
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_count) {
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount++;
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_LIB_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %"
+ PRIu64 "\n"
+ , p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount,
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_drop) {
+
+ /* Drop packet by changing the mask */
+ if (ACL_LIB_DEBUG)
+ printf("ACL before drop pkt_mask %"
+ PRIx64", pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ (*pkts_drop_without_rule)++;
+ if (ACL_LIB_DEBUG)
+ printf("ACL after drop pkt_mask %"PRIx64
+ ", pkt_num %d, packet_drop%"
+ PRIu64"\n", pkts_mask, pos,
+ *pkts_drop_without_rule);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_fwd) {
+ phy_port = action_array_active[action_id].
+ fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action FWD Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_nat) {
+ phy_port = action_array_active[action_id].
+ nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action NAT Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_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_LIB_DEBUG)
+ printf("Action DSCP DSCP Priority: %"
+ PRIu16 "\n", *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_accept) {
+ if (ACL_LIB_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ *conntrack_mask |= pkt_mask;
+ if (ACL_LIB_DEBUG)
+ printf("ACL CT enabled: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_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 ==
+ lib_acl_public_private)
+ *connexist_mask |= pkt_mask;
+
+ if (ACL_LIB_DEBUG)
+ printf("Connexist ENB CT:0x%"
+ PRIx64" connexist: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ *connexist_mask,
+ pkt_mask);
+ }
+ }
+ }
+
+ if (hdr_chk == IPv6_HDR_VERSION) {
+
+ struct lib_acl_table_entry *entry =
+ (struct lib_acl_table_entry *)
+ plib_acl->plib_acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_LIB_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_count) {
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount++;
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_LIB_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %"
+ PRIu64 "\n",
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount,
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_drop) {
+ /* Drop packet by changing the mask */
+ if (ACL_LIB_DEBUG)
+ printf("ACL before drop pkt_mask %"
+ PRIx64", pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ (*pkts_drop_without_rule)++;
+ if (ACL_LIB_DEBUG)
+ printf("ACL after drop pkt_mask %"PRIx64
+ ", pkt_num %d, packet_drop %"
+ PRIu64 "\n", pkts_mask, pos,
+ *pkts_drop_without_rule);
+
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_fwd) {
+ phy_port = action_array_active[action_id].
+ fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action FWD Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_nat) {
+ phy_port = action_array_active[action_id].
+ nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action NAT Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint32_t dscp_offset = IP_START +
+ IP_HDR_DSCP_OFST_IPV6;
+ uint16_t *dscp = RTE_MBUF_METADATA_UINT16_PTR(
+ pkt, dscp_offset);
+ uint16_t temp = *dscp;
+ uint16_t dscp_value = (rte_bswap16(temp) &
+ 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_LIB_DEBUG)
+ printf("Action DSCP DSCP Priority: %"
+ PRIu16"\n", *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_packet_accept) {
+ if (ACL_LIB_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ *conntrack_mask |= pkt_mask;
+ if (ACL_LIB_DEBUG)
+ printf("ACL CT enabled: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_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 ==
+ lib_acl_public_private)
+ *connexist_mask |= pkt_mask;
+
+ if (ACL_LIB_DEBUG)
+ printf("Connexist ENB CT:0x%"
+ PRIx64" connexist: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ *connexist_mask,
+ pkt_mask);
+ }
+ }
+ }
+ }
+ return pkts_mask;
+}
+/**
+ * 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.
+ * - 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.
+ */
+ uint64_t
+lib_acl_ipv4_pkt_work_key(struct lib_acl *plib_acl,
+ struct rte_mbuf **pkts, uint64_t pkts_mask,
+ uint64_t *pkts_drop_without_rule,
+ void *plib_acl_rule_table_ipv4_active,
+ struct pipeline_action_key *action_array_active,
+ struct action_counter_block (*p_action_counter_table)[action_array_max],
+ uint64_t *conntrack_mask,
+ uint64_t *connexist_mask)
+{
+
+ uint64_t lookup_hit_mask_ipv4 = 0;
+ uint64_t lookup_miss_mask_ipv4 = 0;
+ int status;
+
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV4 Lookup Mask Before = 0x%"PRIx64"\n",
+ pkts_mask);
+ status = rte_table_acl_ops.f_lookup(
+ plib_acl_rule_table_ipv4_active,
+ pkts, pkts_mask, &lookup_hit_mask_ipv4,
+ (void **) plib_acl->plib_acl_entries_ipv4);
+ if (status < 0)
+ printf("Lookup Failed\n");
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV4 Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask_ipv4);
+ if (ACL_LIB_DEBUG)
+ printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask_ipv4);
+
+ lookup_miss_mask_ipv4 = pkts_mask & (~lookup_hit_mask_ipv4);
+ pkts_mask = lookup_hit_mask_ipv4;
+ *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv4);
+ if (ACL_LIB_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ *pkts_drop_without_rule,
+ __builtin_popcountll(lookup_miss_mask_ipv4));
+ /* bitmap of packets left to process for ARP */
+ uint64_t pkts_to_process = lookup_hit_mask_ipv4;
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
+ /* bitmask representing only this packet */
+ uint64_t pkt_mask = 1LLU << pos;
+ /* remove this packet from remaining list */
+ pkts_to_process &= ~pkt_mask;
+ struct rte_mbuf *pkt = pkts[pos];
+
+
+
+ struct lib_acl_table_entry *entry =
+ (struct lib_acl_table_entry *)
+ plib_acl->plib_acl_entries_ipv4[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_LIB_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ uint32_t dscp_offset = IP_START + IP_HDR_DSCP_OFST;
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_count) {
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount++;
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_LIB_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %"
+ PRIu64 "\n"
+ , p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount,
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_drop) {
+
+ /* Drop packet by changing the mask */
+ if (ACL_LIB_DEBUG)
+ printf("ACL before drop pkt_mask %"
+ PRIx64", pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ (*pkts_drop_without_rule)++;
+ if (ACL_LIB_DEBUG)
+ printf("ACL after drop pkt_mask %" PRIx64
+ ", pkt_num %d, action_packet_drop %"
+ PRIu64 "\n", pkts_mask, pos,
+ *pkts_drop_without_rule);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_fwd) {
+ phy_port = action_array_active[action_id].
+ fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action FWD Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_nat) {
+ phy_port = action_array_active[action_id].
+ nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action NAT Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_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_LIB_DEBUG)
+ printf("Action DSCP DSCP Priority: %"
+ PRIu16 "\n", *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_accept) {
+ if (ACL_LIB_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ *conntrack_mask |= pkt_mask;
+ if (ACL_LIB_DEBUG)
+ printf("ACL CT enabled: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_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 ==
+ lib_acl_public_private)
+ *connexist_mask |= pkt_mask;
+
+ if (ACL_LIB_DEBUG)
+ printf("ACL Connexist ENB CT:0x%"
+ PRIx64" connexist: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ *connexist_mask,
+ pkt_mask);
+ }
+ }
+
+ }
+ return pkts_mask;
+}
+/**
+ * Main packet processing function.
+ * 64 packet bit mask are used to identify which packets to forward.
+ * Performs the following:
+ * - 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.
+ */
+ uint64_t
+lib_acl_ipv6_pkt_work_key(struct lib_acl *plib_acl,
+ struct rte_mbuf **pkts, uint64_t pkts_mask,
+ uint64_t *pkts_drop_without_rule,
+ void *plib_acl_rule_table_ipv6_active,
+ struct pipeline_action_key *action_array_active,
+ struct action_counter_block (*p_action_counter_table)[action_array_max],
+ uint64_t *conntrack_mask,
+ uint64_t *connexist_mask)
+{
+
+ uint64_t lookup_hit_mask_ipv6 = 0;
+ uint64_t lookup_miss_mask_ipv6 = 0;
+ int status;
+
+
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV6 Lookup Mask Before = 0x%"PRIx64"\n",
+ pkts_mask);
+ status = rte_table_acl_ops.f_lookup(
+ plib_acl_rule_table_ipv6_active,
+ pkts, pkts_mask, &lookup_hit_mask_ipv6,
+ (void **) plib_acl->plib_acl_entries_ipv6);
+ if (status < 0)
+ printf("Lookup Failed\n");
+ if (ACL_LIB_DEBUG)
+ printf("ACL IPV6 Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask_ipv6);
+
+ if (ACL_LIB_DEBUG)
+ printf("ACL Lookup Mask After = 0x%"PRIx64"\n",
+ lookup_hit_mask_ipv6);
+
+ lookup_miss_mask_ipv6 = pkts_mask & (~lookup_hit_mask_ipv6);
+ pkts_mask = lookup_hit_mask_ipv6;
+ *pkts_drop_without_rule += __builtin_popcountll(lookup_miss_mask_ipv6);
+ if (ACL_LIB_DEBUG)
+ printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n",
+ *pkts_drop_without_rule,
+ __builtin_popcountll(lookup_miss_mask_ipv6));
+ /* bitmap of packets left to process for ARP */
+ uint64_t pkts_to_process = lookup_hit_mask_ipv6;
+
+ for (; pkts_to_process;) {
+ uint8_t pos = (uint8_t)__builtin_ctzll(pkts_to_process);
+ /* bitmask representing only this packet */
+ uint64_t pkt_mask = 1LLU << pos;
+ /* remove this packet from remaining list */
+ pkts_to_process &= ~pkt_mask;
+ struct rte_mbuf *pkt = pkts[pos];
+
+
+ struct lib_acl_table_entry *entry =
+ (struct lib_acl_table_entry *)
+ plib_acl->plib_acl_entries_ipv6[pos];
+ uint16_t phy_port = entry->head.port_id;
+ uint32_t action_id = entry->action_id;
+
+ if (ACL_LIB_DEBUG)
+ printf("action_id = %u\n", action_id);
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_count) {
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount++;
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount +=
+ rte_pktmbuf_pkt_len(pkt);
+ if (ACL_LIB_DEBUG)
+ printf("Action Count Packet Count: %"
+ PRIu64 " Byte Count: %"
+ PRIu64 "\n",
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].packetCount,
+ p_action_counter_table
+ [plib_acl->action_counter_index]
+ [action_id].byteCount);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_packet_drop) {
+ /* Drop packet by changing the mask */
+ if (ACL_LIB_DEBUG)
+ printf("ACL before drop pkt_mask %"
+ PRIx64", pkt_num %d\n",
+ pkts_mask, pos);
+ pkts_mask &= ~(1LLU << pos);
+ (*pkts_drop_without_rule)++;
+ if (ACL_LIB_DEBUG)
+ printf("ACL after drop pkt_mask %" PRIx64
+ ", pkt_num %d, action_packet_drop %"
+ PRIu64 "\n", pkts_mask, pos,
+ *pkts_drop_without_rule);
+
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_fwd) {
+ phy_port = action_array_active[action_id].
+ fwd_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action FWD Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_nat) {
+ phy_port = action_array_active[action_id].
+ nat_port;
+ entry->head.port_id = phy_port;
+ if (ACL_LIB_DEBUG)
+ printf("Action NAT Port ID: %"
+ PRIu16"\n", phy_port);
+ }
+
+ if (action_array_active[action_id].action_bitmap &
+ lib_acl_action_dscp) {
+
+ /* Set DSCP priority */
+ uint32_t dscp_offset = IP_START +
+ IP_HDR_DSCP_OFST_IPV6;
+ uint16_t *dscp = RTE_MBUF_METADATA_UINT16_PTR(
+ pkt, dscp_offset);
+ uint16_t temp = *dscp;
+ uint16_t dscp_value = (rte_bswap16(temp) &
+ 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_LIB_DEBUG)
+ printf("Action DSCP DSCP Priority: %"
+ PRIu16"\n", *dscp);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_packet_accept) {
+ if (ACL_LIB_DEBUG)
+ printf("Action Accept\n");
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_acl_action_conntrack) {
+
+ /* Set conntrack bit for this pkt */
+ *conntrack_mask |= pkt_mask;
+ if (ACL_LIB_DEBUG)
+ printf("ACL CT enabled: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ pkt_mask);
+ }
+
+ if (action_array_active[action_id].action_bitmap
+ & lib_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 ==
+ lib_acl_public_private)
+ *connexist_mask |= pkt_mask;
+
+ if (ACL_LIB_DEBUG)
+ printf("ACL Connexist ENB CT:0x%"
+ PRIx64" connexist: 0x%"
+ PRIx64" pkt_mask: 0x%"
+ PRIx64"\n",
+ *conntrack_mask,
+ *connexist_mask,
+ pkt_mask);
+ }
+ }
+ }
+ return pkts_mask;
+}