summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Makefile3
-rw-r--r--VNFs/vACL/Makefile107
-rw-r--r--VNFs/vACL/config/IPv4_hwlb_acl.tc42
-rw-r--r--VNFs/vACL/config/IPv4_hwlb_acl_1LB_1t.cfg36
-rw-r--r--VNFs/vACL/config/IPv4_swlb_acl.tc33
-rw-r--r--VNFs/vACL/config/IPv4_swlb_acl_1LB_1t.cfg58
-rw-r--r--VNFs/vACL/config/IPv6_hwlb_acl.tc49
-rw-r--r--VNFs/vACL/config/IPv6_hwlb_acl_1LB_1t.cfg37
-rw-r--r--VNFs/vACL/config/IPv6_swlb_acl.tc40
-rw-r--r--VNFs/vACL/config/IPv6_swlb_acl_1LB_1t.cfg59
-rw-r--r--VNFs/vACL/init.c1383
-rw-r--r--VNFs/vACL/main.c50
-rw-r--r--VNFs/vACL/pipeline/pipeline_acl.c4178
-rw-r--r--VNFs/vACL/pipeline/pipeline_acl.h144
-rw-r--r--VNFs/vACL/pipeline/pipeline_acl_be.c3639
-rw-r--r--VNFs/vACL/pipeline/pipeline_acl_be.h228
-rw-r--r--docs/vACL/INSTALL.rst176
-rw-r--r--docs/vACL/README.rst142
-rw-r--r--docs/vACL/RELEASE_NOTES.rst69
19 files changed, 10472 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 68feab0d..9cb9fb7c 100644
--- a/Makefile
+++ b/Makefile
@@ -21,9 +21,10 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc
TARGETS := all clean
VNF_DIR := VNFs
+ACL := $(VNF_DIR)/vACL
CGNAPT := $(VNF_DIR)/vCGNAPT
-subdirs := $(CGNAPT)
+subdirs := $(ACL) $(CGNAPT)
.PHONY: $(TARGETS) $(subdirs)
diff --git a/VNFs/vACL/Makefile b/VNFs/vACL/Makefile
new file mode 100644
index 00000000..febfc7b6
--- /dev/null
+++ b/VNFs/vACL/Makefile
@@ -0,0 +1,107 @@
+# 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.
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+ifeq ($(VNF_CORE),)
+$(error "Please define VNF_CORE environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+DIRS-(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = vACL
+
+
+VPATH += $(VNF_CORE)/common/vnf_common
+VPATH += $(VNF_CORE)/common/VIL/conntrack
+VPATH += $(VNF_CORE)/common/VIL/pipeline_common
+VPATH += $(VNF_CORE)/common/VIL/pipeline_loadb
+VPATH += $(VNF_CORE)/common/VIL/pipeline_master
+VPATH += $(VNF_CORE)/common/VIL/pipeline_passthrough
+VPATH += $(SRCDIR)/pipeline
+VPATH += $(VNF_CORE)/common/VIL/l2l3_stack
+VPATH += $(VNF_CORE)/common/VIL/pipeline_txrx
+VPATH += $(VNF_CORE)/common/VIL/pipeline_arpicmp
+
+INC += $(wildcard *.h)
+INC += $(wildcard pipeline/*.h)
+INC += $(wildcard $(VNF_CORE)/common/vnf_common/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_arpicmp/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/conntrack/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_loadb/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_common/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_master/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_passthrough/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_txrx/*.h)
+INC += $(wildcard $(VNF_CORE)/common/VIL/l2l3_stack/*.h)
+
+CFLAGS += -I$(SRCDIR) -mrtm -mhle -I$(SRCDIR)/pipeline -I$(VNF_CORE)/common/vnf_common
+CFLAGS += -I$(VNF_CORE)/common/VIL/l2l3_stack -I$(VNF_CORE)/common/VIL/conntrack
+CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_common -I$(VNF_CORE)/common/VIL/pipeline_loadb
+CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_master -I$(VNF_CORE)/common/VIL/pipeline_passthrough
+CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_txrx
+CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_arpicmp
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread_fe.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib_arp.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib_icmpv6.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += interface.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += hle.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += tsx.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += l2_proto.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += l3fwd_main.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += l3fwd_lpm4.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += l3fwd_lpm6.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += bond.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_fe.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_ct_tcp.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_cnxn_tracking.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_ct_udp.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_ct_synproxy.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_loadb.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_loadb_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_acl.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_acl_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += vnf_common.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_arpicmp.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_arpicmp_be.c
+
+CFLAGS += -O3
+CFLAGS += -DIPV6
+CFLAGS += -Wno-error=unused-function -Wno-error=unused-variable
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/VNFs/vACL/config/IPv4_hwlb_acl.tc b/VNFs/vACL/config/IPv4_hwlb_acl.tc
new file mode 100644
index 00000000..fa4f1430
--- /dev/null
+++ b/VNFs/vACL/config/IPv4_hwlb_acl.tc
@@ -0,0 +1,42 @@
+; 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.
+
+link 0 down
+link 0 config 192.16.100.10 8
+link 0 up
+link 1 down
+link 1 config 152.16.40.10 8
+link 1 up
+
+p 1 arpadd 1 152.16.40.20 00:00:00:00:00:02
+p 1 arpadd 0 192.16.100.20 00:00:00:00:00:01
+p action add 0 accept
+p action add 0 fwd 0
+p action add 0 count
+p action add 1 accept
+p action add 1 fwd 1
+p action add 1 count
+
+p acl add 1 192.16.100.0 8 152.16.40.0 8 0 65535 0 65535 0 0 1
+p acl add 1 152.16.40.0 8 192.16.100.0 8 0 65535 0 65535 0 0 0
+p acl applyruleset
+set fwd rxonly
+set_sym_hash_ena_per_port 0 enable
+set_hash_global_config 0 simple_xor ipv4-udp enable
+set_sym_hash_ena_per_port 1 enable
+set_hash_global_config 1 simple_xor ipv4-udp enable
+
+set_hash_input_set 0 ipv4-udp src-ipv4 udp-src-port add
+set_hash_input_set 1 ipv4-udp dst-ipv4 udp-dst-port add
+
diff --git a/VNFs/vACL/config/IPv4_hwlb_acl_1LB_1t.cfg b/VNFs/vACL/config/IPv4_hwlb_acl_1LB_1t.cfg
new file mode 100644
index 00000000..77beeb14
--- /dev/null
+++ b/VNFs/vACL/config/IPv4_hwlb_acl_1LB_1t.cfg
@@ -0,0 +1,36 @@
+; 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.
+
+[PIPELINE0]
+type = MASTER
+core = 0
+[PIPELINE1]
+type = ARPICMP
+core = 1
+pktq_in = SWQ0
+pktq_out = TXQ0.0 TXQ1.0
+arp_route_tbl = (98102814,ff000000,1,98102814) (c0106414,ff000000,0,c0106414)
+ports_mac_list = 00:00:00:00:00:01 00:00:00:00:00:02
+pktq_in_prv = RXQ0.0
+prv_to_pub_map = (0,1)
+prv_que_handler = (0)
+[PIPELINE2]
+type = ACL
+core = 2
+pktq_in = RXQ0.0 RXQ1.0
+pktq_out = TXQ0.1 TXQ1.1 SWQ0
+n_flows = 1000000
+pkt_type = ipv4
+traffic_type = 4
+
diff --git a/VNFs/vACL/config/IPv4_swlb_acl.tc b/VNFs/vACL/config/IPv4_swlb_acl.tc
new file mode 100644
index 00000000..25fdfba6
--- /dev/null
+++ b/VNFs/vACL/config/IPv4_swlb_acl.tc
@@ -0,0 +1,33 @@
+; 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.
+
+link 0 down
+link 0 config 192.16.100.10 8
+link 0 up
+link 1 down
+link 1 config 192.16.40.10 8
+link 1 up
+
+;p 1 arpadd 1 192.16.40.20 00:00:00:00:00:02
+;p 1 arpadd 0 192.16.100.20 00:00:00:00:00:01
+p action add 0 accept
+p action add 0 fwd 0
+p action add 0 count
+p action add 1 accept
+p action add 1 fwd 1
+p action add 1 count
+
+p acl add 1 192.16.100.0 8 192.16.40.0 8 0 65535 0 65535 0 0 1
+p acl add 1 192.16.40.0 8 192.16.100.0 8 0 65535 0 65535 0 0 0
+p acl applyruleset
diff --git a/VNFs/vACL/config/IPv4_swlb_acl_1LB_1t.cfg b/VNFs/vACL/config/IPv4_swlb_acl_1LB_1t.cfg
new file mode 100644
index 00000000..2637ec1d
--- /dev/null
+++ b/VNFs/vACL/config/IPv4_swlb_acl_1LB_1t.cfg
@@ -0,0 +1,58 @@
+; 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.
+
+[PIPELINE0]
+type = MASTER
+core = 0
+[PIPELINE1]
+type = ARPICMP
+core = 1
+pktq_in = SWQ2
+pktq_out = TXQ0.0 TXQ1.0
+arp_route_tbl = (c0102814,ffffff00,1,98102814) (c0106414,ffffff00,0,c0106414)
+ports_mac_list = 00:00:00:00:00:01 00:00:00:00:00:02
+pktq_in_prv = RXQ0.0
+prv_to_pub_map = (0,1)
+prv_que_handler = (0)
+
+[PIPELINE2]
+type = TXRX
+core = 2
+pktq_in = RXQ0.0 RXQ1.0
+pktq_out = SWQ0 SWQ1 SWQ2
+pipeline_txrx_type = RXRX
+dest_if_offset=176
+[PIPELINE3]
+type = LOADB
+core = 3
+pktq_in = SWQ0 SWQ1
+pktq_out = SWQ3 SWQ4
+outport_offset = 136
+phyport_offset = 204
+n_vnf_threads = 1
+prv_que_handler = (0)
+[PIPELINE4]
+type = ACL
+core = 4
+pktq_in = SWQ3 SWQ4
+pktq_out = SWQ5 SWQ6
+n_flows = 1000000
+pkt_type = ipv4
+traffic_type = 4
+[PIPELINE5]
+type = TXRX
+core = 5
+pktq_in = SWQ5 SWQ6
+pktq_out = TXQ0.1 TXQ1.1
+pipeline_txrx_type = TXTX
diff --git a/VNFs/vACL/config/IPv6_hwlb_acl.tc b/VNFs/vACL/config/IPv6_hwlb_acl.tc
new file mode 100644
index 00000000..3ec5fba7
--- /dev/null
+++ b/VNFs/vACL/config/IPv6_hwlb_acl.tc
@@ -0,0 +1,49 @@
+; 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.
+
+link 0 down
+link 0 config fec0:0000:0000:0000:6a05:caff:fe30:21a0 64
+link 0 up
+link 1 down
+link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64
+link 1 up
+p 1 arpadd 0 fec0::6a05:caff:fe30:21b0 00:00:00:00:00:01
+p 1 arpadd 1 2012::6a05:caff:fe30:2081 00:00:00:00:00:02
+p action add 0 accept
+p action add 0 fwd 1
+p action add 0 count
+
+p action add 1 accept
+p action add 1 fwd 0
+p action add 1 count
+
+
+;p action add 0 conntrack
+;p action add 1 conntrack
+;p action add 2 conntrack
+;p action add 3 conntrack
+
+p acl add 1 fec0::6a05:caff:fe30:21b0 64 2012::6a05:caff:fe30:2081 64 0 65535 0 65535 0 0 0
+p acl add 1 2012::6a05:caff:fe30:2081 64 fec0::6a05:caff:fe30:21b0 64 0 65535 0 65535 0 0 1
+p acl applyruleset
+set fwd rxonly
+set_sym_hash_ena_per_port 0 enable
+set_hash_global_config 0 simple_xor ipv6-udp enable
+set_sym_hash_ena_per_port 1 enable
+set_hash_global_config 1 simple_xor ipv6-udp enable
+
+set_hash_input_set 0 ipv6-udp src-ipv6 udp-src-port add
+set_hash_input_set 1 ipv6-udp dst-ipv6 udp-dst-port add
+
+
diff --git a/VNFs/vACL/config/IPv6_hwlb_acl_1LB_1t.cfg b/VNFs/vACL/config/IPv6_hwlb_acl_1LB_1t.cfg
new file mode 100644
index 00000000..cdb16ca0
--- /dev/null
+++ b/VNFs/vACL/config/IPv6_hwlb_acl_1LB_1t.cfg
@@ -0,0 +1,37 @@
+; 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.
+
+[PIPELINE0]
+type = MASTER
+core = 0
+[PIPELINE1]
+type = ARPICMP
+core = 1
+pktq_in = SWQ0
+pktq_out = TXQ0.0 TXQ1.0
+nd_route_tbl = (fe80::6a05:caff:fe30:21b0,64,0,fe80::6a05:caff:fe30:21b0)
+nd_route_tbl = (2012::6a05:caff:fe30:2081,64,1,2012::6a05:caff:fe30:2081)
+ports_mac_list = 00:00:00:00:00:01 00:00:00:00:00:02
+pktq_in_prv = RXQ0.0
+prv_to_pub_map = (0,1)
+prv_que_handler = (0)
+[PIPELINE2]
+type = ACL
+core = 2
+pktq_in = RXQ0.0 RXQ1.0
+pktq_out = TXQ0.1 TXQ1.1 SWQ0
+n_flows = 1000000
+pkt_type = ipv6
+traffic_type = 6
+
diff --git a/VNFs/vACL/config/IPv6_swlb_acl.tc b/VNFs/vACL/config/IPv6_swlb_acl.tc
new file mode 100644
index 00000000..0dc82129
--- /dev/null
+++ b/VNFs/vACL/config/IPv6_swlb_acl.tc
@@ -0,0 +1,40 @@
+; 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.
+
+link 0 down
+link 0 config fe80:0000:0000:0000:6a05:caff:fe30:21a0 64
+link 0 up
+link 1 down
+link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64
+link 1 up
+p 1 arpadd 0 fe80::6a05:caff:fe30:21b0 00:00:00:00:00:01
+p 1 arpadd 1 2012::6a05:caff:fe30:2081 3c:fd:fe:a1:37:aa
+p action add 0 accept
+p action add 0 fwd 1
+p action add 0 count
+
+p action add 1 accept
+p action add 1 fwd 0
+p action add 1 count
+
+
+;p action add 0 conntrack
+;p action add 1 conntrack
+;p action add 2 conntrack
+;p action add 3 conntrack
+
+p acl add 1 fe80::6a05:caff:fe30:21b0 64 2012::6a05:caff:fe30:2081 64 0 65535 0 65535 0 0 0
+p acl add 1 2012::6a05:caff:fe30:2081 64 fe80::6a05:caff:fe30:21b0 64 0 65535 0 65535 0 0 1
+p acl applyruleset
+
diff --git a/VNFs/vACL/config/IPv6_swlb_acl_1LB_1t.cfg b/VNFs/vACL/config/IPv6_swlb_acl_1LB_1t.cfg
new file mode 100644
index 00000000..43d0e726
--- /dev/null
+++ b/VNFs/vACL/config/IPv6_swlb_acl_1LB_1t.cfg
@@ -0,0 +1,59 @@
+; 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.
+
+[PIPELINE0]
+type = MASTER
+core = 0
+[PIPELINE1]
+type = ARPICMP
+core = 1
+pktq_in = SWQ2
+pktq_out = TXQ0.0 TXQ1.0
+nd_route_tbl = (fe80::6a05:caff:fe30:21b0,64,0,fe80::6a05:caff:fe30:21b0)
+nd_route_tbl = (2012::6a05:caff:fe30:2081,64,1,2012::6a05:caff:fe30:2081)
+ports_mac_list = 00:00:00:00:00:01 00:00:00:00:00:02
+pktq_in_prv = RXQ0.0
+prv_to_pub_map = (0,1)
+prv_que_handler = (0)
+
+[PIPELINE2]
+type = TXRX
+core = 2
+pktq_in = RXQ0.0 RXQ1.0
+pktq_out = SWQ0 SWQ1 SWQ2
+pipeline_txrx_type = RXRX
+dest_if_offset=176
+[PIPELINE3]
+type = LOADB
+core = 3
+pktq_in = SWQ0 SWQ1
+pktq_out = SWQ3 SWQ4
+outport_offset = 136
+phyport_offset = 204
+n_vnf_threads = 1
+prv_que_handler = (0)
+[PIPELINE4]
+type = ACL
+core = 4
+pktq_in = SWQ3 SWQ4
+pktq_out = SWQ5 SWQ6
+n_flows = 1000000
+pkt_type = ipv6
+traffic_type = 6
+[PIPELINE5]
+type = TXRX
+core = 5
+pktq_in = SWQ5 SWQ6
+pktq_out = TXQ0.1 TXQ1.1
+pipeline_txrx_type = TXTX
diff --git a/VNFs/vACL/init.c b/VNFs/vACL/init.c
new file mode 100644
index 00000000..e85dc297
--- /dev/null
+++ b/VNFs/vACL/init.c
@@ -0,0 +1,1383 @@
+/*
+// 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 <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_eal.h>
+#include <rte_malloc.h>
+
+#include "app.h"
+#include "pipeline.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_master.h"
+//#include "pipeline_passthrough.h"
+#include "thread_fe.h"
+#include "pipeline_loadb.h"
+#include "pipeline_arpicmp.h"
+#include "pipeline_acl.h"
+#include "pipeline_txrx.h"
+
+#include "interface.h"
+#include "l3fwd_common.h"
+#include "l3fwd_lpm4.h"
+#include "l3fwd_lpm6.h"
+#include "lib_arp.h"
+
+#define APP_NAME_SIZE 32
+
+/* Core Mask String in Hex Representation */
+#define APP_CORE_MASK_STRING_SIZE ((64 * APP_CORE_MASK_SIZE) / 8 * 2 + 1)
+
+port_config_t *port_config;
+uint32_t timer_lcore;
+
+static void
+app_init_core_map(struct app_params *app)
+{
+ APP_LOG(app, HIGH, "Initializing CPU core map ...");
+ app->core_map = cpu_core_map_init(4, 32, 4, 0);
+
+ if (app->core_map == NULL)
+ rte_panic("Cannot create CPU core map\n");
+
+ if (app->log_level >= APP_LOG_LEVEL_LOW)
+ cpu_core_map_print(app->core_map);
+}
+
+static void
+app_init_core_mask(struct app_params *app)
+{
+ char core_mask_str[APP_CORE_MASK_STRING_SIZE];
+ uint32_t i;
+
+ for (i = 0; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ int lcore_id;
+
+ lcore_id = cpu_core_map_get_lcore_id(app->core_map,
+ p->socket_id,
+ p->core_id,
+ p->hyper_th_id);
+
+ if (lcore_id < 0)
+ rte_panic("Cannot create CPU core mask\n");
+
+ app_core_enable_in_core_mask(app, lcore_id);
+ }
+
+ app_core_build_core_mask_string(app, core_mask_str);
+ APP_LOG(app, HIGH, "CPU core mask = 0x%s", core_mask_str);
+
+}
+
+static void
+app_init_eal(struct app_params *app)
+{
+ char buffer[256];
+ char core_mask_str[APP_CORE_MASK_STRING_SIZE];
+ struct app_eal_params *p = &app->eal_params;
+ uint8_t n_args = 0;
+ uint32_t i;
+ int status;
+
+ app->eal_argv[n_args++] = strdup(app->app_name);
+
+ app_core_build_core_mask_string(app, core_mask_str);
+ snprintf(buffer, sizeof(buffer), "-c%s", core_mask_str);
+ app->eal_argv[n_args++] = strdup(buffer);
+
+ if (p->coremap) {
+ snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->master_lcore_present) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--master-lcore=%" PRIu32,
+ p->master_lcore);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels);
+ app->eal_argv[n_args++] = strdup(buffer);
+
+ if (p->memory_present) {
+ snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->ranks_present) {
+ snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->pci_blacklist[i] == NULL)
+ break;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--pci-blacklist=%s",
+ p->pci_blacklist[i]);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (app->port_mask != 0)
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->pci_whitelist[i] == NULL)
+ break;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--pci-whitelist=%s",
+ p->pci_whitelist[i]);
+ if (n_args < 256)
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+ else
+ for (i = 0; i < app->n_links; i++) {
+ char *pci_bdf = app->link_params[i].pci_bdf;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--pci-whitelist=%s",
+ pci_bdf);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->vdev[i] == NULL)
+ break;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--vdev=%s",
+ p->vdev[i]);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) {
+ snprintf(buffer, sizeof(buffer), "--vmware-tsc-map");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->proc_type) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--proc-type=%s",
+ p->proc_type);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->syslog) {
+ snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->log_level_present) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--log-level=%" PRIu32,
+ p->log_level);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->version_present) && p->version) {
+ snprintf(buffer, sizeof(buffer), "-v");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->help_present) && p->help) {
+ snprintf(buffer, sizeof(buffer), "--help");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->no_huge_present) && p->no_huge) {
+ snprintf(buffer, sizeof(buffer), "--no-huge");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->no_pci_present) && p->no_pci) {
+ snprintf(buffer, sizeof(buffer), "--no-pci");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->no_hpet_present) && p->no_hpet) {
+ snprintf(buffer, sizeof(buffer), "--no-hpet");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->no_shconf_present) && p->no_shconf) {
+ snprintf(buffer, sizeof(buffer), "--no-shconf");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->add_driver) {
+ snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->socket_mem) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--socket-mem=%s",
+ p->socket_mem);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->huge_dir) {
+ snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->file_prefix) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--file-prefix=%s",
+ p->file_prefix);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->base_virtaddr) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--base-virtaddr=%s",
+ p->base_virtaddr);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->create_uio_dev_present) && p->create_uio_dev) {
+ snprintf(buffer, sizeof(buffer), "--create-uio-dev");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if (p->vfio_intr) {
+ snprintf(buffer,
+ sizeof(buffer),
+ "--vfio-intr=%s",
+ p->vfio_intr);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ if ((p->xen_dom0_present) && (p->xen_dom0)) {
+ snprintf(buffer, sizeof(buffer), "--xen-dom0");
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ snprintf(buffer, sizeof(buffer), "--");
+ app->eal_argv[n_args++] = strdup(buffer);
+
+ app->eal_argc = n_args;
+
+ APP_LOG(app, HIGH, "Initializing EAL ...");
+ if (app->log_level >= APP_LOG_LEVEL_LOW) {
+ int i;
+
+ fprintf(stdout, "[APP] EAL arguments: \"");
+ for (i = 1; i < app->eal_argc; i++)
+ fprintf(stdout, "%s ", app->eal_argv[i]);
+ fprintf(stdout, "\"\n");
+ }
+
+ status = rte_eal_init(app->eal_argc, app->eal_argv);
+ if (status < 0)
+ rte_panic("EAL init error\n");
+}
+
+static inline int
+app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = 0,
+ .proto_mask = 0, /* Disable */
+ .tcp_flags = 0,
+ .priority = 1, /* Lowest */
+ .queue = l1->ip_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+}
+
+static inline int
+app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = 0,
+ .proto_mask = 0, /* Disable */
+ .tcp_flags = 0,
+ .priority = 1, /* Lowest */
+ .queue = l1->ip_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+}
+
+static inline int
+app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_TCP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->tcp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+}
+
+static inline int
+app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_TCP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->tcp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+}
+
+static inline int
+app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_UDP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->udp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+}
+
+static inline int
+app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_UDP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->udp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+}
+
+static inline int
+app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_SCTP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->sctp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+}
+
+static inline int
+app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2)
+{
+ struct rte_eth_ntuple_filter filter = {
+ .flags = RTE_5TUPLE_FLAGS,
+ .dst_ip = rte_bswap32(l2->ip),
+ .dst_ip_mask = UINT32_MAX, /* Enable */
+ .src_ip = 0,
+ .src_ip_mask = 0, /* Disable */
+ .dst_port = 0,
+ .dst_port_mask = 0, /* Disable */
+ .src_port = 0,
+ .src_port_mask = 0, /* Disable */
+ .proto = IPPROTO_SCTP,
+ .proto_mask = UINT8_MAX, /* Enable */
+ .tcp_flags = 0,
+ .priority = 2, /* Higher priority than IP */
+ .queue = l1->sctp_local_q,
+ };
+
+ return rte_eth_dev_filter_ctrl(l1->pmd_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+}
+
+static int
+app_link_is_virtual(struct app_link_params *p)
+{
+ uint32_t pmd_id = p->pmd_id;
+ struct rte_eth_dev *dev = &rte_eth_devices[pmd_id];
+
+ if (dev->dev_type == RTE_ETH_DEV_VIRTUAL)
+ return 1;
+
+ return 0;
+}
+
+void
+app_link_up_internal(struct app_params *app, struct app_link_params *cp)
+{
+ uint32_t i;
+ int status;
+ struct rte_eth_link link;
+
+ if(app == NULL || cp == NULL)
+ printf("NULL Pointers");
+
+ if (app_link_is_virtual(cp)) {
+ cp->state = 1;
+ return;
+ }
+
+ ifm_update_linkstatus(cp->pmd_id, IFM_ETH_LINK_UP);
+
+ /* Mark link as UP */
+ cp->state = 1;
+
+}
+
+void
+app_link_down_internal(struct app_params *app, struct app_link_params *cp)
+{
+ uint32_t i;
+ int status;
+ struct rte_eth_link link;
+
+ if(app == NULL || cp == NULL)
+ printf("NULL Pointers");
+
+ if (app_link_is_virtual(cp)) {
+ cp->state = 0;
+ return;
+ }
+
+ ifm_update_linkstatus(cp->pmd_id, IFM_ETH_LINK_DOWN);
+
+ /* Mark link as DOWN */
+ cp->state = 0;
+
+}
+
+static void
+app_check_link(struct app_params *app)
+{
+ uint32_t all_links_up, i;
+
+ all_links_up = 1;
+
+ for (i = 0; i < app->n_links; i++) {
+ struct app_link_params *p = &app->link_params[i];
+ struct rte_eth_link link_params;
+
+ memset(&link_params, 0, sizeof(link_params));
+ rte_eth_link_get(p->pmd_id, &link_params);
+
+ APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s",
+ p->name,
+ p->pmd_id,
+ link_params.link_speed / 1000,
+ link_params.link_status ? "UP" : "DOWN");
+
+ if (link_params.link_status == ETH_LINK_DOWN)
+ all_links_up = 0;
+ }
+
+ if (all_links_up == 0)
+ rte_panic("Some links are DOWN\n");
+}
+
+static uint32_t
+is_any_swq_frag_or_ras(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_swq; i++) {
+ struct app_pktq_swq_params *p = &app->swq_params[i];
+
+ if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||
+ (p->ipv4_ras == 1) || (p->ipv6_ras == 1))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+app_init_link_frag_ras(struct app_params *app)
+{
+ uint32_t i;
+
+ if (is_any_swq_frag_or_ras(app)) {
+ for (i = 0; i < app->n_pktq_hwq_out; i++) {
+ struct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[i];
+
+ p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
+ }
+ }
+}
+
+static inline int
+app_get_cpu_socket_id(uint32_t pmd_id)
+{
+ int status = rte_eth_dev_socket_id(pmd_id);
+
+ return (status != SOCKET_ID_ANY) ? status : 0;
+}
+struct rte_eth_rxmode rx_mode = {
+ .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled. */
+ .hw_ip_checksum = 0, /**< IP checksum offload disabled. */
+ .hw_vlan_filter = 1, /**< VLAN filtering enabled. */
+ .hw_vlan_strip = 1, /**< VLAN strip enabled. */
+ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */
+ .hw_strip_crc = 0, /**< CRC stripping by hardware disabled. */
+};
+struct rte_fdir_conf fdir_conf = {
+ .mode = RTE_FDIR_MODE_NONE,
+ .pballoc = RTE_FDIR_PBALLOC_64K,
+ .status = RTE_FDIR_REPORT_STATUS,
+ .mask = {
+ .vlan_tci_mask = 0x0,
+ .ipv4_mask = {
+ .src_ip = 0xFFFFFFFF,
+ .dst_ip = 0xFFFFFFFF,
+ },
+ .ipv6_mask = {
+ .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF},
+ .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF},
+ },
+ .src_port_mask = 0xFFFF,
+ .dst_port_mask = 0xFFFF,
+ .mac_addr_byte_mask = 0xFF,
+ .tunnel_type_mask = 1,
+ .tunnel_id_mask = 0xFFFFFFFF,
+ },
+ .drop_queue = 127,
+};
+static void
+app_init_link(struct app_params *app)
+{
+ uint32_t i, size;
+
+ app_init_link_frag_ras(app);
+
+ /*
+ *Configuring port_config_t structure for interface manager initialization
+ */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(port_config_t));
+ port_config = rte_zmalloc(NULL, (app->n_links * size), RTE_CACHE_LINE_SIZE);
+ if (port_config == NULL)
+ rte_panic("port_config is NULL: Memory Allocation failure\n");
+
+ for (i = 0; i < app->n_links; i++) {
+ struct app_link_params *p_link = &app->link_params[i];
+ uint32_t link_id, n_hwq_in, n_hwq_out, j;
+ int status;
+
+ sscanf(p_link->name, "LINK%" PRIu32, &link_id);
+ n_hwq_in = app_link_get_n_rxq(app, p_link);
+ n_hwq_out = app_link_get_n_txq(app, p_link);
+ printf("\n\nn_hwq_in %d\n", n_hwq_in);
+ struct rte_eth_conf *My_local_conf = &p_link->conf;
+ if (enable_hwlb) {
+ My_local_conf->rxmode = rx_mode;
+ My_local_conf->fdir_conf = fdir_conf;
+ My_local_conf->rxmode.mq_mode = ETH_MQ_RX_RSS;
+ My_local_conf->rx_adv_conf.rss_conf.rss_key = NULL;
+ My_local_conf->rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
+ } else {/* disable-rss */
+ My_local_conf->rx_adv_conf.rss_conf.rss_hf = 0;
+ /* pkt-filter-mode is perfect */
+ My_local_conf->fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+ }
+
+ /* Set the hardware CRC stripping to avoid double stripping of FCS in VM */
+ p_link->conf.rxmode.hw_strip_crc = 1;
+
+ APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
+ "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
+ p_link->name,
+ p_link->pmd_id,
+ n_hwq_in,
+ n_hwq_out);
+
+ port_config[i].port_id = p_link->pmd_id;
+ port_config[i].nrx_queue = n_hwq_in;
+ port_config[i].ntx_queue = n_hwq_out;
+ port_config[i].state = 1;
+ port_config[i].promisc = p_link->promisc;
+ port_config[i].mempool.pool_size = app->mempool_params[0].pool_size;
+ port_config[i].mempool.buffer_size = app->mempool_params[0].buffer_size;
+ port_config[i].mempool.cache_size = app->mempool_params[0].cache_size;
+ port_config[i].mempool.cpu_socket_id = app->mempool_params[0].cpu_socket_id;
+ memcpy (&port_config[i].port_conf, &p_link->conf, sizeof(struct rte_eth_conf));
+ memcpy (&port_config[i].rx_conf, &app->hwq_in_params[0].conf, sizeof(struct rte_eth_rxconf));
+ memcpy (&port_config[i].tx_conf, &app->hwq_out_params[0].conf, sizeof(struct rte_eth_txconf));
+
+ if (app->header_csum_req) {
+ /* Enable TCP and UDP HW Checksum */
+ port_config[i].tx_conf.txq_flags &=
+ ~(ETH_TXQ_FLAGS_NOXSUMTCP|ETH_TXQ_FLAGS_NOXSUMUDP);
+ }
+
+ if (ifm_port_setup (p_link->pmd_id, &port_config[i])) {
+ rte_panic ("Port Setup Failed: %s - %"PRIu32"\n",
+ p_link->name, p_link->pmd_id);
+ }
+
+ /* LINK UP */
+ app_link_up_internal(app, p_link);
+ }
+
+ app_check_link(app);
+}
+
+static void
+app_init_swq(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_swq; i++) {
+ struct app_pktq_swq_params *p = &app->swq_params[i];
+ unsigned int flags = 0;
+
+ if (app_swq_get_readers(app, p) == 1)
+ flags |= RING_F_SC_DEQ;
+ if (app_swq_get_writers(app, p) == 1)
+ flags |= RING_F_SP_ENQ;
+
+ APP_LOG(app, HIGH, "Initializing %s...", p->name);
+ app->swq[i] = rte_ring_create(
+ p->name,
+ p->size,
+ p->cpu_socket_id,
+ flags);
+
+ if (app->swq[i] == NULL)
+ rte_panic("%s init error\n", p->name);
+ }
+}
+
+static void
+app_init_tm(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pktq_tm; i++) {
+ struct app_pktq_tm_params *p_tm = &app->tm_params[i];
+ struct app_link_params *p_link;
+ struct rte_eth_link link_eth_params;
+ struct rte_sched_port *sched;
+ uint32_t n_subports, subport_id;
+ int status;
+
+ p_link = app_get_link_for_tm(app, p_tm);
+ /* LINK */
+ rte_eth_link_get(p_link->pmd_id, &link_eth_params);
+
+ /* TM */
+ p_tm->sched_port_params.name = p_tm->name;
+ p_tm->sched_port_params.socket =
+ app_get_cpu_socket_id(p_link->pmd_id);
+ p_tm->sched_port_params.rate =
+ (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8;
+
+ APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name);
+ sched = rte_sched_port_config(&p_tm->sched_port_params);
+ if (sched == NULL)
+ rte_panic("%s init error\n", p_tm->name);
+ app->tm[i] = sched;
+
+ /* Subport */
+ n_subports = p_tm->sched_port_params.n_subports_per_port;
+ for (subport_id = 0; subport_id < n_subports; subport_id++) {
+ uint32_t n_pipes_per_subport, pipe_id;
+
+ status = rte_sched_subport_config(sched,
+ subport_id,
+ &p_tm->sched_subport_params[subport_id]);
+ if (status)
+ rte_panic("%s subport %" PRIu32
+ " init error (%" PRId32 ")\n",
+ p_tm->name, subport_id, status);
+
+ /* Pipe */
+ n_pipes_per_subport =
+ p_tm->sched_port_params.n_pipes_per_subport;
+ for (pipe_id = 0;
+ pipe_id < n_pipes_per_subport;
+ pipe_id++) {
+ int profile_id = p_tm->sched_pipe_to_profile[
+ subport_id * APP_MAX_SCHED_PIPES +
+ pipe_id];
+
+ if (profile_id == -1)
+ continue;
+
+ status = rte_sched_pipe_config(sched,
+ subport_id,
+ pipe_id,
+ profile_id);
+ if (status)
+ rte_panic("%s subport %" PRIu32
+ " pipe %" PRIu32
+ " (profile %" PRId32 ") "
+ "init error (% " PRId32 ")\n",
+ p_tm->name, subport_id, pipe_id,
+ profile_id, status);
+ }
+ }
+ }
+}
+
+static void
+app_init_msgq(struct app_params *app)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_msgq; i++) {
+ struct app_msgq_params *p = &app->msgq_params[i];
+
+ APP_LOG(app, HIGH, "Initializing %s ...", p->name);
+ app->msgq[i] = rte_ring_create(
+ p->name,
+ p->size,
+ p->cpu_socket_id,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+
+ if (app->msgq[i] == NULL)
+ rte_panic("%s init error\n", p->name);
+ }
+}
+
+static void app_pipeline_params_get(struct app_params *app,
+ struct app_pipeline_params *p_in,
+ struct pipeline_params *p_out)
+{
+ uint32_t i;
+ uint32_t mempool_id;
+
+ snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
+
+ p_out->socket_id = (int) p_in->socket_id;
+
+ p_out->log_level = app->log_level;
+
+ /* pktq_in */
+ p_out->n_ports_in = p_in->n_pktq_in;
+ for (i = 0; i < p_in->n_pktq_in; i++) {
+ struct app_pktq_in_params *in = &p_in->pktq_in[i];
+ struct pipeline_port_in_params *out = &p_out->port_in[i];
+
+ switch (in->type) {
+ case APP_PKTQ_IN_HWQ:
+ {
+ struct app_pktq_hwq_in_params *p_hwq_in =
+ &app->hwq_in_params[in->id];
+ struct app_link_params *p_link =
+ app_get_link_for_rxq(app, p_hwq_in);
+ uint32_t rxq_link_id, rxq_queue_id;
+
+ sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32,
+ &rxq_link_id,
+ &rxq_queue_id);
+
+ out->type = PIPELINE_PORT_IN_ETHDEV_READER;
+ out->params.ethdev.port_id = p_link->pmd_id;
+ out->params.ethdev.queue_id = rxq_queue_id;
+ out->burst_size = p_hwq_in->burst;
+ break;
+ }
+ case APP_PKTQ_IN_SWQ:
+ {
+ struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
+
+ if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) {
+ if (app_swq_get_readers(app, swq_params) == 1) {
+ out->type = PIPELINE_PORT_IN_RING_READER;
+ out->params.ring.ring = app->swq[in->id];
+ out->burst_size = app->swq_params[in->id].burst_read;
+ } else {
+ out->type = PIPELINE_PORT_IN_RING_MULTI_READER;
+ out->params.ring_multi.ring = app->swq[in->id];
+ out->burst_size = swq_params->burst_read;
+ }
+ } else {
+ if (swq_params->ipv4_frag == 1) {
+ struct rte_port_ring_reader_ipv4_frag_params *params =
+ &out->params.ring_ipv4_frag;
+
+ out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
+ params->ring = app->swq[in->id];
+ params->mtu = swq_params->mtu;
+ params->metadata_size = swq_params->metadata_size;
+ params->pool_direct =
+ app->mempool[swq_params->mempool_direct_id];
+ params->pool_indirect =
+ app->mempool[swq_params->mempool_indirect_id];
+ out->burst_size = swq_params->burst_read;
+ } else {
+ struct rte_port_ring_reader_ipv6_frag_params *params =
+ &out->params.ring_ipv6_frag;
+
+ out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
+ params->ring = app->swq[in->id];
+ params->mtu = swq_params->mtu;
+ params->metadata_size = swq_params->metadata_size;
+ params->pool_direct =
+ app->mempool[swq_params->mempool_direct_id];
+ params->pool_indirect =
+ app->mempool[swq_params->mempool_indirect_id];
+ out->burst_size = swq_params->burst_read;
+ }
+ }
+ break;
+ }
+ case APP_PKTQ_IN_TM:
+ out->type = PIPELINE_PORT_IN_SCHED_READER;
+ out->params.sched.sched = app->tm[in->id];
+ out->burst_size = app->tm_params[in->id].burst_read;
+ break;
+ case APP_PKTQ_IN_SOURCE:
+ mempool_id = app->source_params[in->id].mempool_id;
+ out->type = PIPELINE_PORT_IN_SOURCE;
+ out->params.source.mempool = app->mempool[mempool_id];
+ out->burst_size = app->source_params[in->id].burst;
+
+#ifdef RTE_NEXT_ABI
+ if (app->source_params[in->id].file_name
+ != NULL) {
+ out->params.source.file_name = strdup(
+ app->source_params[in->id].
+ file_name);
+ if (out->params.source.file_name == NULL) {
+ out->params.source.
+ n_bytes_per_pkt = 0;
+ break;
+ }
+ out->params.source.n_bytes_per_pkt =
+ app->source_params[in->id].
+ n_bytes_per_pkt;
+ }
+#endif
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* pktq_out */
+ p_out->n_ports_out = p_in->n_pktq_out;
+ for (i = 0; i < p_in->n_pktq_out; i++) {
+ struct app_pktq_out_params *in = &p_in->pktq_out[i];
+ struct pipeline_port_out_params *out = &p_out->port_out[i];
+
+ switch (in->type) {
+ case APP_PKTQ_OUT_HWQ:
+ {
+ struct app_pktq_hwq_out_params *p_hwq_out =
+ &app->hwq_out_params[in->id];
+ struct app_link_params *p_link =
+ app_get_link_for_txq(app, p_hwq_out);
+ uint32_t txq_link_id, txq_queue_id;
+
+ sscanf(p_hwq_out->name,
+ "TXQ%" SCNu32 ".%" SCNu32,
+ &txq_link_id,
+ &txq_queue_id);
+
+ if (p_hwq_out->dropless == 0) {
+ struct rte_port_ethdev_writer_params *params =
+ &out->params.ethdev;
+
+ out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER;
+ params->port_id = p_link->pmd_id;
+ params->queue_id = txq_queue_id;
+ params->tx_burst_sz =
+ app->hwq_out_params[in->id].burst;
+ } else {
+ struct rte_port_ethdev_writer_nodrop_params
+ *params = &out->params.ethdev_nodrop;
+
+ out->type =
+ PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP;
+ params->port_id = p_link->pmd_id;
+ params->queue_id = txq_queue_id;
+ params->tx_burst_sz = p_hwq_out->burst;
+ params->n_retries = p_hwq_out->n_retries;
+ }
+ break;
+ }
+ case APP_PKTQ_OUT_SWQ:
+ {
+ struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
+
+ if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) {
+ if (app_swq_get_writers(app, swq_params) == 1) {
+ if (app->swq_params[in->id].dropless == 0) {
+ struct rte_port_ring_writer_params *params =
+ &out->params.ring;
+
+ out->type = PIPELINE_PORT_OUT_RING_WRITER;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz =
+ app->swq_params[in->id].burst_write;
+ } else {
+ struct rte_port_ring_writer_nodrop_params
+ *params = &out->params.ring_nodrop;
+
+ out->type =
+ PIPELINE_PORT_OUT_RING_WRITER_NODROP;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz =
+ app->swq_params[in->id].burst_write;
+ params->n_retries =
+ app->swq_params[in->id].n_retries;
+ }
+ } else {
+ if (swq_params->dropless == 0) {
+ struct rte_port_ring_multi_writer_params *params =
+ &out->params.ring_multi;
+
+ out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz = swq_params->burst_write;
+ } else {
+ struct rte_port_ring_multi_writer_nodrop_params
+ *params = &out->params.ring_multi_nodrop;
+
+ out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz = swq_params->burst_write;
+ params->n_retries = swq_params->n_retries;
+ }
+ }
+ } else {
+ if (swq_params->ipv4_ras == 1) {
+ struct rte_port_ring_writer_ipv4_ras_params *params =
+ &out->params.ring_ipv4_ras;
+
+ out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz = swq_params->burst_write;
+ } else {
+ struct rte_port_ring_writer_ipv6_ras_params *params =
+ &out->params.ring_ipv6_ras;
+
+ out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
+ params->ring = app->swq[in->id];
+ params->tx_burst_sz = swq_params->burst_write;
+ }
+ }
+ break;
+ }
+ case APP_PKTQ_OUT_TM: {
+ struct rte_port_sched_writer_params *params =
+ &out->params.sched;
+
+ out->type = PIPELINE_PORT_OUT_SCHED_WRITER;
+ params->sched = app->tm[in->id];
+ params->tx_burst_sz =
+ app->tm_params[in->id].burst_write;
+ break;
+ }
+ case APP_PKTQ_OUT_SINK:
+ out->type = PIPELINE_PORT_OUT_SINK;
+ if (app->sink_params[in->id].file_name != NULL) {
+ out->params.sink.file_name = strdup(
+ app->sink_params[in->id].
+ file_name);
+ if (out->params.sink.file_name == NULL) {
+ out->params.sink.max_n_pkts = 0;
+ break;
+ }
+ out->params.sink.max_n_pkts =
+ app->sink_params[in->id].
+ n_pkts_to_dump;
+ } else {
+ out->params.sink.file_name = NULL;
+ out->params.sink.max_n_pkts = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* msgq */
+ p_out->n_msgq = p_in->n_msgq_in;
+
+ for (i = 0; i < p_in->n_msgq_in; i++)
+ p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]];
+
+ for (i = 0; i < p_in->n_msgq_out; i++)
+ p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]];
+
+ /* args */
+ p_out->n_args = p_in->n_args;
+ for (i = 0; i < p_in->n_args; i++) {
+ p_out->args_name[i] = p_in->args_name[i];
+ p_out->args_value[i] = p_in->args_value[i];
+ }
+}
+
+static void
+app_init_pipelines(struct app_params *app)
+{
+ uint32_t p_id;
+
+ for (p_id = 0; p_id < app->n_pipelines; p_id++) {
+ struct app_pipeline_params *params =
+ &app->pipeline_params[p_id];
+ struct app_pipeline_data *data = &app->pipeline_data[p_id];
+ struct pipeline_type *ptype;
+ struct pipeline_params pp;
+
+ APP_LOG(app, HIGH, "Initializing %s ...", params->name);
+
+ ptype = app_pipeline_type_find(app, params->type);
+ if (ptype == NULL)
+ rte_panic("Init error: Unknown pipeline type \"%s\"\n",
+ params->type);
+
+ app_pipeline_params_get(app, params, &pp);
+
+ /* Back-end */
+ data->be = NULL;
+ if (ptype->be_ops->f_init) {
+ data->be = ptype->be_ops->f_init(&pp, (void *) app);
+
+ if (data->be == NULL)
+ rte_panic("Pipeline instance \"%s\" back-end "
+ "init error\n", params->name);
+ }
+
+ /* Front-end */
+ data->fe = NULL;
+ if (ptype->fe_ops->f_init) {
+ data->fe = ptype->fe_ops->f_init(&pp, (void *) app);
+
+ if (data->fe == NULL)
+ rte_panic("Pipeline instance \"%s\" front-end "
+ "init error\n", params->name);
+ }
+
+ data->ptype = ptype;
+
+ data->timer_period = (rte_get_tsc_hz() *
+ params->timer_period) / 100;
+ }
+}
+
+static void
+app_init_threads(struct app_params *app)
+{
+ uint64_t time = rte_get_tsc_cycles();
+ uint32_t p_id;
+
+ for (p_id = 0; p_id < app->n_pipelines; p_id++) {
+ struct app_pipeline_params *params =
+ &app->pipeline_params[p_id];
+ struct app_pipeline_data *data = &app->pipeline_data[p_id];
+ struct pipeline_type *ptype;
+ struct app_thread_data *t;
+ struct app_thread_pipeline_data *p;
+ int lcore_id;
+
+ lcore_id = cpu_core_map_get_lcore_id(app->core_map,
+ params->socket_id,
+ params->core_id,
+ params->hyper_th_id);
+
+ if (lcore_id < 0)
+ rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n",
+ params->socket_id,
+ params->core_id,
+ (params->hyper_th_id) ? "h" : "");
+
+ t = &app->thread_data[lcore_id];
+
+ t->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000;
+ t->thread_req_deadline = time + t->timer_period;
+
+ t->headroom_cycles = 0;
+ t->headroom_time = rte_get_tsc_cycles();
+ t->headroom_ratio = 0.0;
+
+ t->msgq_in = app_thread_msgq_in_get(app,
+ params->socket_id,
+ params->core_id,
+ params->hyper_th_id);
+ if (t->msgq_in == NULL)
+ rte_panic("Init error: Cannot find MSGQ_IN for thread %" PRId32,
+ lcore_id);
+
+ t->msgq_out = app_thread_msgq_out_get(app,
+ params->socket_id,
+ params->core_id,
+ params->hyper_th_id);
+ if (t->msgq_out == NULL)
+ rte_panic("Init error: Cannot find MSGQ_OUT for thread %" PRId32,
+ lcore_id);
+
+ ptype = app_pipeline_type_find(app, params->type);
+ if (ptype == NULL)
+ rte_panic("Init error: Unknown pipeline "
+ "type \"%s\"\n", params->type);
+
+ p = (ptype->be_ops->f_run == NULL) ?
+ &t->regular[t->n_regular] :
+ &t->custom[t->n_custom];
+
+ p->pipeline_id = p_id;
+ p->be = data->be;
+ p->f_run = ptype->be_ops->f_run;
+ p->f_timer = ptype->be_ops->f_timer;
+ p->timer_period = data->timer_period;
+ p->deadline = time + data->timer_period;
+
+ data->enabled = 1;
+
+ if (ptype->be_ops->f_run == NULL)
+ t->n_regular++;
+ else
+ t->n_custom++;
+ }
+}
+
+int app_init(struct app_params *app)
+{
+ app_init_core_map(app);
+ app_init_core_mask(app);
+
+ app_init_eal(app);
+
+ /* IFM init */
+ ifm_init();
+ timer_lcore = rte_lcore_id();
+
+ app_init_link(app);
+ app_init_swq(app);
+ app_init_tm(app);
+ app_init_msgq(app);
+
+ app_pipeline_common_cmd_push(app);
+ app_pipeline_thread_cmd_push(app);
+ app_pipeline_type_register(app, &pipeline_master);
+ app_pipeline_type_register(app, &pipeline_arpicmp);
+
+ app_pipeline_type_register(app, &pipeline_loadb);
+ app_pipeline_type_register(app, &pipeline_acl);
+ app_pipeline_type_register(app, &pipeline_txrx);
+
+ app_init_pipelines(app);
+ app_init_threads(app);
+
+ l3fwd_init();
+ create_arp_table();
+ create_nd_table();
+ populate_lpm_routes();
+ print_interface_details();
+
+ return 0;
+}
+
+static int
+app_pipeline_type_cmd_push(struct app_params *app,
+ struct pipeline_type *ptype)
+{
+ cmdline_parse_ctx_t *cmds;
+ uint32_t n_cmds, i;
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (ptype == NULL))
+ return -EINVAL;
+
+ n_cmds = pipeline_type_cmds_count(ptype);
+ if (n_cmds == 0)
+ return 0;
+
+ cmds = ptype->fe_ops->cmds;
+
+ /* Check for available slots in the application commands array */
+ if (n_cmds > APP_MAX_CMDS - app->n_cmds)
+ return -ENOMEM;
+
+ /* Push pipeline commands into the application */
+ memcpy(&app->cmds[app->n_cmds],
+ cmds,
+ n_cmds * sizeof(cmdline_parse_ctx_t));
+
+ for (i = 0; i < n_cmds; i++)
+ app->cmds[app->n_cmds + i]->data = app;
+
+ app->n_cmds += n_cmds;
+ app->cmds[app->n_cmds] = NULL;
+
+ return 0;
+}
+
+int
+app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype)
+{
+ uint32_t n_cmds, i;
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (ptype == NULL) ||
+ (ptype->name == NULL) ||
+ (strlen(ptype->name) == 0) ||
+ (ptype->be_ops->f_init == NULL) ||
+ (ptype->be_ops->f_timer == NULL))
+ return -EINVAL;
+
+ /* Check for duplicate entry */
+ for (i = 0; i < app->n_pipeline_types; i++)
+ if (strcmp(app->pipeline_type[i].name, ptype->name) == 0)
+ return -EEXIST;
+
+ /* Check for resource availability */
+ n_cmds = pipeline_type_cmds_count(ptype);
+ if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) ||
+ (n_cmds > APP_MAX_CMDS - app->n_cmds))
+ return -ENOMEM;
+
+ /* Copy pipeline type */
+ memcpy(&app->pipeline_type[app->n_pipeline_types++],
+ ptype,
+ sizeof(struct pipeline_type));
+
+ /* Copy CLI commands */
+ if (n_cmds)
+ app_pipeline_type_cmd_push(app, ptype);
+
+ return 0;
+}
+
+struct
+pipeline_type *app_pipeline_type_find(struct app_params *app, char *name)
+{
+ uint32_t i;
+
+ for (i = 0; i < app->n_pipeline_types; i++)
+ if (strcmp(app->pipeline_type[i].name, name) == 0)
+ return &app->pipeline_type[i];
+
+ return NULL;
+}
diff --git a/VNFs/vACL/main.c b/VNFs/vACL/main.c
new file mode 100644
index 00000000..9ebf6fc3
--- /dev/null
+++ b/VNFs/vACL/main.c
@@ -0,0 +1,50 @@
+/*
+// 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 "app.h"
+
+static struct app_params app;
+
+int
+main(int argc, char **argv)
+{
+ rte_openlog_stream(stderr);
+
+ /* Config */
+ app_config_init(&app);
+
+ app_config_args(&app, argc, argv);
+
+ app_config_preproc(&app);
+
+ app_config_parse(&app, app.parser_file);
+
+ app_config_check(&app);
+
+ /* Timer subsystem init*/
+ rte_timer_subsystem_init();
+
+ /* Init */
+ app_init(&app);
+
+ /* Run-time */
+ rte_eal_mp_remote_launch(
+ app_thread,
+ (void *) &app,
+ CALL_MASTER);
+
+ return 0;
+}
diff --git a/VNFs/vACL/pipeline/pipeline_acl.c b/VNFs/vACL/pipeline/pipeline_acl.c
new file mode 100644
index 00000000..1a4ed4f5
--- /dev/null
+++ b/VNFs/vACL/pipeline/pipeline_acl.c
@@ -0,0 +1,4178 @@
+/*
+// 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 FE Implementation.
+ *
+ * Implementation of the Pipeline ACL Front End (FE).
+ * Runs on the Master pipeline, responsible for CLI commands.
+ *
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_malloc.h>
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+#include <rte_table_acl.h>
+
+#include "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_acl.h"
+#include "pipeline_acl_be.h"
+#include "rte_cnxn_tracking.h"
+
+/**
+ * A structure defining the ACL rule for the TAILQ Tables.
+ */
+struct app_pipeline_acl_rule {
+ struct pipeline_acl_key key;
+ int32_t priority;
+ uint32_t port_id;
+ uint32_t action_id;
+ uint32_t command;
+ void *entry_ptr;
+
+ TAILQ_ENTRY(app_pipeline_acl_rule) node;
+};
+
+/**
+ * A structure defining the ACL pipeline front end data.
+ */
+struct app_pipeline_acl {
+ /* parameters */
+ uint32_t n_ports_in;
+ uint32_t n_ports_out;
+
+};
+
+/*
+ * Define a structure to calculate performance measurements for ACL.
+ * ACL continually updates counters for total number of packets
+ * processed, and total number of bytes processed. Each ACL backend thread
+ * i.e. the packet processing instances updates their own copy of these counters
+ * An optional, 1 second periodic timer fires on the master core, which combines
+ * those numbers to perform byte and packet per second calculations, without
+ * burdening the packet processors.
+ */
+#define RTE_ACL_PERF_MSR_BUFF_SIZE 8 /* must be power of 2 */
+#define RTE_ACL_PERF_MSR_BUFF_SIZE_MASK (RTE_ACL_PERF_MSR_BUFF_SIZE - 1)
+
+/**
+ * A structure defining the ACL performance measurements.
+ */
+struct rte_acl_performance_measures_t {
+ /* two circular buffers */
+ uint64_t total_packets[RTE_ACL_PERF_MSR_BUFF_SIZE];
+ uint64_t total_bytes[RTE_ACL_PERF_MSR_BUFF_SIZE];
+ uint32_t bytes_last_second;
+ uint32_t ave_bytes_per_second;
+ uint32_t pkts_last_second;
+ uint32_t ave_pkts_per_second;
+ uint64_t total_entries;
+ /* times data has been (over-)written into buffers */
+ uint8_t current_index; /* for circular buffers */
+};
+
+struct rte_acl_performance_measures_t rte_acl_performance_measures;
+
+/*
+ * Active and Standby Tables
+ * Active and standby tables exist to allow modifying ACL rules and
+ * actions and having no impact on the packet processing running on
+ * the multiple ACL threads/pipelines. The packet processing does a
+ * lookup on the active tables. Each ACL thread/pipeline runs on
+ * a separate core (i.e. 2,3,4, etc).
+ *
+ * All CLI actions run on the ACL Front End (FE) code on Core 0.
+ * All changes, adding/delete rules and action occurs on the standby tables.
+ * In activate the changes in the standby table, the CLI command is entered:
+ * p acl applyruleset
+ *
+ * The standby tables become active. The active table becomes the standby.
+ * The new standby table gets updated with the changes that were done.
+ *
+ * Table descriptions:
+ * ACL Rule Tables TAILQ - 2 global tables active/standby per ipv4,ipv6
+ * The TAILQ tables are required for the LS CLI command and in order
+ * to do a lookup using a rule when adding or deleting a rule.
+ * The ACL TRIE tables in DPDK do not allow this type of listing or lookup.
+ *
+ * ACL Rule Tables TRIE - 2 global tables active/standby per ipv4, ipv6
+ * The TRIE tables are the tables used during packet processing.
+ * A bulk lookup can be performed by passing in a burst of packets.
+ * Unfortunately, the current implementation of the TRIE tables does
+ * not allow lookup using a rule. Hence the need for the TAILQ tables.
+ *
+ * ACL Action Tables ARRAY - 2 global tables active/standby
+ * The action tables stores the ACL actions.
+ * Every rule has an action id which defines what action to take
+ * when a packet matching that rule is received.
+ * Actions: accept, drop, fwd, count, nat, dscp, conntrack
+ *
+ * Command Table TAILQ - 1 table
+ * After the active and standby tables are swithover, the new standby
+ * table needs to be updated with all the changes that were done.
+ * This table stores all the add and delete commands and updates
+ * the new standby table when the applyruleset command executes.
+ *
+ * The active and standby tables can be displayed individually:
+ * p acl ls 0 <== active ACL rules
+ * p acl ls 1 <== standby ACL rules
+ * p action ls 0 <== active ACL actions
+ * p action ls 1 <== standby ACL actions
+ */
+
+/* Only create global ACL tables once */
+int acl_rule_table_created;
+
+/*
+ * ACL Rule Tables TAILQ - see description above
+ * Two tables/counters are required for active and standby.
+ * The A and B tables/counters are the actual instances.
+ * The pointers are set to point to these tables/counters.
+ * The pointers are updated during the switchover for the applyruleset.
+ */
+
+/* Definition of the the TAILQ table */
+TAILQ_HEAD(app_pipeline_acl_rule_type, app_pipeline_acl_rule);
+/* Instances of tables and counters */
+struct app_pipeline_acl_rule_type acl_tailq_rules_ipv4a;
+struct app_pipeline_acl_rule_type acl_tailq_rules_ipv4b;
+struct app_pipeline_acl_rule_type acl_tailq_rules_ipv6a;
+struct app_pipeline_acl_rule_type acl_tailq_rules_ipv6b;
+uint32_t acl_n_tailq_rules_ipv4a;
+uint32_t acl_n_tailq_rules_ipv6a;
+uint32_t acl_n_tailq_rules_ipv4b;
+uint32_t acl_n_tailq_rules_ipv6b;
+/* Pointers to tables and counters for switchover in applyruleset */
+struct app_pipeline_acl_rule_type *acl_tailq_rules_ipv4_active;
+struct app_pipeline_acl_rule_type *acl_tailq_rules_ipv4_standby;
+struct app_pipeline_acl_rule_type *acl_tailq_rules_ipv6_active;
+struct app_pipeline_acl_rule_type *acl_tailq_rules_ipv6_standby;
+struct app_pipeline_acl_rule_type *acl_tailq_rules_temp_ptr;
+uint32_t *acl_n_tailq_rules_ipv4_active;
+uint32_t *acl_n_tailq_rules_ipv4_standby;
+uint32_t *acl_n_tailq_rules_ipv6_active;
+uint32_t *acl_n_tailq_rules_ipv6_standby;
+
+/* ACL commands to update new standby tables after switchover */
+TAILQ_HEAD(, app_pipeline_acl_rule) acl_commands;
+
+/* ACL IPV4 and IPV6 enable flags for debugging (Default both on) */
+int acl_ipv4_enabled = 1;
+int acl_ipv6_enabled = 1;
+
+/* Number of ACL Rules, default 4 * 1024 */
+uint32_t acl_n_rules = 4 * 1024;
+/* ACL Rule Table TRIE - 2 (Active, Standby) Global table per ipv4, ipv6 */
+void *acl_rule_table_ipv4_active;
+void *acl_rule_table_ipv4_standby;
+void *acl_rule_table_ipv6_active;
+void *acl_rule_table_ipv6_standby;
+
+/**
+ * Reset running averages for performance measurements.
+ *
+ */
+static void rte_acl_reset_running_averages(void)
+{
+ memset(&rte_acl_performance_measures, 0,
+ sizeof(rte_acl_performance_measures));
+};
+
+/**
+ * Compute performance calculations on master to reduce computing on
+ * packet processor.
+ *
+ * @param total_bytes
+ * Total bytes processed during this interval.
+ * @param total_packets
+ * Total packets processed during this interval.
+ *
+ */
+static void rte_acl_update_performance_measures(uint64_t total_bytes,
+ uint64_t total_packets)
+{
+ /* make readable */
+ struct rte_acl_performance_measures_t *pm =
+ &rte_acl_performance_measures;
+
+ if (unlikely(pm->total_entries == 0 && total_packets == 0))
+/* the timer is running, but no traffic started yet, so do nothing */
+ return;
+
+ if (likely(pm->total_entries > 0)) {
+ uint8_t oldest_index;
+ uint8_t divisor;
+
+ pm->bytes_last_second =
+ total_bytes - pm->total_bytes[pm->current_index];
+ pm->pkts_last_second =
+ total_packets - pm->total_packets[pm->current_index];
+
+ /* if total_entries zero, current_index must remain as zero */
+ pm->current_index =
+ (pm->current_index + 1) & RTE_ACL_PERF_MSR_BUFF_SIZE_MASK;
+
+ if (unlikely(pm->total_entries <= RTE_ACL_PERF_MSR_BUFF_SIZE)) {
+ /* oldest value is at element 0 */
+ oldest_index = 0;
+ divisor = pm->total_entries;
+ /* note, prior to incrementing total_entries */
+ } else {
+ /* oldest value is at element about to be overwritten */
+ oldest_index = pm->current_index;
+ divisor = RTE_ACL_PERF_MSR_BUFF_SIZE;
+ }
+
+ pm->ave_bytes_per_second =
+ (total_bytes - pm->total_bytes[oldest_index]) / divisor;
+ pm->ave_pkts_per_second =
+ (total_packets - pm->total_packets[oldest_index]) / divisor;
+ }
+
+ pm->total_bytes[pm->current_index] = total_bytes;
+ pm->total_packets[pm->current_index] = total_packets;
+ pm->total_entries++;
+}
+
+/**
+ * Combine data from all acl+connection tracking instances.
+ * Calculate various statistics. Dump to console.
+ *
+ */
+static void rte_acl_sum_and_print_counters(void)
+{
+ int i;
+ struct rte_ACL_counter_block acl_counter_sums;
+ struct rte_CT_counter_block ct_counter_sums;
+ /* For ct instance with this fw instance */
+ struct rte_CT_counter_block *ct_counters;
+
+ memset(&acl_counter_sums, 0, sizeof(acl_counter_sums));
+ memset(&ct_counter_sums, 0, sizeof(ct_counter_sums));
+
+ for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) {
+ struct rte_ACL_counter_block *acl_ctrs =
+ &rte_acl_counter_table[i];
+ ct_counters = rte_acl_counter_table[i].ct_counters;
+
+ printf
+ ("{\"ACL counters\" : {\"id\" : \"%s\", \"packets_processed\" : %"
+ PRIu64 ", \"bytes_processed\" : %" PRIu64
+ ", \"ct_packets_forwarded\" : %" PRIu64
+ ", \"ct_packets_dropped\" : %" PRIu64 "}}\n",
+ acl_ctrs->name, acl_ctrs->tpkts_processed,
+ acl_ctrs->bytes_processed, ct_counters->pkts_forwarded,
+ ct_counters->pkts_drop);
+
+ /* sum ACL counters */
+ acl_counter_sums.tpkts_processed += acl_ctrs->tpkts_processed;
+ acl_counter_sums.bytes_processed += acl_ctrs->bytes_processed;
+ acl_counter_sums.pkts_drop += acl_ctrs->pkts_drop;
+ acl_counter_sums.pkts_received += acl_ctrs->pkts_received;
+ acl_counter_sums.pkts_drop_ttl += acl_ctrs->pkts_drop_ttl;
+ acl_counter_sums.pkts_drop_bad_size +=
+ acl_ctrs->pkts_drop_bad_size;
+ acl_counter_sums.pkts_drop_fragmented +=
+ acl_ctrs->pkts_drop_fragmented;
+ acl_counter_sums.pkts_drop_without_arp_entry +=
+ acl_ctrs->pkts_drop_without_arp_entry;
+ acl_counter_sums.sum_latencies += acl_ctrs->sum_latencies;
+ acl_counter_sums.count_latencies += acl_ctrs->count_latencies;
+
+ /* sum cnxn tracking counters */
+ ct_counter_sums.current_active_sessions +=
+ ct_counters->current_active_sessions;
+ ct_counter_sums.sessions_activated +=
+ ct_counters->sessions_activated;
+ ct_counter_sums.sessions_closed += ct_counters->sessions_closed;
+ ct_counter_sums.sessions_timedout +=
+ ct_counters->sessions_timedout;
+ ct_counter_sums.pkts_forwarded += ct_counters->pkts_forwarded;
+ ct_counter_sums.pkts_drop += ct_counters->pkts_drop;
+ ct_counter_sums.pkts_drop_invalid_conn +=
+ ct_counters->pkts_drop_invalid_conn;
+ ct_counter_sums.pkts_drop_invalid_state +=
+ ct_counters->pkts_drop_invalid_state;
+ ct_counter_sums.pkts_drop_invalid_rst +=
+ ct_counters->pkts_drop_invalid_rst;
+ ct_counter_sums.pkts_drop_outof_window +=
+ ct_counters->pkts_drop_outof_window;
+ }
+
+ rte_acl_update_performance_measures(acl_counter_sums.bytes_processed,
+ acl_counter_sums.tpkts_processed);
+ uint64_t average_latency =
+ acl_counter_sums.count_latencies ==
+ 0 ? 0 : acl_counter_sums.sum_latencies /
+ acl_counter_sums.count_latencies;
+
+ printf("{\"ACL sum counters\" : {"
+ "\"packets_last_sec\" : %" PRIu32
+ ", \"average_packets_per_sec\" : %" PRIu32
+ ", \"bytes_last_sec\" : %" PRIu32
+ ", \"average_bytes_per_sec\" : %" PRIu32
+ ", \"packets_processed\" : %" PRIu64 ", \"bytes_processed\" : %"
+ PRIu64 ", \"average_latency_in_clocks\" : %" PRIu64
+ ", \"ct_packets_forwarded\" : %" PRIu64
+ ", \"ct_packets_dropped\" : %" PRIu64 ", \"drops\" : {"
+ "\"TTL_zero\" : %" PRIu64 ", \"bad_size\" : %" PRIu64
+ ", \"fragmented_packet\" : %" PRIu64 ", \"no_arp_entry\" : %"
+ PRIu64 "}, \"ct_sessions\" : {" "\"active\" : %" PRIu64
+ ", \"open\" : %" PRIu64 ", \"closed\" : %" PRIu64
+ ", \"timeout\" : %" PRIu64 "}, \"ct_drops\" : {"
+ "\"out_of_window\" : %" PRIu64 ", \"invalid_conn\" : %" PRIu64
+ ", \"invalid_state_transition\" : %" PRIu64 " \"RST\" : %" PRIu64
+ "}}}\n", rte_acl_performance_measures.pkts_last_second,
+ rte_acl_performance_measures.ave_pkts_per_second,
+ rte_acl_performance_measures.bytes_last_second,
+ rte_acl_performance_measures.ave_bytes_per_second,
+ acl_counter_sums.tpkts_processed,
+ acl_counter_sums.bytes_processed, average_latency,
+ ct_counter_sums.pkts_forwarded, ct_counter_sums.pkts_drop,
+ acl_counter_sums.pkts_drop_ttl,
+ acl_counter_sums.pkts_drop_bad_size,
+ acl_counter_sums.pkts_drop_fragmented,
+ acl_counter_sums.pkts_drop_without_arp_entry,
+ ct_counter_sums.current_active_sessions,
+ ct_counter_sums.sessions_activated,
+ ct_counter_sums.sessions_closed,
+ ct_counter_sums.sessions_timedout,
+ ct_counter_sums.pkts_drop_outof_window,
+ ct_counter_sums.pkts_drop_invalid_conn,
+ ct_counter_sums.pkts_drop_invalid_state,
+ ct_counter_sums.pkts_drop_invalid_rst);
+
+}
+
+/**
+ * Callback routine for 1 second, periodic timer.
+ *
+ * @param rt
+ * A pointer to the rte_timer.
+ * @param arg
+ * A pointer to application specific arguments (not used).
+ *
+ * @return
+ * 0 on success and port_id is filled, negative on error.
+ */
+void rte_dump_acl_counters_from_master(struct rte_timer *rt, void *arg)
+{
+ rte_acl_sum_and_print_counters();
+}
+
+int rte_acl_hertz_computed; /* only launch timer once */
+uint64_t rte_acl_ticks_in_one_second;
+/* TODO: is processor hertz computed/stored elsewhere? */
+struct rte_timer rte_acl_one_second_timer = RTE_TIMER_INITIALIZER;
+
+/**
+ * Print IPv4 Rule.
+ *
+ * @param rule
+ * A pointer to the rule.
+ *
+ */
+static void print_acl_ipv4_rule(struct app_pipeline_acl_rule *rule)
+{
+ printf("Prio = %" PRId32 " (SA = %" PRIu32 ".%" PRIu32
+ ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", DA = %"
+ PRIu32 ".%" PRIu32
+ ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", SP = %"
+ PRIu32 "-%" PRIu32 ", DP = %"
+ PRIu32 "-%" PRIu32 ", Proto = %"
+ PRIu32 " / 0x%" PRIx32 ") => Action ID = %"
+ PRIu32 " (entry ptr = %p)\n",
+ rule->priority,
+ (rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF,
+ (rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF,
+ (rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF,
+ rule->key.key.ipv4_5tuple.src_ip & 0xFF,
+ rule->key.key.ipv4_5tuple.src_ip_mask,
+ (rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF,
+ (rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF,
+ (rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF,
+ rule->key.key.ipv4_5tuple.dst_ip & 0xFF,
+ rule->key.key.ipv4_5tuple.dst_ip_mask,
+ rule->key.key.ipv4_5tuple.src_port_from,
+ rule->key.key.ipv4_5tuple.src_port_to,
+ rule->key.key.ipv4_5tuple.dst_port_from,
+ rule->key.key.ipv4_5tuple.dst_port_to,
+ rule->key.key.ipv4_5tuple.proto,
+ rule->key.key.ipv4_5tuple.proto_mask,
+ rule->action_id, rule->entry_ptr);
+}
+
+/**
+ * Print IPv6 Rule.
+ *
+ * @param rule
+ * A pointer to the rule.
+ *
+ */
+static void print_acl_ipv6_rule(struct app_pipeline_acl_rule *rule)
+{
+ printf("Prio = %" PRId32 " (SA = %02" PRIx8 "%02" PRIx8
+ ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8
+ ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8
+ ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8
+ ":%02" PRIx8 "%02" PRIx8 "/" "%" PRIu32 ", DA = %02"
+ PRIx8 "%02" PRIx8 ":%02" PRIx8
+ "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8
+ "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8
+ "%02" PRIx8 ":%02" PRIx8 "%02" PRIx8 ":%02" PRIx8
+ "%02" PRIx8 "/" "%" PRIu32
+ ", " "SP = %" PRIu32 "-%" PRIu32 ", DP = %"
+ PRIu32 "-%" PRIu32 ", Proto = %"
+ PRIu32 " / 0x%" PRIx32 ") => Action ID = %"
+ PRIu32 " (entry ptr = %p)\n", rule->priority,
+ (rule->key.key.ipv6_5tuple.src_ip[0]),
+ (rule->key.key.ipv6_5tuple.src_ip[1]),
+ (rule->key.key.ipv6_5tuple.src_ip[2]),
+ (rule->key.key.ipv6_5tuple.src_ip[3]),
+ (rule->key.key.ipv6_5tuple.src_ip[4]),
+ (rule->key.key.ipv6_5tuple.src_ip[5]),
+ (rule->key.key.ipv6_5tuple.src_ip[6]),
+ (rule->key.key.ipv6_5tuple.src_ip[7]),
+ (rule->key.key.ipv6_5tuple.src_ip[8]),
+ (rule->key.key.ipv6_5tuple.src_ip[9]),
+ (rule->key.key.ipv6_5tuple.src_ip[10]),
+ (rule->key.key.ipv6_5tuple.src_ip[11]),
+ (rule->key.key.ipv6_5tuple.src_ip[12]),
+ (rule->key.key.ipv6_5tuple.src_ip[13]),
+ (rule->key.key.ipv6_5tuple.src_ip[14]),
+ (rule->key.key.ipv6_5tuple.src_ip[15]),
+ rule->key.key.ipv6_5tuple.src_ip_mask,
+ (rule->key.key.ipv6_5tuple.dst_ip[0]),
+ (rule->key.key.ipv6_5tuple.dst_ip[1]),
+ (rule->key.key.ipv6_5tuple.dst_ip[2]),
+ (rule->key.key.ipv6_5tuple.dst_ip[3]),
+ (rule->key.key.ipv6_5tuple.dst_ip[4]),
+ (rule->key.key.ipv6_5tuple.dst_ip[5]),
+ (rule->key.key.ipv6_5tuple.dst_ip[6]),
+ (rule->key.key.ipv6_5tuple.dst_ip[7]),
+ (rule->key.key.ipv6_5tuple.dst_ip[8]),
+ (rule->key.key.ipv6_5tuple.dst_ip[9]),
+ (rule->key.key.ipv6_5tuple.dst_ip[10]),
+ (rule->key.key.ipv6_5tuple.dst_ip[11]),
+ (rule->key.key.ipv6_5tuple.dst_ip[12]),
+ (rule->key.key.ipv6_5tuple.dst_ip[13]),
+ (rule->key.key.ipv6_5tuple.dst_ip[14]),
+ (rule->key.key.ipv6_5tuple.dst_ip[15]),
+ rule->key.key.ipv6_5tuple.dst_ip_mask,
+ rule->key.key.ipv6_5tuple.src_port_from,
+ rule->key.key.ipv6_5tuple.src_port_to,
+ rule->key.key.ipv6_5tuple.dst_port_from,
+ rule->key.key.ipv6_5tuple.dst_port_to,
+ rule->key.key.ipv6_5tuple.proto,
+ rule->key.key.ipv6_5tuple.proto_mask, rule->action_id,
+ rule->entry_ptr);
+}
+
+/**
+ * Find an ACL rule.
+ * This function is used by the add and delete rule functions.
+ * Since all updates are done on the standby tables,
+ * only search the standby tables.
+ * Both IPv4 and IPv6 rules can be searched
+ *
+ * @param key
+ * A pointer to the rule to be found.
+ *
+ * @return
+ * - Pointer to the rule found.
+ * - NULL if no rule found.
+ */
+static struct app_pipeline_acl_rule *app_pipeline_acl_rule_find(struct
+ pipeline_acl_key
+ *key)
+{
+ /*
+ * This function is used by the add and delete rule functions.
+ * Since all updates are done on the standby tables,
+ * only search the standby tables.
+ */
+
+ struct app_pipeline_acl_rule *r;
+
+ if (key->type == PIPELINE_ACL_IPV4_5TUPLE) {
+ TAILQ_FOREACH(r, acl_tailq_rules_ipv4_standby, node)
+ if (memcmp(key,
+ &r->key, sizeof(struct pipeline_acl_key)) == 0)
+ return r;
+ } else { /* IPV6 */
+ TAILQ_FOREACH(r, acl_tailq_rules_ipv6_standby, node)
+ if (memcmp(key,
+ &r->key, sizeof(struct pipeline_acl_key)) == 0)
+ return r;
+ }
+
+ return NULL;
+}
+
+/**
+ * Display ACL Rules to the console.
+ * Rules from Active and standby tables can be dispayed.
+ * Both IPv4 and IPv6 will be displayed.
+ *
+ * @param app
+ * A pointer to application specific data.
+ * @param active_standby_table
+ * Specifies which table to display:
+ * - active_rule_table (0)
+ * - standby_rule_table (1)
+ *
+ */
+static void
+app_pipeline_acl_ls(struct app_params *app, uint32_t active_standby_table)
+{
+ struct app_pipeline_acl_rule *rule;
+ uint32_t n_rules;
+ int priority;
+
+ if (active_standby_table == active_rule_table) {
+ n_rules = *acl_n_tailq_rules_ipv4_active;
+ if (n_rules > 0)
+ printf("ACL Active Table IPV4 Rules\n");
+ for (priority = 0; n_rules; priority++)
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv4_active, node)
+ if (rule->priority == priority) {
+ print_acl_ipv4_rule(rule);
+ n_rules--;
+ }
+
+ n_rules = *acl_n_tailq_rules_ipv6_active;
+ if (n_rules > 0)
+ printf("ACL Active Table IPV6 Rules\n");
+ for (priority = 0; n_rules; priority++)
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv6_active, node)
+ if (rule->priority == priority) {
+ print_acl_ipv6_rule(rule);
+ n_rules--;
+ }
+ } else {
+ n_rules = *acl_n_tailq_rules_ipv4_standby;
+ if (n_rules > 0)
+ printf("ACL Standby Table IPV4 Rules\n");
+ for (priority = 0; n_rules; priority++)
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv4_standby, node)
+ if (rule->priority == priority) {
+ print_acl_ipv4_rule(rule);
+ n_rules--;
+ }
+
+ n_rules = *acl_n_tailq_rules_ipv6_standby;
+ if (n_rules > 0)
+ printf("ACL Standby Table IPV6a Rules\n");
+ for (priority = 0; n_rules; priority++)
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv6_standby, node)
+ if (rule->priority == priority) {
+ print_acl_ipv6_rule(rule);
+ n_rules--;
+ }
+ }
+ printf("\n");
+}
+
+/**
+ * Initialize ACL pipeline Front End (FE).
+ *
+ * @param params
+ * A pointer to pipeline parameters
+ * @param arg
+ * A pointer to pipeline specific data (not used).
+ *
+ * @return
+ * - A pointer to the pipeline FE
+ * - NULL if initialization failed.
+ */
+static void *app_pipeline_acl_init(struct pipeline_params *params,
+ __rte_unused void *arg)
+{
+ struct app_pipeline_acl *p;
+ uint32_t size;
+
+ /* 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 app_pipeline_acl));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ if (p == NULL)
+ return NULL;
+
+ /* Initialization */
+ p->n_ports_in = params->n_ports_in;
+ p->n_ports_out = params->n_ports_out;
+
+ if (!acl_rule_table_created) {
+/* Only create and init once when first ACL pipeline/thread comes up */
+
+ /* Init tailq tables */
+ TAILQ_INIT(&acl_tailq_rules_ipv4a);
+ acl_n_tailq_rules_ipv4a = 0;
+ TAILQ_INIT(&acl_tailq_rules_ipv4b);
+ acl_n_tailq_rules_ipv4b = 0;
+ TAILQ_INIT(&acl_tailq_rules_ipv6a);
+ acl_n_tailq_rules_ipv6a = 0;
+ TAILQ_INIT(&acl_tailq_rules_ipv6b);
+ acl_n_tailq_rules_ipv6b = 0;
+ TAILQ_INIT(&acl_commands);
+ acl_tailq_rules_ipv4_active = &acl_tailq_rules_ipv4a;
+ acl_tailq_rules_ipv4_standby = &acl_tailq_rules_ipv4b;
+ acl_tailq_rules_ipv6_active = &acl_tailq_rules_ipv6a;
+ acl_tailq_rules_ipv6_standby = &acl_tailq_rules_ipv6b;
+ acl_n_tailq_rules_ipv4_active = &acl_n_tailq_rules_ipv4a;
+ acl_n_tailq_rules_ipv4_standby = &acl_n_tailq_rules_ipv4b;
+ acl_n_tailq_rules_ipv6_active = &acl_n_tailq_rules_ipv6a;
+ acl_n_tailq_rules_ipv6_standby = &acl_n_tailq_rules_ipv6b;
+
+ /* Both IPV4 and IPV6 enabled by default */
+ acl_ipv4_enabled = 1;
+ acl_ipv6_enabled = 1;
+
+ printf("ACL FE Init Create ACL Tables acl_n_rules = %i\n",
+ acl_n_rules);
+
+ /* Init Action Array and Counter Table */
+ action_array_size =
+ RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_action_key) *
+ action_array_max);
+ action_array_a =
+ rte_zmalloc(NULL, action_array_size, RTE_CACHE_LINE_SIZE);
+ if (action_array_a == NULL)
+ return NULL;
+ action_array_b =
+ rte_zmalloc(NULL, action_array_size, RTE_CACHE_LINE_SIZE);
+ if (action_array_b == NULL)
+ return NULL;
+ memset(action_array_a, 0, action_array_size);
+ memset(action_array_b, 0, action_array_size);
+ action_array_active = action_array_a;
+ action_array_standby = action_array_b;
+ memset(&action_counter_table, 0, sizeof(action_counter_table));
+
+ acl_rule_table_created = 1;
+ }
+
+ if (!rte_acl_hertz_computed) {
+/* all initialization serialized on core 0, so no need for lock */
+ rte_acl_ticks_in_one_second = rte_get_tsc_hz();
+ rte_acl_hertz_computed = 1;
+ }
+
+ return (void *)p;
+}
+
+/**
+ * Free ACL pipeline resources.
+ *
+ * @param pipeline
+ * A pointer to the pipeline to delete.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int app_pipeline_acl_free(void *pipeline)
+{
+ struct app_pipeline_acl *p = pipeline;
+
+ /* Check input arguments */
+ if (p == NULL)
+ return -1;
+
+ /* Free resources */
+ /* Ignore Klockwork infinite loop issues for all while loops */
+ while (!TAILQ_EMPTY(&acl_tailq_rules_ipv4a)) {
+ struct app_pipeline_acl_rule *rule;
+
+ rule = TAILQ_FIRST(&acl_tailq_rules_ipv4a);
+ TAILQ_REMOVE(&acl_tailq_rules_ipv4a, rule, node);
+ rte_free(rule);
+ }
+ while (!TAILQ_EMPTY(&acl_tailq_rules_ipv4b)) {
+ struct app_pipeline_acl_rule *rule;
+
+ rule = TAILQ_FIRST(&acl_tailq_rules_ipv4b);
+ TAILQ_REMOVE(&acl_tailq_rules_ipv4b, rule, node);
+ rte_free(rule);
+ }
+ while (!TAILQ_EMPTY(&acl_tailq_rules_ipv6a)) {
+ struct app_pipeline_acl_rule *rule;
+
+ rule = TAILQ_FIRST(&acl_tailq_rules_ipv6a);
+ TAILQ_REMOVE(&acl_tailq_rules_ipv6a, rule, node);
+ rte_free(rule);
+ }
+ while (!TAILQ_EMPTY(&acl_tailq_rules_ipv6b)) {
+ struct app_pipeline_acl_rule *rule;
+
+ rule = TAILQ_FIRST(&acl_tailq_rules_ipv6b);
+ TAILQ_REMOVE(&acl_tailq_rules_ipv6b, rule, node);
+ rte_free(rule);
+ }
+ while (!TAILQ_EMPTY(&acl_commands)) {
+ struct app_pipeline_acl_rule *command;
+
+ command = TAILQ_FIRST(&acl_commands);
+ TAILQ_REMOVE(&acl_commands, command, node);
+ rte_free(command);
+ }
+ rte_free(action_array_a);
+ rte_free(action_array_b);
+ rte_free(p);
+ return 0;
+}
+
+/**
+ * Verify that the ACL rule is valid.
+ * Both IPv4 and IPv6 rules
+ *
+ * @param key
+ * A pointer to the ACL rule to verify.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+static int
+app_pipeline_acl_key_check_and_normalize(struct pipeline_acl_key *key)
+{
+ switch (key->type) {
+ case PIPELINE_ACL_IPV4_5TUPLE:
+ {
+ uint32_t src_ip_depth =
+ key->key.ipv4_5tuple.src_ip_mask;
+ uint32_t dst_ip_depth =
+ key->key.ipv4_5tuple.dst_ip_mask;
+ uint16_t src_port_from =
+ key->key.ipv4_5tuple.src_port_from;
+ uint16_t src_port_to = key->key.ipv4_5tuple.src_port_to;
+ uint16_t dst_port_from =
+ key->key.ipv4_5tuple.dst_port_from;
+ uint16_t dst_port_to = key->key.ipv4_5tuple.dst_port_to;
+
+ uint32_t src_ip_netmask = 0;
+ uint32_t dst_ip_netmask = 0;
+
+ if ((src_ip_depth > 32) ||
+ (dst_ip_depth > 32) ||
+ (src_port_from > src_port_to) ||
+ (dst_port_from > dst_port_to))
+ return -1;
+
+ if (src_ip_depth)
+ src_ip_netmask = (~0) << (32 - src_ip_depth);
+
+ if (dst_ip_depth)
+ dst_ip_netmask = ((~0) << (32 - dst_ip_depth));
+
+ key->key.ipv4_5tuple.src_ip &= src_ip_netmask;
+ key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask;
+
+ return 0;
+ }
+ case PIPELINE_ACL_IPV6_5TUPLE:
+ {
+ uint32_t src_ip_depth =
+ key->key.ipv6_5tuple.src_ip_mask;
+ uint32_t dst_ip_depth =
+ key->key.ipv6_5tuple.dst_ip_mask;
+ uint16_t src_port_from =
+ key->key.ipv6_5tuple.src_port_from;
+ uint16_t src_port_to = key->key.ipv6_5tuple.src_port_to;
+ uint16_t dst_port_from =
+ key->key.ipv6_5tuple.dst_port_from;
+ uint16_t dst_port_to = key->key.ipv6_5tuple.dst_port_to;
+ uint8_t src_ip_netmask[16];
+ uint8_t dst_ip_netmask[16];
+ int i;
+
+ convert_prefixlen_to_netmask_ipv6(src_ip_depth,
+ src_ip_netmask);
+ convert_prefixlen_to_netmask_ipv6(dst_ip_depth,
+ dst_ip_netmask);
+ for (i = 0; i < 16; i++) {
+ key->key.ipv6_5tuple.src_ip[i] &=
+ src_ip_netmask[i];
+ key->key.ipv6_5tuple.dst_ip[i] &=
+ dst_ip_netmask[i];
+ }
+ return 0;
+ }
+
+ default:
+ return -1;
+ }
+}
+
+/**
+ * Add ACL rule to the ACL rule table.
+ * Rules are added standby table.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules can be added.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the ACL rule to add.
+ * @param priority
+ * Priority of the ACL rule.
+ * @param port_id
+ * Port ID of the ACL rule.
+ * @param action_id
+ * Action ID of the ACL rule. Defined in Action Table.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_acl_add_rule(struct app_params *app,
+ struct pipeline_acl_key *key,
+ uint32_t priority,
+ uint32_t port_id, uint32_t action_id)
+{
+ struct app_pipeline_acl_rule *rule;
+ struct pipeline_acl_add_msg_rsp *rsp;
+ int new_rule, src_field_start, dst_field_start, i;
+ uint32_t *ip1, *ip2, *ip3, *ip4, src_mask, dest_mask;
+ uint32_t src_ip[IPV6_32BIT_LENGTH], dst_ip[IPV6_32BIT_LENGTH];
+ const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
+
+ struct rte_table_acl_rule_add_params params;
+ struct acl_table_entry entry = {
+ .head = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_id},
+ },
+ .action_id = action_id,
+ };
+
+ memset(&params, 0, sizeof(params));
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (key == NULL) || !((key->type == PIPELINE_ACL_IPV4_5TUPLE) ||
+ (key->type == PIPELINE_ACL_IPV6_5TUPLE)))
+ return -1;
+
+ if (action_id > action_array_max) {
+ printf("Action ID greater than max\n");
+ return -1;
+ }
+
+ if (app_pipeline_acl_key_check_and_normalize(key) != 0)
+ return -1;
+
+ /* Find existing rule or allocate new rule */
+ rule = app_pipeline_acl_rule_find(key);
+ new_rule = (rule == NULL);
+ if (rule == NULL) {
+ rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE);
+
+ if (rule == NULL)
+ return -1;
+ }
+
+ /* Allocate Response */
+ rsp = app_msg_alloc(app);
+ if (rsp == NULL) {
+ if (new_rule)
+ rte_free(rule);
+ return -1;
+ }
+
+ switch (key->type) {
+ case PIPELINE_ACL_IPV4_5TUPLE:
+ params.priority = priority;
+ params.field_value[0].value.u8 = key->key.ipv4_5tuple.proto;
+ params.field_value[0].mask_range.u8 =
+ key->key.ipv4_5tuple.proto_mask;
+ params.field_value[1].value.u32 = key->key.ipv4_5tuple.src_ip;
+ params.field_value[1].mask_range.u32 =
+ key->key.ipv4_5tuple.src_ip_mask;
+ params.field_value[2].value.u32 = key->key.ipv4_5tuple.dst_ip;
+ params.field_value[2].mask_range.u32 =
+ key->key.ipv4_5tuple.dst_ip_mask;
+ params.field_value[3].value.u16 =
+ key->key.ipv4_5tuple.src_port_from;
+ params.field_value[3].mask_range.u16 =
+ key->key.ipv4_5tuple.src_port_to;
+ params.field_value[4].value.u16 =
+ key->key.ipv4_5tuple.dst_port_from;
+ params.field_value[4].mask_range.u16 =
+ key->key.ipv4_5tuple.dst_port_to;
+
+ rsp->status =
+ rte_table_acl_ops.f_add(acl_rule_table_ipv4_standby,
+ &params,
+ (struct rte_pipeline_table_entry *)
+ &entry, &rsp->key_found,
+ (void **)&rsp->entry_ptr);
+
+ if (rsp->status != 0)
+ printf
+ ("ACL IPV4 Add Rule Command failed key_found: %i\n",
+ rsp->key_found);
+ else
+ printf
+ ("ACL IPV4 Add Rule Command success key_found: %i\n",
+ rsp->key_found);
+
+ break;
+
+ case PIPELINE_ACL_IPV6_5TUPLE:
+ ip1 = (uint32_t *) (key->key.ipv6_5tuple.src_ip);
+ ip2 = ip1 + 1;
+ ip3 = ip1 + 2;
+ ip4 = ip1 + 3;
+
+ params.priority = priority;
+ params.field_value[0].value.u8 = key->key.ipv6_5tuple.proto;
+ params.field_value[0].mask_range.u8 =
+ key->key.ipv6_5tuple.proto_mask;
+
+ src_ip[0] = rte_bswap32(*ip1);
+ src_ip[1] = rte_bswap32(*ip2);
+ src_ip[2] = rte_bswap32(*ip3);
+ src_ip[3] = rte_bswap32(*ip4);
+
+ src_mask = key->key.ipv6_5tuple.src_ip_mask;
+
+ src_field_start = 1;
+ for (i = 0; i != RTE_DIM(src_ip); i++, src_field_start++) {
+ if (src_mask >= (i + 1) * nbu32)
+ params.field_value[src_field_start].
+ mask_range.u32 = nbu32;
+ else
+ params.field_value[src_field_start].
+ mask_range.u32 =
+ src_mask >
+ (i * nbu32) ? src_mask - (i * 32) : 0;
+ params.field_value[src_field_start].value.u32 =
+ src_ip[i];
+ }
+
+ ip1 = (uint32_t *) (key->key.ipv6_5tuple.dst_ip);
+ ip2 = ip1 + 1;
+ ip3 = ip1 + 2;
+ ip4 = ip1 + 3;
+
+ dst_ip[0] = rte_bswap32(*ip1);
+ dst_ip[1] = rte_bswap32(*ip2);
+ dst_ip[2] = rte_bswap32(*ip3);
+ dst_ip[3] = rte_bswap32(*ip4);
+
+ dest_mask = key->key.ipv6_5tuple.dst_ip_mask;
+
+ dst_field_start = 5;
+ for (i = 0; i != RTE_DIM(dst_ip); i++, dst_field_start++) {
+ if (dest_mask >= (i + 1) * nbu32)
+ params.field_value[dst_field_start].
+ mask_range.u32 = nbu32;
+ else
+ params.field_value[dst_field_start].
+ mask_range.u32 =
+ dest_mask >
+ (i * nbu32) ? dest_mask - (i * 32) : 0;
+ params.field_value[dst_field_start].value.u32 =
+ dst_ip[i];
+ }
+
+ params.field_value[9].value.u16 =
+ key->key.ipv6_5tuple.src_port_from;
+ params.field_value[9].mask_range.u16 =
+ key->key.ipv6_5tuple.src_port_to;
+ params.field_value[10].value.u16 =
+ key->key.ipv6_5tuple.dst_port_from;
+ params.field_value[10].mask_range.u16 =
+ key->key.ipv6_5tuple.dst_port_to;
+
+ rsp->status =
+ rte_table_acl_ops.f_add(acl_rule_table_ipv6_standby,
+ &params,
+ (struct rte_pipeline_table_entry *)
+ &entry, &rsp->key_found,
+ (void **)&rsp->entry_ptr);
+
+ if (rsp->status != 0)
+ printf
+ ("ACL IPV6 Add Rule Command failed key_found: %i\n",
+ rsp->key_found);
+ else
+ printf
+ ("ACL IPV6 Add Rule Command success key_found: %i\n",
+ rsp->key_found);
+
+ break;
+
+ default:
+ /* Error */
+ app_msg_free(app, rsp);
+ if (new_rule)
+ rte_free(rule);
+ return -1;
+ }
+
+ /* Read response and write rule */
+ if (rsp->status ||
+ (rsp->entry_ptr == NULL) ||
+ ((new_rule == 0) && (rsp->key_found == 0)) ||
+ ((new_rule == 1) && (rsp->key_found == 1))) {
+ app_msg_free(app, rsp);
+ if (new_rule)
+ rte_free(rule);
+ return -1;
+ }
+
+ memcpy(&rule->key, key, sizeof(*key));
+ rule->priority = priority;
+ rule->port_id = port_id;
+ rule->action_id = action_id;
+ rule->entry_ptr = rsp->entry_ptr;
+
+ /* Commit rule */
+ if (new_rule) {
+ if (key->type == PIPELINE_ACL_IPV4_5TUPLE) {
+ TAILQ_INSERT_TAIL(acl_tailq_rules_ipv4_standby, rule,
+ node);
+ (*acl_n_tailq_rules_ipv4_standby)++;
+ } else { /* IPV6 */
+ TAILQ_INSERT_TAIL(acl_tailq_rules_ipv6_standby, rule,
+ node);
+ (*acl_n_tailq_rules_ipv6_standby)++;
+ }
+ }
+
+ if (key->type == PIPELINE_ACL_IPV4_5TUPLE)
+ print_acl_ipv4_rule(rule);
+ else
+ print_acl_ipv6_rule(rule);
+
+ /* Free response */
+ app_msg_free(app, rsp);
+
+ return 0;
+}
+
+/**
+ * Delete ACL rule from the ACL rule table.
+ * Rules deleted from standby tables.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules can be deleted.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the ACL rule to delete.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_acl_delete_rule(struct app_params *app,
+ struct pipeline_acl_key *key)
+{
+ struct app_pipeline_acl_rule *rule;
+ int status, key_found;
+ uint32_t src_ip[IPV6_32BIT_LENGTH], dst_ip[IPV6_32BIT_LENGTH];
+ int new_rule, src_field_start, dst_field_start, i;
+ uint32_t *ip1, *ip2, *ip3, *ip4, src_mask, dest_mask;
+ const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
+
+
+ struct rte_table_acl_rule_delete_params params;
+
+ memset(&params, 0, sizeof(params));
+
+ /* Check input arguments */
+ if ((app == NULL) ||
+ (key == NULL) || !((key->type == PIPELINE_ACL_IPV4_5TUPLE) ||
+ (key->type == PIPELINE_ACL_IPV6_5TUPLE)))
+ return -1;
+
+ if (app_pipeline_acl_key_check_and_normalize(key) != 0)
+ return -1;
+
+ /* Find rule */
+ rule = app_pipeline_acl_rule_find(key);
+ if (rule == NULL) {
+ printf("ACL Delete Rule - Rule does not exist\n");
+ return 0;
+ }
+
+ switch (key->type) {
+ case PIPELINE_ACL_IPV4_5TUPLE:
+ params.field_value[0].value.u8 = key->key.ipv4_5tuple.proto;
+ params.field_value[0].mask_range.u8 =
+ key->key.ipv4_5tuple.proto_mask;
+ params.field_value[1].value.u32 = key->key.ipv4_5tuple.src_ip;
+ params.field_value[1].mask_range.u32 =
+ key->key.ipv4_5tuple.src_ip_mask;
+ params.field_value[2].value.u32 = key->key.ipv4_5tuple.dst_ip;
+ params.field_value[2].mask_range.u32 =
+ key->key.ipv4_5tuple.dst_ip_mask;
+ params.field_value[3].value.u16 =
+ key->key.ipv4_5tuple.src_port_from;
+ params.field_value[3].mask_range.u16 =
+ key->key.ipv4_5tuple.src_port_to;
+ params.field_value[4].value.u16 =
+ key->key.ipv4_5tuple.dst_port_from;
+ params.field_value[4].mask_range.u16 =
+ key->key.ipv4_5tuple.dst_port_to;
+
+ status = rte_table_acl_ops.f_delete(acl_rule_table_ipv4_standby,
+ &params, &key_found, NULL);
+
+ if (status != 0)
+ printf
+ ("ACL IPV4 Del Rule Command failed key_found: %i\n",
+ key_found);
+ else
+ printf
+ ("ACL IPV4 Del Rule Command success key_found: %i\n",
+ key_found);
+
+ break;
+
+ case PIPELINE_ACL_IPV6_5TUPLE:
+ ip1 = (uint32_t *) (key->key.ipv6_5tuple.src_ip);
+ ip2 = ip1 + 1;
+ ip3 = ip1 + 2;
+ ip4 = ip1 + 3;
+
+ params.field_value[0].value.u8 = key->key.ipv6_5tuple.proto;
+ params.field_value[0].mask_range.u8 =
+ key->key.ipv6_5tuple.proto_mask;
+
+ src_ip[0] = rte_bswap32(*ip1);
+ src_ip[1] = rte_bswap32(*ip2);
+ src_ip[2] = rte_bswap32(*ip3);
+ src_ip[3] = rte_bswap32(*ip4);
+
+ src_mask = key->key.ipv6_5tuple.src_ip_mask;
+
+ src_field_start = 1;
+ for (i = 0; i != RTE_DIM(src_ip); i++, src_field_start++) {
+ if (src_mask >= (i + 1) * nbu32)
+ params.field_value[src_field_start].
+ mask_range.u32 = nbu32;
+ else
+ params.field_value[src_field_start].
+ mask_range.u32 =
+ src_mask >
+ (i * nbu32) ? src_mask - (i * 32) : 0;
+ params.field_value[src_field_start].value.u32 =
+ src_ip[i];
+ }
+
+ ip1 = (uint32_t *) (key->key.ipv6_5tuple.dst_ip);
+ ip2 = ip1 + 1;
+ ip3 = ip1 + 2;
+ ip4 = ip1 + 3;
+
+ dst_ip[0] = rte_bswap32(*ip1);
+ dst_ip[1] = rte_bswap32(*ip2);
+ dst_ip[2] = rte_bswap32(*ip3);
+ dst_ip[3] = rte_bswap32(*ip4);
+
+ dest_mask = key->key.ipv6_5tuple.dst_ip_mask;
+
+ dst_field_start = 5;
+ for (i = 0; i != RTE_DIM(dst_ip); i++, dst_field_start++) {
+ if (dest_mask >= (i + 1) * nbu32)
+ params.field_value[dst_field_start].
+ mask_range.u32 = nbu32;
+ else
+ params.field_value[dst_field_start].
+ mask_range.u32 =
+ dest_mask >
+ (i * nbu32) ? dest_mask - (i * 32) : 0;
+ params.field_value[dst_field_start].value.u32 =
+ dst_ip[i];
+ }
+
+ params.field_value[9].value.u16 =
+ key->key.ipv6_5tuple.src_port_from;
+ params.field_value[9].mask_range.u16 =
+ key->key.ipv6_5tuple.src_port_to;
+ params.field_value[10].value.u16 =
+ key->key.ipv6_5tuple.dst_port_from;
+ params.field_value[10].mask_range.u16 =
+ key->key.ipv6_5tuple.dst_port_to;
+
+
+ status = rte_table_acl_ops.f_delete(acl_rule_table_ipv6_standby,
+ &params, &key_found, NULL);
+
+ if (status != 0)
+ printf
+ ("ACL IPV6 Del Rule Command failed key_found: %i\n",
+ key_found);
+ else
+ printf
+ ("ACL IPV6 Del Rule Command success key_found: %i\n",
+ key_found);
+
+ break;
+
+ default:
+ /* Error */
+ return -1;
+ }
+
+ /* Read response */
+ if (status || !key_found)
+ return -1;
+
+ /* Remove rule */
+ if (key->type == PIPELINE_ACL_IPV4_5TUPLE) {
+ TAILQ_REMOVE(acl_tailq_rules_ipv4_standby, rule, node);
+ (*acl_n_tailq_rules_ipv4_standby)--;
+ } else { /* IPV6 */
+ TAILQ_REMOVE(acl_tailq_rules_ipv6_standby, rule, node);
+ (*acl_n_tailq_rules_ipv6_standby)--;
+ }
+
+ rte_free(rule);
+
+ return 0;
+}
+
+/**
+ * Clear all ACL rules from the ACL rule table.
+ * Rules cleared from standby tables.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules will be cleared.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int app_pipeline_acl_clearrules(struct app_params *app)
+{
+ struct app_pipeline_acl_rule *rule;
+ struct app_pipeline_acl_rule *command;
+ uint32_t n_rules;
+
+ int priority;
+
+ /* Check input arguments */
+ if (app == NULL)
+ return -1;
+
+ n_rules = *acl_n_tailq_rules_ipv4_standby;
+ for (priority = 0; n_rules; priority++) {
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv4_standby, node) {
+ if (rule->priority == priority) {
+ struct pipeline_acl_key key = rule->key;
+
+ /* Store command to update standby tables after switchover */
+ command =
+ rte_malloc(NULL, sizeof(*command),
+ RTE_CACHE_LINE_SIZE);
+ if (command == NULL) {
+ printf("Cannot allocation command\n");
+ return -1;
+ }
+ memset(command, 0,
+ sizeof(struct app_pipeline_acl_rule));
+ memcpy(&command->key, &key, sizeof(key));
+ command->command = acl_delete_command;
+ TAILQ_INSERT_TAIL(&acl_commands, command, node);
+
+ /* Delete rule */
+ app_pipeline_acl_delete_rule(app, &key);
+ n_rules--;
+ }
+ }
+ }
+
+ n_rules = *acl_n_tailq_rules_ipv6_standby;
+ for (priority = 0; n_rules; priority++) {
+ TAILQ_FOREACH(rule, acl_tailq_rules_ipv6_standby, node) {
+ if (rule->priority == priority) {
+ struct pipeline_acl_key key = rule->key;
+
+ /* Store command to update standby tables after switchover */
+ command =
+ rte_malloc(NULL, sizeof(*command),
+ RTE_CACHE_LINE_SIZE);
+ if (command == NULL) {
+ printf("Cannot allocation command\n");
+ return -1;
+ }
+ memset(command, 0,
+ sizeof(struct app_pipeline_acl_rule));
+ memcpy(&command->key, &key, sizeof(key));
+ command->command = acl_delete_command;
+ TAILQ_INSERT_TAIL(&acl_commands, command, node);
+
+ /* Delete rule */
+ app_pipeline_acl_delete_rule(app, &key);
+ n_rules--;
+ }
+ }
+ }
+
+ /* Clear Action Array */
+ memset(action_array_standby, 0, action_array_size);
+
+ return 0;
+}
+
+/*
+ * loadrules
+ */
+
+/**
+ * Open file and process all commands in the file.
+ *
+ * @param ctx
+ * A pointer to the CLI context
+ * @param file_name
+ * A pointer to the file to process.
+ *
+ */
+static void app_loadrules_file(cmdline_parse_ctx_t *ctx, const char *file_name)
+{
+ struct cmdline *file_cl;
+ int fd;
+
+ fd = open(file_name, O_RDONLY);
+ if (fd < 0) {
+ printf("Cannot open file \"%s\"\n", file_name);
+ return;
+ }
+
+ file_cl = cmdline_new(ctx, "", fd, 1);
+ cmdline_interact(file_cl);
+ close(fd);
+}
+
+struct cmd_loadrules_file_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t loadrules_string;
+ char file_name[APP_FILE_NAME_SIZE];
+};
+
+/**
+ * Parse load rules command.
+ * Verify that file exists.
+ * Clear existing rules and action.
+ * Process commands in command file.
+ *
+ * @param parsed_result
+ * A pointer to the CLI command parsed result
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data.
+ *
+ * @return
+ * 0 on success, negative on error.
+ *
+ */
+static void
+cmd_loadrules_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_loadrules_file_result *params = parsed_result;
+ struct app_params *app = data;
+ int status;
+ int fd;
+
+ /* Make sure the file exists before clearing rules and actions */
+ fd = open(params->file_name, O_RDONLY);
+ if (fd < 0) {
+ printf("Cannot open file \"%s\"\n", params->file_name);
+ return;
+ }
+ close(fd);
+
+ /* Clear all rules and actions */
+ status = app_pipeline_acl_clearrules(app);
+
+ if (status != 0) {
+ printf("Command clearrules failed\n");
+ return;
+ }
+
+ /* Process commands in script file */
+ app_loadrules_file(cl->ctx, params->file_name);
+}
+
+cmdline_parse_token_string_t cmd_loadrules_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_loadrules_file_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_loadrules_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_loadrules_file_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_loadrules_loadrules_string =
+TOKEN_STRING_INITIALIZER(struct cmd_loadrules_file_result, loadrules_string,
+ "loadrules");
+
+cmdline_parse_token_string_t cmd_loadrules_file_name =
+TOKEN_STRING_INITIALIZER(struct cmd_loadrules_file_result, file_name, NULL);
+
+cmdline_parse_inst_t cmd_loadrules = {
+ .f = cmd_loadrules_parsed,
+ .data = NULL,
+ .help_str = "ACL Load Rules",
+ .tokens = {
+ (void *)&cmd_loadrules_p_string,
+ (void *)&cmd_loadrules_acl_string,
+ (void *)&cmd_loadrules_loadrules_string,
+ (void *)&cmd_loadrules_file_name,
+ NULL,
+ },
+};
+
+/**
+ * Add Action to the Action table.
+ * Actions are added standby table.
+ * Applyruleset command will activate the change.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the Action to add.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_action_add(struct app_params *app, struct pipeline_action_key *key)
+{
+
+ /*
+ * This function will update the action IDs on the standby table.
+ * Activating the changes is done with the applyruleset command.
+ */
+
+ uint32_t action_bitmap = key->action_bitmap;
+ uint32_t action_id = key->action_id;
+
+ if (action_id >= action_array_max) {
+ if (ACL_DEBUG)
+ printf("Action id: %u out of range\n", action_id);
+ return -1;
+ }
+
+ action_array_standby[action_id].action_id = action_id;
+
+ if (ACL_DEBUG)
+ printf("Adding action id: %u Type: ", action_id);
+ if (action_bitmap == acl_action_packet_accept) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_packet_accept;
+ if (ACL_DEBUG)
+ printf("Accept\n");
+ }
+ if (action_bitmap == acl_action_packet_drop) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_packet_drop;
+ if (ACL_DEBUG)
+ printf("Drop\n");
+ }
+ if (action_bitmap == acl_action_nat) {
+ action_array_standby[action_id].action_bitmap |= acl_action_nat;
+ action_array_standby[action_id].nat_port = key->nat_port;
+ if (ACL_DEBUG)
+ printf("NAT Port ID: %u\n", key->nat_port);
+ }
+ if (action_bitmap == acl_action_fwd) {
+ action_array_standby[action_id].action_bitmap |= acl_action_fwd;
+ action_array_standby[action_id].fwd_port = key->fwd_port;
+ if (ACL_DEBUG)
+ printf("FWD Port ID: %u\n", key->fwd_port);
+ }
+ if (action_bitmap == acl_action_count) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_count;
+ if (ACL_DEBUG)
+ printf("Count\n");
+ }
+ if (action_bitmap == acl_action_conntrack) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_conntrack;
+ if (ACL_DEBUG)
+ printf("Conntrack\n");
+ }
+ if (action_bitmap == acl_action_connexist) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_connexist;
+ action_array_standby[action_id].private_public =
+ key->private_public;
+ if (ACL_DEBUG)
+ printf("Conntrack prvpub: %i\n", key->private_public);
+ }
+ if (action_bitmap == acl_action_dscp) {
+ action_array_standby[action_id].action_bitmap |=
+ acl_action_dscp;
+ action_array_standby[action_id].dscp_priority =
+ key->dscp_priority;
+ if (ACL_DEBUG)
+ printf("DSCP Priority: %u\n", key->dscp_priority);
+ }
+
+ if (ACL_DEBUG)
+ printf("action_bitmap: %" PRIu32 "\n",
+ action_array_standby[action_id].action_bitmap);
+
+ return 0;
+}
+
+/**
+ * Delete Action from the Action table.
+ * Actions are deleted from the standby table.
+ * Applyruleset command will activate the change.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the Action to delete.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_action_delete(struct app_params *app,
+ struct pipeline_action_key *key)
+{
+ /*
+ * This function will update the action IDs on the standby table.
+ * Activating the changes is done with the applyruleset command.
+ */
+
+ uint32_t action_bitmap = key->action_bitmap;
+ uint32_t action_id = key->action_id;
+
+ if (action_id >= action_array_max) {
+ if (ACL_DEBUG)
+ printf("Action id: %u out of range\n", action_id);
+ return -1;
+ }
+
+ if (action_array_standby[action_id].action_bitmap & action_bitmap)
+ action_array_standby[action_id].action_bitmap &= ~action_bitmap;
+ else
+ printf("ACL Action Delete - Action not set\n");
+
+ if (ACL_DEBUG) {
+ printf("Deleting action id: %u Type: ", key->action_id);
+ if (action_bitmap == acl_action_packet_accept)
+ printf("Accept\n");
+ if (action_bitmap == acl_action_packet_drop)
+ printf("Drop\n");
+ if (action_bitmap == acl_action_nat)
+ printf("NAT\n");
+ if (action_bitmap == acl_action_fwd)
+ printf("FWD\n");
+ if (action_bitmap == acl_action_count)
+ printf("Count\n");
+ if (action_bitmap == acl_action_conntrack)
+ printf("Conntrack\n");
+ if (action_bitmap == acl_action_connexist)
+ printf("Connexist\n");
+ if (action_bitmap == acl_action_dscp)
+ printf("DSCP\n");
+
+ printf("action_bitmap: %" PRIu32 "\n",
+ action_array_standby[action_id].action_bitmap);
+ }
+
+ return 0;
+}
+
+/*
+ * p acl add
+ */
+
+/**
+ * A structure defining the ACL add rule command.
+ */
+struct cmd_acl_add_ip_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t add_string;
+ int32_t priority;
+ cmdline_ipaddr_t src_ip;
+ uint32_t src_ip_mask;
+ cmdline_ipaddr_t dst_ip;
+ uint32_t dst_ip_mask;
+ uint16_t src_port_from;
+ uint16_t src_port_to;
+ uint16_t dst_port_from;
+ uint16_t dst_port_to;
+ uint8_t proto;
+ uint8_t proto_mask;
+ uint8_t port_id;
+ uint32_t action_id;
+};
+
+/**
+ * Parse ACL add rule CLI command.
+ * Add rule to standby table.
+ * Store command to update standby table
+ * after applyruleset command is invoked.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_add_ip_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_add_ip_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_acl_key key;
+ struct app_pipeline_acl_rule *command;
+ int status;
+
+ memset(&key, 0, sizeof(struct pipeline_acl_key));
+
+ if (params->src_ip.family == AF_INET) {
+ key.type = PIPELINE_ACL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t)
+ params->src_ip.
+ addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+ key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t)
+ params->dst_ip.
+ addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv4_5tuple.proto = params->proto;
+ key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+ }
+ if (params->src_ip.family == AF_INET6) {
+ if (ACL_DEBUG)
+ printf("entered IPV6");
+ key.type = PIPELINE_ACL_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.src_ip,
+ params->src_ip.addr.ipv6.s6_addr,
+ sizeof(params->src_ip.addr.ipv6.s6_addr));
+ key.key.ipv6_5tuple.src_ip_mask = params->src_ip_mask;
+ memcpy(key.key.ipv6_5tuple.dst_ip,
+ params->dst_ip.addr.ipv6.s6_addr,
+ sizeof(params->src_ip.addr.ipv6.s6_addr));
+ key.key.ipv6_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv6_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv6_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv6_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv6_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv6_5tuple.proto = params->proto;
+ key.key.ipv6_5tuple.proto_mask = params->proto_mask;
+ }
+
+ status = app_pipeline_acl_add_rule(app, &key, params->priority, 1,
+/* Set to 1 as default, overwritten by Action FWD/NAT Port */
+ params->action_id);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+
+ /* Store command to update standby tables after switchover */
+ command = rte_malloc(NULL, sizeof(*command), RTE_CACHE_LINE_SIZE);
+ if (command == NULL) {
+ printf("Cannot allocation command\n");
+ return;
+ }
+ memset(command, 0, sizeof(struct app_pipeline_acl_rule));
+ memcpy(&command->key, &key, sizeof(key));
+ command->priority = params->priority;
+ command->port_id = params->port_id;
+ command->action_id = params->action_id;
+ command->command = acl_add_command;
+ TAILQ_INSERT_TAIL(&acl_commands, command, node);
+}
+
+cmdline_parse_token_string_t cmd_acl_add_ip_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_add_ip_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_acl_add_ip_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_add_ip_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_add_ip_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_add_ip_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_acl_add_ip_priority =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result, priority,
+ INT32);
+
+cmdline_parse_token_ipaddr_t cmd_acl_add_ip_src_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_acl_add_ip_result, src_ip);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_src_ip_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result, src_ip_mask,
+ UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_acl_add_ip_dst_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_acl_add_ip_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_dst_ip_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result, dst_ip_mask,
+ UINT32);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_src_port_from =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_src_port_to =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ src_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_dst_port_from =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ dst_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_dst_port_to =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ dst_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_proto =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ proto, UINT8);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_proto_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ proto_mask, UINT8);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ port_id, UINT8);
+
+cmdline_parse_token_num_t cmd_acl_add_ip_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_add_ip_result,
+ action_id, UINT32);
+
+cmdline_parse_inst_t cmd_acl_add_ip = {
+ .f = cmd_acl_add_ip_parsed,
+ .data = NULL,
+ .help_str = "ACL rule add",
+ .tokens = {
+ (void *)&cmd_acl_add_ip_p_string,
+ (void *)&cmd_acl_add_ip_acl_string,
+ (void *)&cmd_acl_add_ip_add_string,
+ (void *)&cmd_acl_add_ip_priority,
+ (void *)&cmd_acl_add_ip_src_ip,
+ (void *)&cmd_acl_add_ip_src_ip_mask,
+ (void *)&cmd_acl_add_ip_dst_ip,
+ (void *)&cmd_acl_add_ip_dst_ip_mask,
+ (void *)&cmd_acl_add_ip_src_port_from,
+ (void *)&cmd_acl_add_ip_src_port_to,
+ (void *)&cmd_acl_add_ip_dst_port_from,
+ (void *)&cmd_acl_add_ip_dst_port_to,
+ (void *)&cmd_acl_add_ip_proto,
+ (void *)&cmd_acl_add_ip_proto_mask,
+ (void *)&cmd_acl_add_ip_action_id,
+ NULL,
+ },
+};
+
+/*
+ * p acl del
+ */
+
+/**
+ * A structure defining the ACL delete rule command.
+ */
+struct cmd_acl_del_ip_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t del_string;
+ cmdline_ipaddr_t src_ip;
+ uint32_t src_ip_mask;
+ cmdline_ipaddr_t dst_ip;
+ uint32_t dst_ip_mask;
+ uint16_t src_port_from;
+ uint16_t src_port_to;
+ uint16_t dst_port_from;
+ uint16_t dst_port_to;
+ uint8_t proto;
+ uint8_t proto_mask;
+};
+
+/**
+ * Parse ACL delete rule CLI command.
+ * Delete rule from standby table.
+ * Store command to update standby table
+ * after applyruleset command is invoked.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_del_ip_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_del_ip_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_acl_key key;
+ struct app_pipeline_acl_rule *command;
+ int status;
+
+ memset(&key, 0, sizeof(struct pipeline_acl_key));
+
+ if (params->src_ip.family == AF_INET) {
+ key.type = PIPELINE_ACL_IPV4_5TUPLE;
+ key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t)
+ params->src_ip.
+ addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+ key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t)
+ params->dst_ip.
+ addr.ipv4.s_addr);
+ key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv4_5tuple.proto = params->proto;
+ key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+ }
+ if (params->src_ip.family == AF_INET6) {
+ key.type = PIPELINE_ACL_IPV6_5TUPLE;
+ memcpy(key.key.ipv6_5tuple.src_ip,
+ params->src_ip.addr.ipv6.s6_addr,
+ sizeof(params->src_ip.addr.ipv6.s6_addr));
+ key.key.ipv6_5tuple.src_ip_mask = params->src_ip_mask;
+ memcpy(key.key.ipv6_5tuple.dst_ip,
+ params->dst_ip.addr.ipv6.s6_addr,
+ sizeof(params->dst_ip.addr.ipv6.s6_addr));
+ key.key.ipv6_5tuple.dst_ip_mask = params->dst_ip_mask;
+ key.key.ipv6_5tuple.src_port_from = params->src_port_from;
+ key.key.ipv6_5tuple.src_port_to = params->src_port_to;
+ key.key.ipv6_5tuple.dst_port_from = params->dst_port_from;
+ key.key.ipv6_5tuple.dst_port_to = params->dst_port_to;
+ key.key.ipv6_5tuple.proto = params->proto;
+ key.key.ipv6_5tuple.proto_mask = params->proto_mask;
+ }
+
+ status = app_pipeline_acl_delete_rule(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+
+ /* Store command to update standby tables after switchover */
+ command = rte_malloc(NULL, sizeof(*command), RTE_CACHE_LINE_SIZE);
+ if (command == NULL) {
+ printf("Cannot allocation command\n");
+ return;
+ }
+ memset(command, 0, sizeof(struct app_pipeline_acl_rule));
+ memcpy(&command->key, &key, sizeof(key));
+ command->command = acl_delete_command;
+ TAILQ_INSERT_TAIL(&acl_commands, command, node);
+}
+
+cmdline_parse_token_string_t cmd_acl_del_ip_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_del_ip_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_acl_del_ip_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_del_ip_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_del_ip_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_del_ip_result,
+ del_string, "del");
+
+cmdline_parse_token_ipaddr_t cmd_acl_del_ip_src_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_acl_del_ip_result, src_ip);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_src_ip_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result, src_ip_mask,
+ UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_acl_del_ip_dst_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_acl_del_ip_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_dst_ip_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result, dst_ip_mask,
+ UINT32);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_src_port_from =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result,
+ src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_src_port_to =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result, src_port_to,
+ UINT16);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_dst_port_from =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result,
+ dst_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_dst_port_to =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result,
+ dst_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_proto =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result,
+ proto, UINT8);
+
+cmdline_parse_token_num_t cmd_acl_del_ip_proto_mask =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_del_ip_result, proto_mask,
+ UINT8);
+
+cmdline_parse_inst_t cmd_acl_del_ip = {
+ .f = cmd_acl_del_ip_parsed,
+ .data = NULL,
+ .help_str = "ACL rule delete",
+ .tokens = {
+ (void *)&cmd_acl_del_ip_p_string,
+ (void *)&cmd_acl_del_ip_acl_string,
+ (void *)&cmd_acl_del_ip_del_string,
+ (void *)&cmd_acl_del_ip_src_ip,
+ (void *)&cmd_acl_del_ip_src_ip_mask,
+ (void *)&cmd_acl_del_ip_dst_ip,
+ (void *)&cmd_acl_del_ip_dst_ip_mask,
+ (void *)&cmd_acl_del_ip_src_port_from,
+ (void *)&cmd_acl_del_ip_src_port_to,
+ (void *)&cmd_acl_del_ip_dst_port_from,
+ (void *)&cmd_acl_del_ip_dst_port_to,
+ (void *)&cmd_acl_del_ip_proto,
+ (void *)&cmd_acl_del_ip_proto_mask,
+ NULL,
+ },
+};
+
+/*
+ * p acl stats
+ */
+
+/**
+ * A structure defining the ACL stats command.
+ */
+struct cmd_acl_stats_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t stats_string;
+};
+
+/**
+ * Display ACL and Connection Tracker stats to the console.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_stats_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_stats_result *params = parsed_result;
+ struct app_params *app = data;
+ int i, j;
+ struct rte_ACL_counter_block acl_counter_sums;
+ struct rte_CT_counter_block ct_counter_sums;
+ struct rte_CT_counter_block *ct_counters;
+ struct action_counter_block action_counter_sum[action_array_max];
+
+ memset(&acl_counter_sums, 0, sizeof(acl_counter_sums));
+ memset(&ct_counter_sums, 0, sizeof(ct_counter_sums));
+ memset(&action_counter_sum, 0, sizeof(action_counter_sum));
+
+ printf("ACL Stats\n");
+ for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) {
+ struct rte_ACL_counter_block *acl_ctrs =
+ &rte_acl_counter_table[i];
+ ct_counters = rte_acl_counter_table[i].ct_counters;
+ printf("acl entry[%i] tpkts_processed: %" PRIu64
+ ", pkts_drop: %" PRIu64 ", pkts_received: %" PRIu64
+ ", bytes_processed: %" PRIu64 "\n", i,
+ acl_ctrs->tpkts_processed, acl_ctrs->pkts_drop,
+ acl_ctrs->pkts_received, acl_ctrs->bytes_processed);
+
+ acl_counter_sums.tpkts_processed += acl_ctrs->tpkts_processed;
+ acl_counter_sums.bytes_processed += acl_ctrs->bytes_processed;
+ acl_counter_sums.pkts_drop += acl_ctrs->pkts_drop;
+ acl_counter_sums.pkts_received += acl_ctrs->pkts_received;
+ ct_counter_sums.pkts_forwarded += ct_counters->pkts_forwarded;
+ ct_counter_sums.pkts_drop += ct_counters->pkts_drop;
+ }
+
+ printf("ACL TOTAL: tpkts_processed: %" PRIu64 ", pkts_drop: %" PRIu64
+ ", pkts_received: %" PRIu64 ", bytes_processed: %" PRIu64 "\n\n",
+ acl_counter_sums.tpkts_processed,
+ acl_counter_sums.pkts_drop,
+ acl_counter_sums.pkts_received,
+ acl_counter_sums.bytes_processed);
+
+ printf("CT TOTAL: ct_packets_forwarded: %" PRIu64
+ ", ct_packets_dropped: %" PRIu64 "\n\n",
+ ct_counter_sums.pkts_forwarded, ct_counter_sums.pkts_drop);
+
+ for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) {
+ for (j = 0; j < action_array_max; j++) {
+ if (action_array_active[j].action_bitmap &
+ acl_action_count) {
+ action_counter_sum[j].packetCount +=
+ action_counter_table[i][j].packetCount;
+ action_counter_sum[j].byteCount +=
+ action_counter_table[i][j].byteCount;
+ }
+ }
+ }
+
+ for (j = 0; j < action_array_max; j++) {
+ if (action_array_active[j].action_bitmap & acl_action_count)
+ printf("Action ID: %02u, packetCount: %" PRIu64
+ ", byteCount: %" PRIu64 "\n", j,
+ action_counter_sum[j].packetCount,
+ action_counter_sum[j].byteCount);
+ }
+}
+
+cmdline_parse_token_string_t cmd_acl_stats_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_stats_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_acl_stats_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_stats_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_stats_stats_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_stats_result,
+ stats_string, "stats");
+
+cmdline_parse_inst_t cmd_acl_stats = {
+ .f = cmd_acl_stats_parsed,
+ .data = NULL,
+ .help_str = "ACL stats",
+ .tokens = {
+ (void *)&cmd_acl_stats_p_string,
+ (void *)&cmd_acl_stats_acl_string,
+ (void *)&cmd_acl_stats_stats_string,
+ NULL,
+ },
+};
+
+/*
+ * p acl clearstats
+ */
+
+/**
+ * A structure defining the ACL clear stats command.
+ */
+struct cmd_acl_clearstats_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t clearstats_string;
+};
+
+/**
+ * Clear ACL and Connection Tracker stats.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_clearstats_parsed(__attribute__ ((unused))
+ void *parsed_result,
+ __attribute__ ((unused))
+ struct cmdline *cl,
+ __attribute__ ((unused))
+ void *data)
+{
+ int i;
+
+ for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) {
+ rte_acl_counter_table[i].tpkts_processed = 0;
+ rte_acl_counter_table[i].bytes_processed = 0;
+ rte_acl_counter_table[i].pkts_drop = 0;
+ rte_acl_counter_table[i].pkts_received = 0;
+ rte_acl_counter_table[i].pkts_drop_ttl = 0;
+ rte_acl_counter_table[i].pkts_drop_bad_size = 0;
+ rte_acl_counter_table[i].pkts_drop_fragmented = 0;
+ rte_acl_counter_table[i].pkts_drop_without_arp_entry = 0;
+ rte_acl_counter_table[i].ct_counters->pkts_forwarded = 0;
+ rte_acl_counter_table[i].ct_counters->pkts_drop = 0;
+ }
+
+ memset(&action_counter_table, 0, sizeof(action_counter_table));
+
+}
+
+cmdline_parse_token_string_t cmd_acl_clearstats_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearstats_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_acl_clearstats_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearstats_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_clearstats_clearstats_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearstats_result,
+ clearstats_string, "clearstats");
+
+cmdline_parse_inst_t cmd_acl_clearstats = {
+ .f = cmd_acl_clearstats_parsed,
+ .data = NULL,
+ .help_str = "ACL clearstats",
+ .tokens = {
+ (void *)&cmd_acl_clearstats_p_string,
+ (void *)&cmd_acl_clearstats_acl_string,
+ (void *)&cmd_acl_clearstats_clearstats_string,
+ NULL,
+ },
+};
+
+/*
+ * p acl dbg
+ */
+
+/**
+ * A structure defining the ACL debug command.
+ */
+struct cmd_acl_dbg_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t dbg_string;
+ uint8_t dbg;
+};
+
+/**
+ * Parse and handle ACL debug command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_dbg_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_dbg_result *params = parsed_result;
+ struct app_params *app = data;
+
+ if (params->dbg == 0) {
+ printf("DBG turned OFF\n");
+ ACL_DEBUG = 0;
+ } else if (params->dbg == 1) {
+ printf("DBG turned ON\n");
+ ACL_DEBUG = 1;
+ } else if (params->dbg == 2) {
+ printf("ACL IPV4 enabled\n");
+ printf("ACL IPV6 enabled\n");
+ acl_ipv4_enabled = 1;
+ acl_ipv6_enabled = 1;
+ } else if (params->dbg == 3) {
+ printf("ACL IPV4 enabled\n");
+ printf("ACL IPV6 disabled\n");
+ acl_ipv4_enabled = 1;
+ acl_ipv6_enabled = 0;
+ } else if (params->dbg == 4) {
+ printf("ACL IPV4 disabled\n");
+ printf("ACL IPV6 enabled\n");
+ acl_ipv4_enabled = 0;
+ acl_ipv6_enabled = 1;
+ } else if (params->dbg == 5) {
+ printf("ACL Version: 3.03\n");
+ } else
+ printf("Invalid DBG setting\n");
+}
+
+cmdline_parse_token_string_t cmd_acl_dbg_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_dbg_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_acl_dbg_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_dbg_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_dbg_dbg_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_dbg_result,
+ dbg_string, "dbg");
+
+cmdline_parse_token_num_t cmd_acl_dbg_dbg =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_dbg_result, dbg,
+ UINT8);
+
+cmdline_parse_inst_t cmd_acl_dbg = {
+ .f = cmd_acl_dbg_parsed,
+ .data = NULL,
+ .help_str = "ACL dbg",
+ .tokens = {
+ (void *)&cmd_acl_dbg_p_string,
+ (void *)&cmd_acl_dbg_acl_string,
+ (void *)&cmd_acl_dbg_dbg_string,
+ (void *)&cmd_acl_dbg_dbg,
+ NULL,
+ },
+};
+
+/*
+ * p acl clearrules
+ */
+
+/**
+ * A structure defining the ACL clear rules command.
+ */
+struct cmd_acl_clearrules_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t clearrules_string;
+};
+
+/**
+ * Parse clear rule command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_clearrules_parsed(__attribute__ ((unused))
+ void *parsed_result,
+ __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct app_params *app = data;
+ int status;
+
+ status = app_pipeline_acl_clearrules(app);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_acl_clearrules_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearrules_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_acl_clearrules_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearrules_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_clearrules_clearrules_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_clearrules_result,
+ clearrules_string, "clearrules");
+
+cmdline_parse_inst_t cmd_acl_clearrules = {
+ .f = cmd_acl_clearrules_parsed,
+ .data = NULL,
+ .help_str = "ACL clearrules",
+ .tokens = {
+ (void *)&cmd_acl_clearrules_p_string,
+ (void *)&cmd_acl_clearrules_acl_string,
+ (void *)&cmd_acl_clearrules_clearrules_string,
+ NULL,
+ },
+};
+
+/*
+ * p acl ls
+ */
+
+/**
+ * A structure defining the ACL ls CLI command result.
+ */
+struct cmd_acl_ls_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t ls_string;
+ uint32_t table_instance;
+};
+
+/**
+ * Parse ACL ls command to display rules to the console.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_ls_parsed(__attribute__ ((unused))
+ void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct app_params *app = data;
+ struct cmd_acl_ls_result *params = parsed_result;
+
+ app_pipeline_acl_ls(app, params->table_instance);
+}
+
+cmdline_parse_token_string_t cmd_acl_ls_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_ls_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_acl_ls_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_ls_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_ls_ls_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_ls_result, ls_string,
+ "ls");
+
+cmdline_parse_token_num_t cmd_acl_ls_table_instance =
+TOKEN_NUM_INITIALIZER(struct cmd_acl_ls_result, table_instance,
+ UINT32);
+
+cmdline_parse_inst_t cmd_acl_ls = {
+ .f = cmd_acl_ls_parsed,
+ .data = NULL,
+ .help_str = "ACL rule list",
+ .tokens = {
+ (void *)&cmd_acl_ls_p_string,
+ (void *)&cmd_acl_ls_acl_string,
+ (void *)&cmd_acl_ls_ls_string,
+ (void *)&cmd_acl_ls_table_instance,
+ NULL,
+ },
+};
+
+/*
+ * p acl applyruleset
+ */
+
+/**
+ * A structure defining the ACL apply ruleset command.
+ */
+struct cmd_acl_applyruleset_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t applyruleset_string;
+};
+
+/**
+ * Parse ACL Apply Ruleset Command.
+ * Switchover active and standby tables.
+ * Sync newly standby tables to match updated data.
+ * Both ACL rule and ACL action tables updated.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_acl_applyruleset_parsed(__attribute__ ((unused))
+ void *parsed_result,
+ __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct app_params *app = data;
+ void *temp_ptr;
+ uint32_t *temp_count_ptr;
+ struct pipeline_action_key *action_array_temp_ptr;
+ int status;
+
+ printf("ACL Apply Ruleset\n");
+
+ /* Switchover Active and Standby TRIE rule tables */
+ temp_ptr = acl_rule_table_ipv4_active;
+ acl_rule_table_ipv4_active = acl_rule_table_ipv4_standby;
+ acl_rule_table_ipv4_standby = temp_ptr;
+ temp_ptr = acl_rule_table_ipv6_active;
+ acl_rule_table_ipv6_active = acl_rule_table_ipv6_standby;
+ acl_rule_table_ipv6_standby = temp_ptr;
+
+ /* Switchover tailq tables */
+ acl_tailq_rules_temp_ptr = acl_tailq_rules_ipv4_active;
+ acl_tailq_rules_ipv4_active = acl_tailq_rules_ipv4_standby;
+ acl_tailq_rules_ipv4_standby = acl_tailq_rules_temp_ptr;
+ acl_tailq_rules_temp_ptr = acl_tailq_rules_ipv6_active;
+ acl_tailq_rules_ipv6_active = acl_tailq_rules_ipv6_standby;
+ acl_tailq_rules_ipv6_standby = acl_tailq_rules_temp_ptr;
+ temp_count_ptr = acl_n_tailq_rules_ipv4_active;
+ acl_n_tailq_rules_ipv4_active = acl_n_tailq_rules_ipv4_standby;
+ acl_n_tailq_rules_ipv4_standby = temp_count_ptr;
+ temp_count_ptr = acl_n_tailq_rules_ipv6_active;
+ acl_n_tailq_rules_ipv6_active = acl_n_tailq_rules_ipv6_standby;
+ acl_n_tailq_rules_ipv6_standby = temp_count_ptr;
+
+ /* Switchover Active and Standby action table */
+ action_array_temp_ptr = action_array_active;
+ action_array_active = action_array_standby;
+ action_array_standby = action_array_temp_ptr;
+ /* Update Standby action table with all changes */
+ memcpy(action_array_standby, action_array_active, action_array_size);
+
+ /* Update Standby Rule Tables with all changes */
+ while (!TAILQ_EMPTY(&acl_commands)) {
+ struct app_pipeline_acl_rule *command;
+
+ command = TAILQ_FIRST(&acl_commands);
+ TAILQ_REMOVE(&acl_commands, command, node);
+
+ if (command->command == acl_add_command) {
+ status = app_pipeline_acl_add_rule(app,
+ &command->key,
+ command->priority,
+ command->port_id,
+ command->action_id);
+ } else
+ status =
+ app_pipeline_acl_delete_rule(app, &command->key);
+
+ if (status != 0) {
+ printf("Command applyruleset add rule failed\n");
+ rte_free(command);
+ return;
+ }
+
+ rte_free(command);
+ }
+}
+
+cmdline_parse_token_string_t cmd_acl_applyruleset_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_applyruleset_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_acl_applyruleset_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_applyruleset_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_applyruleset_applyruleset_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_applyruleset_result,
+ applyruleset_string,
+ "applyruleset");
+
+cmdline_parse_inst_t cmd_acl_applyruleset = {
+ .f = cmd_acl_applyruleset_parsed,
+ .data = NULL,
+ .help_str = "ACL applyruleset",
+ .tokens = {
+ (void *)&cmd_acl_applyruleset_p_string,
+ (void *)&cmd_acl_applyruleset_acl_string,
+ (void *)&cmd_acl_applyruleset_applyruleset_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add accept
+ */
+
+/**
+ * A structure defining the add accept action command.
+ */
+struct cmd_action_add_accept_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t accept_string;
+};
+
+/**
+ * Parse Accept Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_accept_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_accept_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_packet_accept;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_accept_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_accept_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_accept_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_accept_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_accept_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_accept_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_accept_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_accept_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_accept_accept_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_accept_result,
+ accept_string, "accept");
+
+cmdline_parse_inst_t cmd_action_add_accept = {
+ .f = cmd_action_add_accept_parsed,
+ .data = NULL,
+ .help_str = "ACL action add accept",
+ .tokens = {
+ (void *)&cmd_action_add_accept_p_string,
+ (void *)&cmd_action_add_accept_action_string,
+ (void *)&cmd_action_add_accept_add_string,
+ (void *)&cmd_action_add_accept_action_id,
+ (void *)&cmd_action_add_accept_accept_string,
+ NULL,
+ },
+};
+
+/*
+ * p action del accept
+ */
+
+/**
+ * A structure defining the delete accept action command.
+ */
+struct cmd_action_del_accept_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t accept_string;
+};
+
+/**
+ * Parse Accept Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_accept_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_accept_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_packet_accept;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_accept_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_accept_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_accept_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_accept_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_accept_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_accept_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_accept_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_accept_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_accept_accept_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_accept_result,
+ accept_string, "accept");
+
+cmdline_parse_inst_t cmd_action_del_accept = {
+ .f = cmd_action_del_accept_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete accept",
+ .tokens = {
+ (void *)&cmd_action_del_accept_p_string,
+ (void *)&cmd_action_del_accept_action_string,
+ (void *)&cmd_action_del_accept_del_string,
+ (void *)&cmd_action_del_accept_action_id,
+ (void *)&cmd_action_del_accept_accept_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add drop
+ */
+
+/**
+ * A structure defining the add drop action command.
+ */
+struct cmd_action_add_drop_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t drop_string;
+};
+
+/**
+ * Parse Drop Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_drop_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_drop_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_packet_drop;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_drop_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_drop_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_drop_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_drop_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_drop_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_drop_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_drop_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_drop_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_drop_drop_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_drop_result,
+ drop_string, "drop");
+
+cmdline_parse_inst_t cmd_action_add_drop = {
+ .f = cmd_action_add_drop_parsed,
+ .data = NULL,
+ .help_str = "ACL action add drop",
+ .tokens = {
+ (void *)&cmd_action_add_drop_p_string,
+ (void *)&cmd_action_add_drop_action_string,
+ (void *)&cmd_action_add_drop_add_string,
+ (void *)&cmd_action_add_drop_action_id,
+ (void *)&cmd_action_add_drop_drop_string,
+ NULL,
+ },
+};
+
+/*
+ * p action del drop
+ */
+
+/**
+ * A structure defining the delete drop action command.
+ */
+struct cmd_action_del_drop_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t drop_string;
+};
+
+/**
+ * Parse Drop Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_drop_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_drop_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_packet_drop;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_drop_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_drop_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_drop_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_drop_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_drop_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_drop_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_drop_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_drop_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_drop_drop_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_drop_result,
+ drop_string, "drop");
+
+cmdline_parse_inst_t cmd_action_del_drop = {
+ .f = cmd_action_del_drop_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete drop",
+ .tokens = {
+ (void *)&cmd_action_del_drop_p_string,
+ (void *)&cmd_action_del_drop_action_string,
+ (void *)&cmd_action_del_drop_del_string,
+ (void *)&cmd_action_del_drop_action_id,
+ (void *)&cmd_action_del_drop_drop_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add fwd
+ */
+
+/**
+ * A structure defining the add forward action command.
+ */
+struct cmd_action_add_fwd_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t fwd_string;
+ int32_t port_id;
+};
+
+/**
+ * Parse Forward Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_fwd_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_fwd_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_fwd;
+ key.fwd_port = params->port_id;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_fwd_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_fwd_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_fwd_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_fwd_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_fwd_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_fwd_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_fwd_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_fwd_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_fwd_fwd_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_fwd_result,
+ fwd_string, "fwd");
+
+cmdline_parse_token_num_t cmd_action_add_fwd_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_fwd_result, port_id,
+ UINT32);
+
+cmdline_parse_inst_t cmd_action_add_fwd = {
+ .f = cmd_action_add_fwd_parsed,
+ .data = NULL,
+ .help_str = "ACL action add fwd",
+ .tokens = {
+ (void *)&cmd_action_add_fwd_p_string,
+ (void *)&cmd_action_add_fwd_action_string,
+ (void *)&cmd_action_add_fwd_add_string,
+ (void *)&cmd_action_add_fwd_action_id,
+ (void *)&cmd_action_add_fwd_fwd_string,
+ (void *)&cmd_action_add_fwd_port_id,
+ NULL,
+ },
+};
+
+/*
+ * p action del fwd
+ */
+
+/**
+ * A structure defining the delete forward action command.
+ */
+struct cmd_action_del_fwd_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t fwd_string;
+};
+
+/**
+ * Parse Forward Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_fwd_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_fwd_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_fwd;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_fwd_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_fwd_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_fwd_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_fwd_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_fwd_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_fwd_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_fwd_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_fwd_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_fwd_fwd_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_fwd_result,
+ fwd_string, "fwd");
+
+cmdline_parse_inst_t cmd_action_del_fwd = {
+ .f = cmd_action_del_fwd_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete fwd",
+ .tokens = {
+ (void *)&cmd_action_del_fwd_p_string,
+ (void *)&cmd_action_del_fwd_action_string,
+ (void *)&cmd_action_del_fwd_del_string,
+ (void *)&cmd_action_del_fwd_action_id,
+ (void *)&cmd_action_del_fwd_fwd_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add nat
+ */
+
+/**
+ * A structure defining the add NAT action command.
+ */
+struct cmd_action_add_nat_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t nat_string;
+ int32_t port_id;
+};
+
+/**
+ * Parse NAT Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_nat_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_nat_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_nat;
+ key.nat_port = params->port_id;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_nat_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_nat_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_nat_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_nat_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_nat_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_nat_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_nat_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_nat_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_nat_nat_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_nat_result,
+ nat_string, "nat");
+
+cmdline_parse_token_num_t cmd_action_add_nat_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_nat_result, port_id,
+ UINT32);
+
+cmdline_parse_inst_t cmd_action_add_nat = {
+ .f = cmd_action_add_nat_parsed,
+ .data = NULL,
+ .help_str = "ACL action add nat",
+ .tokens = {
+ (void *)&cmd_action_add_nat_p_string,
+ (void *)&cmd_action_add_nat_action_string,
+ (void *)&cmd_action_add_nat_add_string,
+ (void *)&cmd_action_add_nat_action_id,
+ (void *)&cmd_action_add_nat_nat_string,
+ (void *)&cmd_action_add_nat_port_id,
+ NULL,
+ },
+};
+
+/*
+ * p action del nat
+ */
+
+/**
+ * A structure defining the delete NAT action command.
+ */
+struct cmd_action_del_nat_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t nat_string;
+};
+
+/**
+ * Parse NAT Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_nat_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_nat_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_nat;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_nat_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_nat_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_nat_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_nat_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_nat_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_nat_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_nat_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_nat_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_nat_nat_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_nat_result,
+ nat_string, "nat");
+
+cmdline_parse_inst_t cmd_action_del_nat = {
+ .f = cmd_action_del_nat_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete nat",
+ .tokens = {
+ (void *)&cmd_action_del_nat_p_string,
+ (void *)&cmd_action_del_nat_action_string,
+ (void *)&cmd_action_del_nat_del_string,
+ (void *)&cmd_action_del_nat_action_id,
+ (void *)&cmd_action_del_nat_nat_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add count
+ */
+
+/**
+ * A structure defining the add count action command.
+ */
+struct cmd_action_add_count_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t count_string;
+};
+
+/**
+ * Parse Count Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_count_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_count_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_count;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_count_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_count_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_count_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_count_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_count_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_count_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_count_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_count_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_count_count_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_count_result,
+ count_string, "count");
+
+cmdline_parse_inst_t cmd_action_add_count = {
+ .f = cmd_action_add_count_parsed,
+ .data = NULL,
+ .help_str = "ACL action add count",
+ .tokens = {
+ (void *)&cmd_action_add_count_p_string,
+ (void *)&cmd_action_add_count_action_string,
+ (void *)&cmd_action_add_count_add_string,
+ (void *)&cmd_action_add_count_action_id,
+ (void *)&cmd_action_add_count_count_string,
+ NULL,
+ },
+};
+
+/*
+ * p action del count
+ */
+
+/**
+ * A structure defining the delete count action command.
+ */
+struct cmd_action_del_count_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t count_string;
+};
+
+/**
+ * Parse Count Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_count_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_count_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_count;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_count_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_count_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_count_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_count_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_count_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_count_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_count_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_count_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_count_count_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_count_result,
+ count_string, "count");
+
+cmdline_parse_inst_t cmd_action_del_count = {
+ .f = cmd_action_del_count_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete count",
+ .tokens = {
+ (void *)&cmd_action_del_count_p_string,
+ (void *)&cmd_action_del_count_action_string,
+ (void *)&cmd_action_del_count_del_string,
+ (void *)&cmd_action_del_count_action_id,
+ (void *)&cmd_action_del_count_count_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add dscp
+ */
+
+/**
+ * A structure defining the add DSCP action command.
+ */
+struct cmd_action_add_dscp_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t dscp_string;
+ uint8_t dscp_priority;
+};
+
+/**
+ * Parse DSCP Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_dscp_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_dscp_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_dscp;
+ key.dscp_priority = params->dscp_priority;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_dscp_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_dscp_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_dscp_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_dscp_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_dscp_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_dscp_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_dscp_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_dscp_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_dscp_dscp_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_dscp_result,
+ dscp_string, "dscp");
+
+cmdline_parse_token_num_t cmd_action_add_dscp_dscp_priority =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_dscp_result, dscp_priority,
+ UINT8);
+
+cmdline_parse_inst_t cmd_action_add_dscp = {
+ .f = cmd_action_add_dscp_parsed,
+ .data = NULL,
+ .help_str = "ACL action add dscp",
+ .tokens = {
+ (void *)&cmd_action_add_dscp_p_string,
+ (void *)&cmd_action_add_dscp_action_string,
+ (void *)&cmd_action_add_dscp_add_string,
+ (void *)&cmd_action_add_dscp_action_id,
+ (void *)&cmd_action_add_dscp_dscp_string,
+ (void *)&cmd_action_add_dscp_dscp_priority,
+ NULL,
+ },
+};
+
+/*
+ * p action del dscp
+ */
+
+/**
+ * A structure defining the delete DSCP action command.
+ */
+struct cmd_action_del_dscp_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t dscp_string;
+};
+
+/**
+ * Parse DSCP Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_dscp_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_dscp_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_dscp;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_dscp_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_dscp_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_dscp_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_dscp_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_dscp_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_dscp_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_dscp_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_dscp_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_dscp_dscp_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_dscp_result,
+ dscp_string, "dscp");
+
+cmdline_parse_inst_t cmd_action_del_dscp = {
+ .f = cmd_action_del_dscp_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete dscp",
+ .tokens = {
+ (void *)&cmd_action_del_dscp_p_string,
+ (void *)&cmd_action_del_dscp_action_string,
+ (void *)&cmd_action_del_dscp_del_string,
+ (void *)&cmd_action_del_dscp_action_id,
+ (void *)&cmd_action_del_dscp_dscp_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add conntrack
+ */
+
+/**
+ * A structure defining the add Connection Tracking action command.
+ */
+struct cmd_action_add_conntrack_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t conntrack_string;
+};
+
+/**
+ * Parse Connection Tracking Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_conntrack_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_conntrack_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_conntrack;
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_conntrack_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_conntrack_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_conntrack_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_conntrack_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_conntrack_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_conntrack_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_conntrack_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_conntrack_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_conntrack_conntrack_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_conntrack_result,
+ conntrack_string, "conntrack");
+
+cmdline_parse_inst_t cmd_action_add_conntrack = {
+ .f = cmd_action_add_conntrack_parsed,
+ .data = NULL,
+ .help_str = "ACL action add conntrack",
+ .tokens = {
+ (void *)&cmd_action_add_conntrack_p_string,
+ (void *)&cmd_action_add_conntrack_action_string,
+ (void *)&cmd_action_add_conntrack_add_string,
+ (void *)&cmd_action_add_conntrack_action_id,
+ (void *)&cmd_action_add_conntrack_conntrack_string,
+ NULL,
+ },
+};
+
+/*
+ * p action del conntrack
+ */
+
+/**
+ * A structure defining the delete Connection Tracking action command.
+ */
+struct cmd_action_del_conntrack_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t conntrack_string;
+};
+
+/**
+ * Parse Connection Tracking Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_conntrack_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_conntrack_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_conntrack;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_conntrack_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_conntrack_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_conntrack_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_conntrack_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_conntrack_del_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_conntrack_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_conntrack_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_conntrack_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_conntrack_conntrack_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_conntrack_result,
+ conntrack_string, "conntrack");
+
+cmdline_parse_inst_t cmd_action_del_conntrack = {
+ .f = cmd_action_del_conntrack_parsed,
+ .data = NULL,
+ .help_str = "ACL action delete conntrack",
+ .tokens = {
+ (void *)&cmd_action_del_conntrack_p_string,
+ (void *)&cmd_action_del_conntrack_action_string,
+ (void *)&cmd_action_del_conntrack_del_string,
+ (void *)&cmd_action_del_conntrack_action_id,
+ (void *)&cmd_action_del_conntrack_conntrack_string,
+ NULL,
+ },
+};
+
+/*
+ * p action add connexist
+ */
+
+/**
+ * A structure defining the add Connection Exist action command.
+ */
+struct cmd_action_add_connexist_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t add_string;
+ int32_t action_id;
+ cmdline_fixed_string_t connexist_string;
+ cmdline_fixed_string_t private_public_string;
+};
+
+/**
+ * Parse Connection Exist Action Add Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_add_connexist_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_add_connexist_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ if (ACL_DEBUG)
+ printf("public_private: %s\n", params->private_public_string);
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_connexist;
+ if (strcmp(params->private_public_string, "prvpub") == 0)
+ key.private_public = acl_private_public;
+ else if (strcmp(params->private_public_string, "pubprv") == 0)
+ key.private_public = acl_public_private;
+ else {
+ printf("Command failed - Invalid string: %s\n",
+ params->private_public_string);
+ return;
+ }
+
+ status = app_pipeline_action_add(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_add_connexist_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_connexist_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_add_connexist_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_connexist_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_add_connexist_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_connexist_result,
+ add_string, "add");
+
+cmdline_parse_token_num_t cmd_action_add_connexist_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_add_connexist_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_add_connexist_connexist_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_connexist_result,
+ connexist_string, "connexist");
+
+cmdline_parse_token_string_t cmd_action_add_connexist_private_public =
+TOKEN_STRING_INITIALIZER(struct cmd_action_add_connexist_result,
+ private_public_string,
+ NULL);
+
+cmdline_parse_inst_t cmd_action_add_connexist = {
+ .f = cmd_action_add_connexist_parsed,
+ .data = NULL,
+ .help_str = "ACL action add connexist",
+ .tokens = {
+ (void *)&cmd_action_add_connexist_p_string,
+ (void *)&cmd_action_add_connexist_action_string,
+ (void *)&cmd_action_add_connexist_add_string,
+ (void *)&cmd_action_add_connexist_action_id,
+ (void *)&cmd_action_add_connexist_connexist_string,
+ (void *)&cmd_action_add_connexist_private_public,
+ NULL,
+ },
+};
+
+/*
+ * p action del connexist
+ */
+
+/**
+ * A structure defining the delete Connection Exist action command.
+ */
+struct cmd_action_del_connexist_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t del_string;
+ int32_t action_id;
+ cmdline_fixed_string_t connexist_string;
+};
+
+/**
+ * Parse Connection Exist Action Delete Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_action_del_connexist_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_del_connexist_result *params = parsed_result;
+ struct app_params *app = data;
+ struct pipeline_action_key key;
+ int status;
+
+ key.action_id = params->action_id;
+ key.action_bitmap = acl_action_connexist;
+
+ status = app_pipeline_action_delete(app, &key);
+
+ if (status != 0) {
+ printf("Command failed\n");
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_del_connexist_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_connexist_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_del_connexist_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_connexist_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_del_connexist_add_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_connexist_result,
+ del_string, "del");
+
+cmdline_parse_token_num_t cmd_action_del_connexist_action_id =
+TOKEN_NUM_INITIALIZER(struct cmd_action_del_connexist_result, action_id,
+ UINT32);
+
+cmdline_parse_token_string_t cmd_action_del_connexist_connexist_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_del_connexist_result,
+ connexist_string, "connexist");
+
+cmdline_parse_inst_t cmd_action_del_connexist = {
+ .f = cmd_action_del_connexist_parsed,
+ .data = NULL,
+ .help_str = "ACL action del connexist",
+ .tokens = {
+ (void *)&cmd_action_del_connexist_p_string,
+ (void *)&cmd_action_del_connexist_action_string,
+ (void *)&cmd_action_del_connexist_add_string,
+ (void *)&cmd_action_del_connexist_action_id,
+ (void *)&cmd_action_del_connexist_connexist_string,
+ NULL,
+ },
+};
+
+/*
+ * p action ls
+ */
+
+/**
+ * A structure defining the action ls command.
+ */
+struct cmd_action_ls_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t action_string;
+ cmdline_fixed_string_t ls_string;
+ uint32_t table_instance;
+};
+
+/**
+ * Parse Action LS Command.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void cmd_action_ls_parsed(void *parsed_result, __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_action_ls_result *params = parsed_result;
+ struct app_params *app = data;
+ uint32_t action_bitmap, i, j;
+ uint8_t action_found = 0;
+ struct action_counter_block action_counter_sum;
+
+ if (params->table_instance == active_rule_table) {
+ printf("Active Action Table:\n");
+ printf("Action ID Action\n");
+ printf("========= ======\n");
+
+ for (i = 0; i < action_array_max; i++) {
+ action_bitmap = action_array_active[i].action_bitmap;
+ if (action_bitmap != 0) {
+ action_found = 1;
+ if (action_bitmap & acl_action_packet_accept)
+ printf(" %04u Accept\n", i);
+ if (action_bitmap & acl_action_packet_drop)
+ printf(" %04u Drop\n", i);
+ if (action_bitmap & acl_action_nat)
+ printf
+ (" %04u NAT "
+ "NAT Port: %u\n",
+ i,
+ action_array_active[i].nat_port);
+ if (action_bitmap & acl_action_fwd)
+ printf
+ (" %04u FWD "
+ "FWD Port: %u\n",
+ i,
+ action_array_active[i].fwd_port);
+ if (action_bitmap & acl_action_count) {
+ action_counter_sum.packetCount = 0;
+ action_counter_sum.byteCount = 0;
+ for (j = 0;
+ j <=
+ rte_ACL_hi_counter_block_in_use;
+ j++) {
+ action_counter_sum.packetCount
+ += action_counter_table[j]
+ [i].packetCount;
+ action_counter_sum.byteCount +=
+ action_counter_table[j]
+ [i].byteCount;
+ }
+ printf
+ (" %04u "
+ "Count Packet Count: %"
+ PRIu64 " Byte Count: %" PRIu64
+ "\n", i,
+ action_counter_sum.packetCount,
+ action_counter_sum.byteCount);
+ }
+ if (action_bitmap & acl_action_conntrack)
+ printf(" %04u Conntrack\n", i);
+ if (action_bitmap & acl_action_connexist) {
+ printf(" %04u Connexist", i);
+ if (action_array_active
+ [i].private_public ==
+ acl_private_public)
+ printf(" prvpub\n");
+ else
+ printf(" pubprv\n");
+ }
+ if (action_bitmap & acl_action_dscp)
+ printf
+ (" %04u DSCP "
+ "DSCP Priority: %u\n",
+ i,
+ action_array_active
+ [i].dscp_priority);
+ }
+ }
+
+ if (!action_found)
+ printf("None\n");
+
+ } else {
+ action_found = 0;
+ printf("Standby Action Table:\n");
+ printf("Action ID Action\n");
+ printf("========= ======\n");
+
+ for (i = 0; i < action_array_max; i++) {
+ action_bitmap = action_array_standby[i].action_bitmap;
+ if (action_bitmap != 0) {
+ action_found = 1;
+ if (action_bitmap & acl_action_packet_accept)
+ printf(" %04u Accept\n", i);
+ if (action_bitmap & acl_action_packet_drop)
+ printf(" %04u Drop\n", i);
+ if (action_bitmap & acl_action_nat)
+ printf
+ (" %04u NAT "
+ "NAT Port: %u\n",
+ i,
+ action_array_standby[i].nat_port);
+ if (action_bitmap & acl_action_fwd)
+ printf
+ (" %04u FWD "
+ "FWD Port: %u\n",
+ i,
+ action_array_standby[i].fwd_port);
+ if (action_bitmap & acl_action_count)
+ printf(" %04u Count\n", i);
+ if (action_bitmap & acl_action_conntrack)
+ printf(" %04u Conntrack\n", i);
+ if (action_bitmap & acl_action_connexist) {
+ printf(" %04u Connexist", i);
+ if (action_array_standby
+ [i].private_public ==
+ acl_private_public)
+ printf(" prvpub\n");
+ else
+ printf(" pubprv\n");
+ }
+ if (action_bitmap & acl_action_dscp)
+ printf
+ (" %04u DSCP "
+ "DSCP Priority: %u\n",
+ i,
+ action_array_standby
+ [i].dscp_priority);
+ }
+ }
+
+ if (!action_found)
+ printf("None\n");
+ }
+}
+
+cmdline_parse_token_string_t cmd_action_ls_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_ls_result, p_string,
+ "p");
+
+cmdline_parse_token_string_t cmd_action_ls_action_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_ls_result,
+ action_string, "action");
+
+cmdline_parse_token_string_t cmd_action_ls_ls_string =
+TOKEN_STRING_INITIALIZER(struct cmd_action_ls_result, ls_string,
+ "ls");
+
+cmdline_parse_token_num_t cmd_action_ls_table_instance =
+TOKEN_NUM_INITIALIZER(struct cmd_action_ls_result, table_instance,
+ UINT32);
+
+cmdline_parse_inst_t cmd_action_ls = {
+ .f = cmd_action_ls_parsed,
+ .data = NULL,
+ .help_str = "ACL action list",
+ .tokens = {
+ (void *)&cmd_action_ls_p_string,
+ (void *)&cmd_action_ls_action_string,
+ (void *)&cmd_action_ls_ls_string,
+ (void *)&cmd_action_ls_table_instance,
+ NULL,
+ },
+};
+
+/*
+ * p acl onesectimer start/stop
+ */
+
+/**
+ * A structure defining the ACL Dump Counter start/stop command.
+ */
+struct cmd_acl_per_sec_ctr_dump_result {
+ cmdline_fixed_string_t p_string;
+ cmdline_fixed_string_t acl_string;
+ cmdline_fixed_string_t per_sec_ctr_dump_string;
+ cmdline_fixed_string_t stop_string;
+};
+
+/**
+ * Parse Dump Counter Start Command.
+ * Start timer to display stats to console at regular intervals.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_acl_per_sec_ctr_dump_start_parsed(void *parsed_result,
+ __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_per_sec_ctr_dump_result *params = parsed_result;
+ struct app_params *app = data;
+
+ rte_acl_reset_running_averages();
+ uint32_t core_id = rte_lcore_id();/* execute timeout on current core */
+ int success = rte_timer_reset(&rte_acl_one_second_timer,
+ rte_acl_ticks_in_one_second, PERIODICAL,
+ core_id,
+ rte_dump_acl_counters_from_master, NULL);
+}
+
+/**
+ * Parse Dump Counter Stop Command.
+ * Stop timer that was started to display stats.
+ *
+ * @param parsed_result
+ * A pointer to CLI command parsed result.
+ * @param cl
+ * A pointer to command line context.
+ * @param data
+ * A pointer to command specific data
+ *
+ */
+static void
+cmd_acl_per_sec_ctr_dump_stop_parsed(void *parsed_result,
+ __attribute__ ((unused))
+ struct cmdline *cl, void *data)
+{
+ struct cmd_acl_per_sec_ctr_dump_result *params = parsed_result;
+ struct app_params *app = data;
+
+ rte_timer_stop(&rte_acl_one_second_timer);
+}
+
+cmdline_parse_token_string_t cmd_acl_per_sec_ctr_dump_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_per_sec_ctr_dump_result,
+ p_string, "p");
+
+cmdline_parse_token_string_t cmd_acl_per_sec_ctr_dump_acl_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_per_sec_ctr_dump_result,
+ acl_string, "acl");
+
+cmdline_parse_token_string_t cmd_acl_per_sec_ctr_dump_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_per_sec_ctr_dump_result,
+ per_sec_ctr_dump_string, "counterdump");
+
+cmdline_parse_token_string_t cmd_acl_stop_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_per_sec_ctr_dump_result,
+ stop_string, "stop");
+
+cmdline_parse_token_string_t cmd_acl_start_string =
+TOKEN_STRING_INITIALIZER(struct cmd_acl_per_sec_ctr_dump_result,
+ stop_string, "start");
+
+cmdline_parse_inst_t cmd_acl_per_sec_ctr_dump_stop = {
+ .f = cmd_acl_per_sec_ctr_dump_stop_parsed,
+ .data = NULL,
+ .help_str = "ACL counterdump stop",
+ .tokens = {
+ (void *)&cmd_acl_per_sec_ctr_dump_p_string,
+ (void *)&cmd_acl_per_sec_ctr_dump_acl_string,
+ (void *)&cmd_acl_per_sec_ctr_dump_string,
+ (void *)&cmd_acl_stop_string,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_acl_per_sec_ctr_dump_start = {
+ .f = cmd_acl_per_sec_ctr_dump_start_parsed,
+ .data = NULL,
+ .help_str = "ACL counterdump start",
+ .tokens = {
+ (void *)&cmd_acl_per_sec_ctr_dump_p_string,
+ (void *)&cmd_acl_per_sec_ctr_dump_acl_string,
+ (void *)&cmd_acl_per_sec_ctr_dump_string,
+ (void *)&cmd_acl_start_string,
+ NULL,
+ },
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *) &cmd_acl_add_ip,
+ (cmdline_parse_inst_t *) &cmd_acl_del_ip,
+ (cmdline_parse_inst_t *) &cmd_acl_stats,
+ (cmdline_parse_inst_t *) &cmd_acl_clearstats,
+ (cmdline_parse_inst_t *) &cmd_acl_dbg,
+ (cmdline_parse_inst_t *) &cmd_acl_clearrules,
+ (cmdline_parse_inst_t *) &cmd_loadrules,
+ (cmdline_parse_inst_t *) &cmd_acl_ls,
+ (cmdline_parse_inst_t *) &cmd_action_add_accept,
+ (cmdline_parse_inst_t *) &cmd_action_del_accept,
+ (cmdline_parse_inst_t *) &cmd_action_add_drop,
+ (cmdline_parse_inst_t *) &cmd_action_del_drop,
+ (cmdline_parse_inst_t *) &cmd_action_add_fwd,
+ (cmdline_parse_inst_t *) &cmd_action_del_fwd,
+ (cmdline_parse_inst_t *) &cmd_action_add_nat,
+ (cmdline_parse_inst_t *) &cmd_action_del_nat,
+ (cmdline_parse_inst_t *) &cmd_action_add_count,
+ (cmdline_parse_inst_t *) &cmd_action_del_count,
+ (cmdline_parse_inst_t *) &cmd_action_add_dscp,
+ (cmdline_parse_inst_t *) &cmd_action_del_dscp,
+ (cmdline_parse_inst_t *) &cmd_action_add_conntrack,
+ (cmdline_parse_inst_t *) &cmd_action_del_conntrack,
+ (cmdline_parse_inst_t *) &cmd_action_add_connexist,
+ (cmdline_parse_inst_t *) &cmd_action_del_connexist,
+ (cmdline_parse_inst_t *) &cmd_action_ls,
+ (cmdline_parse_inst_t *) &cmd_acl_applyruleset,
+ (cmdline_parse_inst_t *) &cmd_acl_per_sec_ctr_dump_stop,
+ (cmdline_parse_inst_t *) &cmd_acl_per_sec_ctr_dump_start,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_acl_fe_ops = {
+ .f_init = app_pipeline_acl_init,
+ .f_free = app_pipeline_acl_free,
+ .cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_acl = {
+ .name = "ACL",
+ .be_ops = &pipeline_acl_be_ops,
+ .fe_ops = &pipeline_acl_fe_ops,
+};
diff --git a/VNFs/vACL/pipeline/pipeline_acl.h b/VNFs/vACL/pipeline/pipeline_acl.h
new file mode 100644
index 00000000..80a85cae
--- /dev/null
+++ b/VNFs/vACL/pipeline/pipeline_acl.h
@@ -0,0 +1,144 @@
+/*
+// 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_PIPELINE_ACL_H__
+#define __INCLUDE_PIPELINE_ACL_H__
+
+/**
+ * @file
+ * Pipeline ACL FE.
+ *
+ * Pipeline ACL Front End (FE).
+ * Runs on the Master pipeline, responsible for CLI commands.
+ *
+ */
+
+#include "pipeline.h"
+#include "pipeline_acl_be.h"
+
+/* ACL IPV4 and IPV6 enable flags for debugging (Default both on) */
+extern int acl_ipv4_enabled;
+extern int acl_ipv6_enabled;
+
+/* Number of ACL Rules, default 4 * 1024 */
+extern uint32_t acl_n_rules;
+/* ACL Rule Table TRIE - 2 (Active, Standby Global table per ipv4, ipv6 */
+extern void *acl_rule_table_ipv4_active;
+extern void *acl_rule_table_ipv4_standby;
+extern void *acl_rule_table_ipv6_active;
+extern void *acl_rule_table_ipv6_standby;
+
+#define active_rule_table 0
+#define standby_rule_table 1
+#define acl_add_command 0
+#define acl_delete_command 1
+#define IPV6_32BIT_LENGTH 4
+
+/**
+ * Add ACL rule to the ACL rule table.
+ * Rules are added standby table.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules can be added.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the ACL rule to add.
+ * @param priority
+ * Priority of the ACL rule.
+ * @param port_id
+ * Port ID of the ACL rule.
+ * @param action_id
+ * Action ID of the ACL rule. Defined in Action Table.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_acl_add_rule(struct app_params *app,
+ struct pipeline_acl_key *key,
+ uint32_t priority,
+ uint32_t port_id, uint32_t action_id);
+
+/**
+ * Delete ACL rule from the ACL rule table.
+ * Rules deleted from standby tables.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules can be deleted.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the ACL rule to delete.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_acl_delete_rule(struct app_params *app,
+ struct pipeline_acl_key *key);
+
+/**
+ * Clear all ACL rules from the ACL rule table.
+ * Rules cleared from standby tables.
+ * Applyruleset command will activate the change.
+ * Both IPv4 and IPv6 rules will be cleared.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int app_pipeline_acl_clearrules(struct app_params *app);
+
+/**
+ * Add Action to the Action table.
+ * Actions are added standby table.
+ * Applyruleset command will activate the change.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the Action to add.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_action_add(struct app_params *app,
+ struct pipeline_action_key *key);
+
+/**
+ * Delete Action from the Action table.
+ * Actions are deleted from the standby table.
+ * Applyruleset command will activate the change.
+ *
+ * @param app
+ * A pointer to the ACL pipeline parameters.
+ * @param key
+ * A pointer to the Action to delete.
+ *
+ * @return
+ * 0 on success, negative on error.
+ */
+int
+app_pipeline_action_delete(struct app_params *app,
+ struct pipeline_action_key *key);
+
+extern struct pipeline_type pipeline_acl;
+
+#endif
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,
+};
diff --git a/VNFs/vACL/pipeline/pipeline_acl_be.h b/VNFs/vACL/pipeline/pipeline_acl_be.h
new file mode 100644
index 00000000..8c85d888
--- /dev/null
+++ b/VNFs/vACL/pipeline/pipeline_acl_be.h
@@ -0,0 +1,228 @@
+/*
+// 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_PIPELINE_ACL_BE_H__
+#define __INCLUDE_PIPELINE_ACL_BE_H__
+
+/**
+ * @file
+ * Pipeline ACL BE.
+ *
+ * Pipeline ACL Back End (BE).
+ * Responsible for packet processing.
+ *
+ */
+
+#include "pipeline_common_be.h"
+#include "rte_ct_tcp.h"
+#include "pipeline_arpicmp_be.h"
+
+enum pipeline_acl_key_type {
+ PIPELINE_ACL_IPV4_5TUPLE,
+ PIPELINE_ACL_IPV6_5TUPLE
+};
+
+#define MBUF_HDR_ROOM 256
+#define ETH_HDR_SIZE 14
+#define IP_HDR_SIZE 20
+#define IP_HDR_DSCP_OFST 1
+#define IP_HDR_LENGTH_OFST 2
+#define IP_HDR_PROTOCOL_OFST 9
+#define IP_HDR_DST_ADR_OFST 16
+#define IP_VERSION_4 4
+#define IP_VERSION_6 6
+#define MIX 10
+
+/* IPv6 */
+#define IP_HDR_SIZE_IPV6 40
+#define IP_HDR_DSCP_OFST_IPV6 0
+#define IP_HDR_LENGTH_OFST_IPV6 4
+#define IP_HDR_PROTOCOL_OFST_IPV6 6
+#define IP_HDR_DST_ADR_OFST_IPV6 24
+
+#define IPv4_HDR_VERSION 4
+#define IPv6_HDR_VERSION 6
+#define IP_VERSION_CHECK 4
+
+extern int rte_ACL_hi_counter_block_in_use;
+extern uint8_t ACL_DEBUG;
+
+/**
+ * A structure defining the ACL counter block.
+ * One counter block per ACL Thread
+ */
+struct rte_ACL_counter_block {
+ char name[32];
+ /* as long as a counter doesn't cross cache line, writes are atomic */
+ uint64_t tpkts_processed;
+ uint64_t bytes_processed; /* includes all L3 and higher headers */
+
+ uint64_t pkts_drop;
+ uint64_t pkts_received;
+ uint64_t pkts_drop_ttl;
+ uint64_t pkts_drop_bad_size;
+ uint64_t pkts_drop_fragmented;
+ uint64_t pkts_drop_without_arp_entry;
+
+ struct rte_CT_counter_block *ct_counters;
+
+ uint64_t sum_latencies;
+ /* average latency = sum_latencies / count_latencies */
+ uint32_t count_latencies;
+} __rte_cache_aligned;
+
+#define MAX_ACL_INSTANCES 12/* max number ACL threads, actual usually less */
+
+extern struct rte_ACL_counter_block rte_acl_counter_table[MAX_ACL_INSTANCES]
+ __rte_cache_aligned;
+
+/**
+ * A structure defining the IPv4 5-Tuple for ACL rules.
+ */
+struct pipeline_acl_key_ipv4_5tuple {
+ uint32_t src_ip;
+ uint32_t src_ip_mask;
+ uint32_t dst_ip;
+ uint32_t dst_ip_mask;
+ uint16_t src_port_from;
+ uint16_t src_port_to;
+ uint16_t dst_port_from;
+ uint16_t dst_port_to;
+ uint8_t proto;
+ uint8_t proto_mask;
+};
+
+/**
+ * A structure defining the IPv6 5-Tuple for ACL rules.
+ */
+struct pipeline_acl_key_ipv6_5tuple {
+ uint8_t src_ip[16];
+ uint32_t src_ip_mask;
+ uint8_t dst_ip[16];
+ uint32_t dst_ip_mask;
+ uint16_t src_port_from;
+ uint16_t src_port_to;
+ uint16_t dst_port_from;
+ uint16_t dst_port_to;
+ uint8_t proto;
+ uint8_t proto_mask;
+};
+
+/**
+ * A structure defining the key to store ACL rule.
+ * For both IPv4 and IPv6.
+ */
+struct pipeline_acl_key {
+ enum pipeline_acl_key_type type;
+ union {
+ struct pipeline_acl_key_ipv4_5tuple ipv4_5tuple;
+ struct pipeline_acl_key_ipv6_5tuple ipv6_5tuple;
+ } key;
+};
+
+/**
+ * A structure defining the ACL pipeline table.
+ */
+struct acl_table_entry {
+ struct rte_pipeline_table_entry head;
+ uint32_t action_id;
+};
+
+/* Define ACL actions for bitmap */
+#define acl_action_packet_drop 1
+#define acl_action_packet_accept 2
+#define acl_action_nat 4
+#define acl_action_fwd 8
+#define acl_action_count 16
+#define acl_action_dscp 32
+#define acl_action_conntrack 64
+#define acl_action_connexist 128
+
+#define acl_private_public 0
+#define acl_public_private 1
+
+#define action_array_max 10000
+
+/**
+ * A structure defining the key to store an ACL 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 ACL thread.
+ */
+struct action_counter_block {
+ uint64_t byteCount;
+ uint64_t packetCount;
+} __rte_cache_aligned;
+
+extern struct pipeline_action_key *action_array_a;
+extern struct pipeline_action_key *action_array_b;
+extern struct pipeline_action_key *action_array_active;
+extern struct pipeline_action_key *action_array_standby;
+extern uint32_t action_array_size;
+
+extern struct action_counter_block
+ action_counter_table[MAX_ACL_INSTANCES][action_array_max]
+ __rte_cache_aligned;
+
+enum pipeline_acl_msg_req_type {
+ PIPELINE_ACL_MSG_REQ_DBG = 0,
+ PIPELINE_ACL_MSG_REQS
+};
+
+/**
+ * A structure defining the add ACL rule command response message.
+ */
+struct pipeline_acl_add_msg_rsp {
+ int status;
+ int key_found;
+ void *entry_ptr;
+};
+
+/**
+ * A structure defining the debug command request message.
+ */
+struct pipeline_acl_dbg_msg_req {
+ enum pipeline_msg_req_type type;
+ enum pipeline_acl_msg_req_type subtype;
+
+ /* data */
+ uint8_t dbg;
+};
+
+/**
+ * A structure defining the debug command response message.
+ */
+struct pipeline_acl_dbg_msg_rsp {
+ int status;
+ void *entry_ptr;
+};
+
+extern struct pipeline_be_ops pipeline_acl_be_ops;
+
+extern int rte_ct_initialize_default_timeouts(struct rte_ct_cnxn_tracker
+ *new_cnxn_tracker);
+
+#endif
diff --git a/docs/vACL/INSTALL.rst b/docs/vACL/INSTALL.rst
new file mode 100644
index 00000000..e00c6b24
--- /dev/null
+++ b/docs/vACL/INSTALL.rst
@@ -0,0 +1,176 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International
+.. License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) OPNFV, National Center of Scientific Research "Demokritos" and others.
+
+============================
+vACL - Installation Guide
+============================
+
+vACL Compilation
+===================
+
+After downloading (or doing a git clone) in a directory (samplevnf)
+
+###### Dependencies
+* DPDK 16.04: Downloaded and installed via vnf_build.sh or manually from [here](http://fast.dpdk.org/rel/dpdk-16.04.tar.xz)
+Both the options are available as part of vnf_build.sh below.
+* libpcap-dev
+* libzmq
+* libcurl
+
+###### Environment variables
+
+Apply all the additional patches in 'patches/dpdk_custom_patch/' and build dpdk
+
+::
+ export RTE_SDK=<dpdk 16.04 directory>
+ export RTE_TARGET=x86_64-native-linuxapp-gcc
+
+This is done by vnf_build.sh script.
+
+Auto Build:
+==========
+$ ./tools/vnf_build.sh in samplevnf root folder
+
+Follow the steps in the screen from option [1] --> [8] and select option [7]
+to build the vnfs.
+It will automatically download DPDK 16.04 and any required patches and will setup
+everything and build vACL VNFs.
+
+Following are the options for setup:
+
+::
+
+ ----------------------------------------------------------
+ Step 1: Environment setup.
+ ----------------------------------------------------------
+ [1] Check OS and network connection
+
+ ----------------------------------------------------------
+ Step 2: Download and Install
+ ----------------------------------------------------------
+ [2] Agree to download
+ [3] Download packages
+ [4] Download DPDK zip (optional, use it when option 4 fails)
+ [5] Install DPDK
+ [6] Setup hugepages
+
+ ----------------------------------------------------------
+ Step 3: Build VNF
+ ----------------------------------------------------------
+ [7] Build VNF
+
+ [8] Exit Script
+
+An vACL executable will be created at the following location
+samplevnf/VNFs/vACL/build/vACL
+
+
+Manual Build:
+============
+1. Download DPDK 16.04 from dpdk.org
+ - http://dpdk.org/browse/dpdk/snapshot/dpdk-16.04.zip
+2. unzip dpdk-16.04 and apply dpdk patch
+ - cd dpdk-16.04
+ - patch -p0 < VNF_CORE/patches/dpdk_custom_patch/rte_pipeline.patch
+ - patch -p1 < VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-management.patch
+ - patch -p1 < VNF_CORE/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch
+ - patch -p1 < VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch
+ - patch -p1 < VNF_CORE/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch
+ - build dpdk
+ - make config T=x86_64-native-linuxapp-gcc O=x86_64-native-linuxapp-gcc
+ - cd x86_64-native-linuxapp-gcc
+ - make
+ - Setup huge pages
+ - For 1G/2M hugepage sizes, for example 1G pages, the size must be specified
+ explicitly and can also be optionally set as the default hugepage size for
+ the system. For example, to reserve 8G of hugepage memory in the form of
+ eight 1G pages, the following options should be passed to the kernel:
+ * default_hugepagesz=1G hugepagesz=1G hugepages=8 hugepagesz=2M hugepages=2048
+ - Add this to Go to /etc/default/grub configuration file.
+ - Append "default_hugepagesz=1G hugepagesz=1G hugepages=8 hugepagesz=2M hugepages=2048"
+ to the GRUB_CMDLINE_LINUX entry.
+3. Setup Environment Variable
+ - export RTE_SDK=<samplevnf>/dpdk-16.04
+ - export RTE_TARGET=x86_64-native-linuxapp-gcc
+ - export VNF_CORE=<samplevnf>
+ or using ./toot/setenv.sh
+4. Build vACL VNFs
+ - cd <samplevnf>/VNFs/vACL
+ - make clean
+ - make
+5. The vACL executable will be created at the following location
+ - <samplevnf>/VNFs/vACL/build/vACL
+
+Run
+====
+
+Setup Port to run VNF:
+----------------------
+::
+ 1. cd <samplevnf>/dpdk-16.04
+ 3. ./tool/dpdk_nic_bind.py --status <--- List the network device
+ 2. ./tool/dpdk_nic_bind.py -b igb_uio <PCI Port 0> <PCI Port 1>
+ .. _More details: http://dpdk.org/doc/guides-16.04/linux_gsg/build_dpdk.html#binding-and-unbinding-network-ports-to-from-the-kernel-modules
+
+ Make the necessary changes to the config files to run the vACL VNF
+ eg: ports_mac_list = 00:00:00:30:21:00 00:00:00:30:21:00
+
+ACL
+--------------
+Update the configuration according to system configuration.
+
+::
+ ./build/vACL -p <port mask> -f <config> -s <script> - SW_LoadB
+ ./build/vACL -p <port mask> -f <config> -s <script> -hwlb <num_WT> - HW_LoadB
+
+
+Run IPv4
+----------
+::
+ Software LoadB
+ --------------
+ cd <samplevnf>/VNFs/vACL/
+ ./build/vACL -p 0x3 -f ./config/IPv4_swlb_acl_1LB_1t.cfg -s ./config/ IPv4_swlb_acl.tc
+
+
+ Hardware LoadB
+ --------------
+ cd <samplevnf>/VNFs/vACL/
+ ./build/vACL -p 0x3 -f ./config/IPv4_hwlb_acl_1LB_1t.cfg -s ./config/IPv4_hwlb_acl.tc --hwlb 1
+
+Run IPv6
+---------
+::
+ Software LoadB
+ --------------
+ cd <samplevnf>/VNFs/vACL/
+ ./build/vACL -p 0x3 -f ./config/IPv6_swlb_acl_1LB_1t.cfg -s ./config/IPv6_swlb_acl.tc
+
+
+ Hardware LoadB
+ --------------
+ cd <samplevnf>/VNFs/vACL/
+ ./build/vACL -p 0x3 -f ./config/IPv6_hwlb_acl_1LB_1t.cfg -s ./config/IPv6_hwlb_acl.tc --hwlb 1
+
+vACL execution on BM & SRIOV:
+--------------------------------
+::
+ To run the VNF, execute the following:
+ samplevnf/VNFs/vACL# ./build/vACL -p 0x3 -f ./config/IPv4_swlb_acl_1LB_1t.cfg -s ./config/ IPv4_swlb_acl.tc
+ Command Line Params:
+ -p PORTMASK: Hexadecimal bitmask of ports to configure
+ -f CONFIG FILE: vACL configuration file
+ -s SCRIPT FILE: vACL script file
+
+vACL execution on OVS:
+-------------------------
+::
+ To run the VNF, execute the following:
+ samplevnf/VNFs/vACL# ./build/vACL -p 0x3 -f ./config/IPv4_swlb_acl_1LB_1t.cfg -s ./config/ IPv4_swlb_acl.tc --disable-hw-csum
+ Command Line Params:
+ -p PORTMASK: Hexadecimal bitmask of ports to configure
+ -f CONFIG FILE: vACL configuration file
+ -s SCRIPT FILE: vACL script file
+--disable-hw-csum :Disable TCP/UDP hw checksum
diff --git a/docs/vACL/README.rst b/docs/vACL/README.rst
new file mode 100644
index 00000000..547d33bc
--- /dev/null
+++ b/docs/vACL/README.rst
@@ -0,0 +1,142 @@
+.. This work is licensed under a creative commons attribution 4.0 international
+.. license.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) opnfv, national center of scientific research "demokritos" and others.
+
+========================================================
+Virtual ACL - vACL
+========================================================
+
+1. Introduction
+==============
+This application implements Access Control List (ACL). ACL is typically
+used for rule based policy enforcement. It restricts access to a destination
+IP address/port based on various header fields, such as source IP address/port,
+destination IP address/port and protocol. It is built on top of DPDK and
+uses the packet framework infrastructure.
+
+
+About DPDK
+----------
+The DPDK IP Pipeline Framework provides a set of libraries to build a pipeline
+application. In this document, vACL will be explained in detail with its own
+building blocks.
+
+This document assumes the reader possesses the knowledge of DPDK concepts and
+packet framework. For more details, read DPDK Getting Started Guide, DPDK
+Programmers Guide, DPDK Sample Applications Guide.
+
+2. Scope
+==========
+This application provides a standalone DPDK based high performance vACL Virtual
+Network Function implementation.
+
+3. Features
+===========
+The vACL VNF currently supports the following functionality:
+ • 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
+ • Hardware and Software Load Balancing
+ • L2L3 stack support for ARP/ICMP handling
+ • ARP (request, response, gratuitous)
+ • ICMP (terminal echo, echo response, passthrough)
+ • ICMPv6 and ND (Neighbor Discovery)
+
+4. High Level Design
+====================
+The ACL Filter performs bulk filtering of incoming packets based on rules in current ruleset,
+discarding any packets not permitted by the rules. The mechanisms needed for building the
+rule database and performing lookups are provided by the DPDK API.
+http://dpdk.org/doc/api/rte__acl_8h.html
+
+The Input FIFO contains all the incoming packets for ACL filtering. Packets will be dequeued
+from the FIFO in bulk for processing by the ACL. Packets will be enqueued to the output FIFO.
+The Input and Output FIFOs will be implemented using DPDK Ring Buffers.
+
+The DPDK ACL example: http://dpdk.org/doc/guides/sample_app_ug/l3_forward_access_ctrl.html
+#figure-ipv4-acl-rule contains a suitable syntax and parser for ACL rules.
+
+===================
+5. Components of vACL
+===================
+In vACL, each component is constructed using packet framework pipelines.
+It includes Rx and Tx Driver, Master pipeline, load balancer pipeline and
+vACL worker pipeline components. A Pipeline framework is a collection of input
+ports, table(s),output ports and actions (functions).
+
+Receive and Transmit Driver
+******************************
+Packets will be received in bulk and provided to LoadBalancer(LB) thread.
+Transimit takes packets from worker threads in a dedicated ring and sent to
+hardware queue.
+
+Master Pipeline
+******************************
+The Master component is part of all the IP Pipeline applications. This component
+does not process any packets and should configure with Core 0, to allow
+other cores for processing of the traffic. This component is responsible for
+ 1. Initializing each component of the Pipeline application in different threads
+ 2. Providing CLI shell for the user control/debug
+ 3. Propagating the commands from user to the corresponding components
+
+ARPICMP Pipeline
+******************************
+This pipeline processes the APRICMP packets.
+
+TXRX Pipelines
+******************************
+The TXTX and RXRX pipelines are pass through pipelines to forward both ingress
+and egress traffic to Loadbalancer. This is required when the Software
+Loadbalancer is used.
+
+Load Balancer Pipeline
+******************************
+The vACL support both hardware and software balancing for load blalcning of
+traffic across multiple VNF threads. The Hardware load balncing require support
+from hardware like Flow Director for steering of packets to application through
+hardware queues.
+
+The Software Load balancer is also supported if hardware loadbalancing can't be
+used for any reason. The TXRX along with LOADB pipeline provides support for
+software load balancing by distributing the flows to Multiple vACL worker
+threads.
+Loadbalancer (HW or SW) distributes traffic based on the 5 tuple (src addr, src
+port, dest addr, dest port and protocol) applying an XOR logic distributing to
+active worker threads, thereby maintaining an affinity of flows to worker
+threads.
+
+vACL Pipeline
+******************************
+The vACL performs the rule-based packet filtering.
+
+vACL Topology:
+------------------------
+::
+ IXIA(Port 0)-->(Port 0)VNF(Port 1)-->(Port 1) IXIA
+ operation:
+ Egress --> The packets sent out from ixia(port 0) will be sent through ACL to ixia(port 1).
+ Igress --> The packets sent out from ixia(port 1) will be sent through ACL to ixia(port 0).
+
+vACL Topology (L4REPLAY):
+------------------------------------
+::
+ IXIA(Port 0)-->(Port 0)VNF(Port 1)-->(Port 0)L4REPLAY
+ operation:
+ Egress --> The packets sent out from ixia will pass through vACL to L3FWD/L4REPLAY.
+ Ingress --> The L4REPLAY upon reception of packets (Private to Public Network),
+ will immediately replay back the traffic to IXIA interface. (Pub -->Priv).
+
+How to run L4Replay:
+--------------------
+::
+ 1. After the installation of samplevnf:
+ go to <samplevnf/VNFs/L4Replay>
+ 2. ./buid/L4replay -c core_mask -n no_of_channels(let it be as 2) -- -p PORT_MASK --config="(port,queue,lcore)"
+ eg: ./L4replay -c 0xf -n 4 -- -p 0x3 --config="(0,0,1)"
+
+6. Installation, Compile and Execution
+-----------------------------------------------------------------
+Plase refer to <samplevnf>/docs/vACL/INSTALL.rst for installation, configuration, compilation
+and execution.
diff --git a/docs/vACL/RELEASE_NOTES.rst b/docs/vACL/RELEASE_NOTES.rst
new file mode 100644
index 00000000..b35dcce4
--- /dev/null
+++ b/docs/vACL/RELEASE_NOTES.rst
@@ -0,0 +1,69 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International
+.. License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) OPNFV, National Center of Scientific Research "Demokritos" and others.
+
+=========================================================
+Virtual ACL - vACL
+=========================================================
+
+1. Introduction
+================
+
+This is a beta release for Sample Virtual ACL VNF.
+This vACL can application can be run independently (refer INSTALL.rst).
+
+2. User Guide
+===============
+Refer to README.rst for further details on vACL, HLD, features supported, test
+plan. For build configurations and execution requisites please refer to
+INSTALL.rst.
+
+3. Feature for this release
+===========================
+The vACL VNF currently supports the following functionality:
+ • 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
+ • Hardware and Software Load Balancing
+ • L2L3 stack support for ARP/ICMP handling
+ • ARP (request, response, gratuitous)
+ • ICMP (terminal echo, echo response, passthrough)
+ • ICMPv6 and ND (Neighbor Discovery)
+
+4. System requirements - OS and kernel version
+==============================================
+This is supported on Ubuntu 14.04 and Ubuntu 16.04 and kernel version less than 4.5
+
+ VNFs on BareMetal support:
+ OS: Ubuntu 14.04 or 16.04 LTS
+ kernel: < 4.5
+ http://releases.ubuntu.com/16.04/
+ Download/Install the image: ubuntu-16.04.1-server-amd64.iso
+
+ VNFs on Standalone Hypervisor
+ HOST OS: Ubuntu 14.04 or 16.04 LTS
+ http://releases.ubuntu.com/16.04/
+ Download/Install the image: ubuntu-16.04.1-server-amd64.iso
+ - OVS (DPDK) - 2.5
+ - kernel: < 4.5
+ - Hypervisor - KVM
+ - VM OS - Ubuntu 16.04/Ubuntu 14.04
+
+5. Known Bugs and limitations
+=============================
+ - Hardware Load Balancer feature is supported on Fortville nic ACL version 4.53 and below.
+ - Hardware Checksum offload is not supported for IPv6 traffic.
+ - vACL on sriov is tested upto 4 threads
+
+6. Future Work
+==============
+Following would be possible enhancements
+ - Performance optimization on different platforms
+
+7. References
+=============
+Following links provides additional information
+ .. _QUICKSTART: http://dpdk.org/doc/guides-16.04/linux_gsg/quick_start.html
+ .. _DPDKGUIDE: http://dpdk.org/doc/guides-16.04/prog_guide/index.html