diff options
Diffstat (limited to 'common/VIL/acl')
-rw-r--r-- | common/VIL/acl/lib_acl.c | 1203 | ||||
-rw-r--r-- | common/VIL/acl/lib_acl.h | 127 |
2 files changed, 1330 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; +} diff --git a/common/VIL/acl/lib_acl.h b/common/VIL/acl/lib_acl.h new file mode 100644 index 00000000..6eaaf55f --- /dev/null +++ b/common/VIL/acl/lib_acl.h @@ -0,0 +1,127 @@ +/* +// 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. +*/ + +#ifndef __INCLUDE_ACL_LIB_H__ +#define __INCLUDE_ACL_LIB_H__ + +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <rte_pipeline.h> +#include <rte_table_acl.h> +#include "rte_cnxn_tracking.h" +#include "rte_ct_tcp.h" +/* Define VNF actions for bitmap */ +#define lib_acl_action_packet_drop 1 +#define lib_acl_action_packet_accept 2 +#define lib_acl_action_nat 4 +#define lib_acl_action_fwd 8 +#define lib_acl_action_count 16 +#define lib_acl_action_dscp 32 +#define lib_acl_action_conntrack 64 +#define lib_acl_action_connexist 128 +#define action_array_max 10000 +#define lib_acl_private_public 0 +#define lib_acl_public_private 1 +#define IP_HDR_DSCP_OFST 1 +#define IPv4_HDR_VERSION 4 +#define IPv6_HDR_VERSION 6 +#define IP_HDR_DSCP_OFST_IPV6 0 +#define IP_VERSION_CHECK 4 +#define IP_START (MBUF_HDR_ROOM + ETH_HDR_SIZE) +#define DEFULT_NUM_RULE (4*1024) +/** + * A structure defining the key to store an VNF action. + */ +struct pipeline_action_key { + uint32_t action_id; + uint32_t action_bitmap; + uint32_t nat_port; + uint32_t fwd_port; + uint8_t dscp_priority; + uint8_t private_public; +} __rte_cache_aligned; + +/** + * A structure defining the Action counters. + * One Action Counter Block per VNF thread. + */ +struct action_counter_block { + uint64_t byteCount; + uint64_t packetCount; +} __rte_cache_aligned; + +/** + * A structure defining the ACL library table. + */ +struct lib_acl_table_entry { + struct rte_pipeline_table_entry head; + uint32_t action_id; +}; + + +struct lib_acl { + uint32_t n_rules; + uint32_t n_rule_fields; + struct rte_acl_field_def *field_format; + uint32_t field_format_size; + int action_counter_index; + struct lib_acl_table_entry + *plib_acl_entries_ipv4[RTE_PORT_IN_BURST_SIZE_MAX]; + struct lib_acl_table_entry + *plib_acl_entries_ipv6[RTE_PORT_IN_BURST_SIZE_MAX]; +} __rte_cache_aligned; + +void *lib_acl_create_active_standby_table_ipv4(uint8_t table_num, + uint32_t *libacl_n_rules); + +void *lib_acl_create_active_standby_table_ipv6(uint8_t table_num, + uint32_t *libacl_n_rules); +int lib_acl_parse_config(struct lib_acl *plib_acl, + char *arg_name, char *arg_value, + uint32_t *libacl_n_rules); +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 +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 +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); + + +#endif |